From 6593159c1e1902072f67a1bf99803616a1a007e7 Mon Sep 17 00:00:00 2001 From: pcg-kk Date: Thu, 23 May 2024 21:51:48 +0200 Subject: [PATCH 1/7] feat: use the metadata with correct language feat: provide a language support for community pages --- .../collection-form.component.ts | 25 ++- .../collection-form/collection-form.models.ts | 78 ++++---- .../collection-page.component.html | 4 +- .../collection-page.component.ts | 6 +- .../community-list.component.html | 8 +- .../community-list.component.ts | 6 +- .../community-form.component.ts | 71 +++---- .../community-form/community-form.models.ts | 48 +++++ .../community-page.component.html | 6 +- .../community-page.component.ts | 6 +- src/app/core/breadcrumbs/dso-name.service.ts | 4 + src/app/core/shared/collection.model.ts | 20 +- src/app/core/shared/community.model.ts | 16 +- .../comcol-form/comcol-form.component.html | 63 ++++++- .../comcol-form/comcol-form.component.scss | 3 + .../comcol-form/comcol-form.component.ts | 174 +++++++++++++----- .../collection-grid-element.component.html | 2 +- .../collection-grid-element.component.ts | 6 +- .../community-grid-element.component.html | 2 +- .../community-grid-element.component.ts | 6 +- ...-search-result-grid-element.component.html | 2 +- ...on-search-result-grid-element.component.ts | 6 +- ...-search-result-grid-element.component.html | 2 +- ...ty-search-result-grid-element.component.ts | 6 +- .../community-list-element.component.html | 4 +- .../community-list-element.component.ts | 2 + src/assets/i18n/en.json5 | 4 + src/assets/i18n/pl.json5 | 2 + 28 files changed, 395 insertions(+), 187 deletions(-) create mode 100644 src/app/community-page/community-form/community-form.models.ts diff --git a/src/app/collection-page/collection-form/collection-form.component.ts b/src/app/collection-page/collection-form/collection-form.component.ts index 0758435db88..9338d744b37 100644 --- a/src/app/collection-page/collection-form/collection-form.component.ts +++ b/src/app/collection-page/collection-form/collection-form.component.ts @@ -1,6 +1,7 @@ import { AsyncPipe, NgClass, + NgForOf, NgIf, } from '@angular/common'; import { @@ -12,6 +13,7 @@ import { SimpleChange, SimpleChanges, } from '@angular/core'; +import { FormsModule } from '@angular/forms'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { DynamicFormControlModel, @@ -66,7 +68,9 @@ import { ComcolPageLogoComponent, NgIf, NgClass, + NgForOf, VarDirective, + FormsModule, ], }) export class CollectionFormComponent extends ComColFormComponent implements OnInit, OnChanges { @@ -101,11 +105,14 @@ export class CollectionFormComponent extends ComColFormComponent imp protected objectCache: ObjectCacheService, protected entityTypeService: EntityTypeDataService, protected chd: ChangeDetectorRef, - protected modalService: NgbModal) { - super(formService, translate, notificationsService, authService, requestService, objectCache, modalService); + protected modalService: NgbModal, + protected cdr: ChangeDetectorRef) { + super(formService, translate, notificationsService, authService, requestService, objectCache, modalService, cdr); } ngOnInit(): void { + this.initializeLanguage(); + if (hasNoValue(this.formModel) && isNotNull(this.dso)) { this.initializeForm(); } @@ -148,11 +155,23 @@ export class CollectionFormComponent extends ComColFormComponent imp } }); - this.formModel = entityTypes.length === 0 ? collectionFormModels : [...collectionFormModels, this.entityTypeSelection]; + this.formModels.set( + this.defaultLanguageCode, + this.getCollectionFormModels(entityTypes, collectionFormModels(this.defaultLanguageCode, true)), + ); + this.languages.forEach(lang => { + this.formModels.set( + lang.code, + this.getCollectionFormModels(entityTypes, collectionFormModels(lang.code, false)), + ); + }); super.ngOnInit(); this.chd.detectChanges(); }); + } + private getCollectionFormModels(entityTypes: ItemType[], dynamicCollectionFormModels: DynamicFormControlModel[]): DynamicFormControlModel[] { + return entityTypes.length === 0 ? dynamicCollectionFormModels : [...dynamicCollectionFormModels, this.entityTypeSelection]; } } diff --git a/src/app/collection-page/collection-form/collection-form.models.ts b/src/app/collection-page/collection-form/collection-form.models.ts index 22998af674e..f0c35270ebb 100644 --- a/src/app/collection-page/collection-form/collection-form.models.ts +++ b/src/app/collection-page/collection-form/collection-form.models.ts @@ -17,41 +17,43 @@ export const collectionFormEntityTypeSelectionConfig: DynamicSelectModelConfig { + return [ + new DynamicInputModel({ + id: `title-${lang}`, + name: 'dc.title', + required: isDefaultLanguage, + validators: { + required: null, + }, + errorMessages: { + required: 'Please enter a name for this title', + }, + }), + new DynamicTextAreaModel({ + id: `description-${lang}`, + name: 'dc.description', + spellCheck: environment.form.spellCheck, + }), + new DynamicTextAreaModel({ + id: `abstract-${lang}`, + name: 'dc.description.abstract', + spellCheck: environment.form.spellCheck, + }), + new DynamicTextAreaModel({ + id: `rights-${lang}`, + name: 'dc.rights', + spellCheck: environment.form.spellCheck, + }), + new DynamicTextAreaModel({ + id: `tableofcontents-${lang}`, + name: 'dc.description.tableofcontents', + spellCheck: environment.form.spellCheck, + }), + new DynamicTextAreaModel({ + id: `license-${lang}`, + name: 'dc.rights.license', + spellCheck: environment.form.spellCheck, + }), + ]; +}; diff --git a/src/app/collection-page/collection-page.component.html b/src/app/collection-page/collection-page.component.html index 4a3e28c6aad..bae9bdb3e45 100644 --- a/src/app/collection-page/collection-page.component.html +++ b/src/app/collection-page/collection-page.component.html @@ -23,12 +23,12 @@ diff --git a/src/app/collection-page/collection-page.component.ts b/src/app/collection-page/collection-page.component.ts index 0d240f5328d..62cdca1c6ff 100644 --- a/src/app/collection-page/collection-page.component.ts +++ b/src/app/collection-page/collection-page.component.ts @@ -12,7 +12,10 @@ import { Router, RouterOutlet, } from '@angular/router'; -import { TranslateModule } from '@ngx-translate/core'; +import { + TranslateModule, + TranslateService, +} from '@ngx-translate/core'; import { Observable } from 'rxjs'; import { filter, @@ -103,6 +106,7 @@ export class CollectionPageComponent implements OnInit { protected authService: AuthService, protected authorizationDataService: AuthorizationDataService, public dsoNameService: DSONameService, + public translateService: TranslateService, ) { } diff --git a/src/app/community-list-page/community-list/community-list.component.html b/src/app/community-list-page/community-list/community-list.component.html index 82238ddd0d1..84eeb6a1b58 100644 --- a/src/app/community-list-page/community-list/community-list.component.html +++ b/src/app/community-list-page/community-list/community-list.component.html @@ -46,12 +46,12 @@
-
+
- {{node.payload.shortDescription}} + {{shorDescription}}
@@ -77,12 +77,12 @@
-
+
- {{node.payload.shortDescription}} + {{node.payload.shortDescription(translateService.currentLang)}}
diff --git a/src/app/community-list-page/community-list/community-list.component.ts b/src/app/community-list-page/community-list/community-list.component.ts index 5819471d7e5..dea288dfd71 100644 --- a/src/app/community-list-page/community-list/community-list.component.ts +++ b/src/app/community-list-page/community-list/community-list.component.ts @@ -13,7 +13,10 @@ import { OnInit, } from '@angular/core'; import { RouterLink } from '@angular/router'; -import { TranslateModule } from '@ngx-translate/core'; +import { + TranslateModule, + TranslateService, +} from '@ngx-translate/core'; import { take } from 'rxjs/operators'; import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; @@ -59,6 +62,7 @@ export class CommunityListComponent implements OnInit, OnDestroy { constructor( protected communityListService: CommunityListService, public dsoNameService: DSONameService, + public translateService: TranslateService, ) { this.paginationConfig = new FindListOptions(); this.paginationConfig.elementsPerPage = 2; diff --git a/src/app/community-page/community-form/community-form.component.ts b/src/app/community-page/community-form/community-form.component.ts index d32d9e408f2..e578465053a 100644 --- a/src/app/community-page/community-form/community-form.component.ts +++ b/src/app/community-page/community-form/community-form.component.ts @@ -1,28 +1,26 @@ import { AsyncPipe, NgClass, + NgForOf, NgIf, } from '@angular/common'; import { + ChangeDetectorRef, Component, Input, OnChanges, + OnInit, SimpleChange, SimpleChanges, } from '@angular/core'; +import { FormsModule } from '@angular/forms'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { - DynamicFormControlModel, - DynamicFormService, - DynamicInputModel, - DynamicTextAreaModel, -} from '@ng-dynamic-forms/core'; +import { DynamicFormService } from '@ng-dynamic-forms/core'; import { TranslateModule, TranslateService, } from '@ngx-translate/core'; -import { environment } from '../../../environments/environment'; import { AuthService } from '../../core/auth/auth.service'; import { ObjectCacheService } from '../../core/cache/object-cache.service'; import { CommunityDataService } from '../../core/data/community-data.service'; @@ -34,6 +32,7 @@ import { FormComponent } from '../../shared/form/form.component'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { UploaderComponent } from '../../shared/upload/uploader/uploader.component'; import { VarDirective } from '../../shared/utils/var.directive'; +import { communityFormModels } from './community-form.models'; /** * Form used for creating and editing communities @@ -51,10 +50,12 @@ import { VarDirective } from '../../shared/utils/var.directive'; ComcolPageLogoComponent, NgIf, NgClass, + NgForOf, VarDirective, + FormsModule, ], }) -export class CommunityFormComponent extends ComColFormComponent implements OnChanges { +export class CommunityFormComponent extends ComColFormComponent implements OnInit, OnChanges { /** * @type {Community} A new community when a community is being created, an existing Input community when a community is being edited */ @@ -65,44 +66,6 @@ export class CommunityFormComponent extends ComColFormComponent imple */ type = Community.type; - /** - * The dynamic form fields used for creating/editing a community - * @type {(DynamicInputModel | DynamicTextAreaModel)[]} - */ - formModel: DynamicFormControlModel[] = [ - new DynamicInputModel({ - id: 'title', - name: 'dc.title', - required: true, - validators: { - required: null, - }, - errorMessages: { - required: 'Please enter a name for this title', - }, - }), - new DynamicTextAreaModel({ - id: 'description', - name: 'dc.description', - spellCheck: environment.form.spellCheck, - }), - new DynamicTextAreaModel({ - id: 'abstract', - name: 'dc.description.abstract', - spellCheck: environment.form.spellCheck, - }), - new DynamicTextAreaModel({ - id: 'rights', - name: 'dc.rights', - spellCheck: environment.form.spellCheck, - }), - new DynamicTextAreaModel({ - id: 'tableofcontents', - name: 'dc.description.tableofcontents', - spellCheck: environment.form.spellCheck, - }), - ]; - public constructor(protected formService: DynamicFormService, protected translate: TranslateService, protected notificationsService: NotificationsService, @@ -110,8 +73,20 @@ export class CommunityFormComponent extends ComColFormComponent imple protected dsoService: CommunityDataService, protected requestService: RequestService, protected objectCache: ObjectCacheService, - protected modalService: NgbModal) { - super(formService, translate, notificationsService, authService, requestService, objectCache, modalService); + protected modalService: NgbModal, + protected cdr: ChangeDetectorRef) { + super(formService, translate, notificationsService, authService, requestService, objectCache, modalService, cdr); + } + + ngOnInit() { + this.initializeLanguage(); + + this.formModels.set(this.defaultLanguageCode, communityFormModels(this.defaultLanguageCode, true)); + this.languages.forEach(lang => { + this.formModels.set(lang.code, communityFormModels(lang.code, false)); + }); + + super.ngOnInit(); } ngOnChanges(changes: SimpleChanges) { diff --git a/src/app/community-page/community-form/community-form.models.ts b/src/app/community-page/community-form/community-form.models.ts new file mode 100644 index 00000000000..8d0949da15d --- /dev/null +++ b/src/app/community-page/community-form/community-form.models.ts @@ -0,0 +1,48 @@ +import { + DynamicFormControlModel, + DynamicInputModel, + DynamicTextAreaModel, +} from '@ng-dynamic-forms/core'; + +import { environment } from '../../../environments/environment'; + + +/** + * The dynamic form fields used for creating/editing a community + * @type {(DynamicInputModel | DynamicTextAreaModel)[]} + */ +export const communityFormModels = (lang: string, isDefaultLanguage: boolean): DynamicFormControlModel[] => { + return [ + new DynamicInputModel({ + id: `title-${lang}`, + name: 'dc.title', + required: isDefaultLanguage, + validators: { + required: null, + }, + errorMessages: { + required: 'Please enter a name for this title', + }, + }), + new DynamicTextAreaModel({ + id: `description-${lang}`, + name: 'dc.description', + spellCheck: environment.form.spellCheck, + }), + new DynamicTextAreaModel({ + id: `abstract-${lang}`, + name: 'dc.description.abstract', + spellCheck: environment.form.spellCheck, + }), + new DynamicTextAreaModel({ + id: `rights-${lang}`, + name: 'dc.rights', + spellCheck: environment.form.spellCheck, + }), + new DynamicTextAreaModel({ + id: `tableofcontents-${lang}`, + name: 'dc.description.tableofcontents', + spellCheck: environment.form.spellCheck, + }), + ]; +}; diff --git a/src/app/community-page/community-page.component.html b/src/app/community-page/community-page.component.html index a695e2019a3..7707cb61623 100644 --- a/src/app/community-page/community-page.component.html +++ b/src/app/community-page/community-page.component.html @@ -13,10 +13,10 @@ - + - @@ -32,7 +32,7 @@
- +
diff --git a/src/app/community-page/community-page.component.ts b/src/app/community-page/community-page.component.ts index d04ecbee190..8681cf8151b 100644 --- a/src/app/community-page/community-page.component.ts +++ b/src/app/community-page/community-page.component.ts @@ -13,7 +13,10 @@ import { RouterModule, RouterOutlet, } from '@angular/router'; -import { TranslateModule } from '@ngx-translate/core'; +import { + TranslateModule, + TranslateService, +} from '@ngx-translate/core'; import { Observable } from 'rxjs'; import { filter, @@ -103,6 +106,7 @@ export class CommunityPageComponent implements OnInit { private authService: AuthService, private authorizationDataService: AuthorizationDataService, public dsoNameService: DSONameService, + public translateService: TranslateService, ) { } diff --git a/src/app/core/breadcrumbs/dso-name.service.ts b/src/app/core/breadcrumbs/dso-name.service.ts index 988141209f4..b86f0efc0c5 100644 --- a/src/app/core/breadcrumbs/dso-name.service.ts +++ b/src/app/core/breadcrumbs/dso-name.service.ts @@ -78,6 +78,10 @@ export class DSONameService { if (hasValue(match)) { name = this.factories[match](dso); } + // If name is empty we try to get a name from different metadata + if (isEmpty(name) && dso.metadata) { + name = dso.firstMetadataValue('dc.title', { language: this.translateService.currentLang }); + } if (isEmpty(name)) { name = this.factories.Default(dso); } diff --git a/src/app/core/shared/collection.model.ts b/src/app/core/shared/collection.model.ts index b929e54ccb4..72bcb591f77 100644 --- a/src/app/core/shared/collection.model.ts +++ b/src/app/core/shared/collection.model.ts @@ -94,40 +94,40 @@ export class Collection extends DSpaceObject implements ChildHALResource, Handle * The introductory text of this Collection * Corresponds to the metadata field dc.description */ - get introductoryText(): string { - return this.firstMetadataValue('dc.description'); + public introductoryText(language: string): string { + return this.firstMetadataValue('dc.description', { language }); } /** * The short description: HTML * Corresponds to the metadata field dc.description.abstract */ - get shortDescription(): string { - return this.firstMetadataValue('dc.description.abstract'); + public shortDescription(language: string): string { + return this.firstMetadataValue('dc.description.abstract', { language }); } /** * The copyright text of this Collection * Corresponds to the metadata field dc.rights */ - get copyrightText(): string { - return this.firstMetadataValue('dc.rights'); + public copyrightText(language: string): string { + return this.firstMetadataValue('dc.rights', { language }); } /** * The license of this Collection * Corresponds to the metadata field dc.rights.license */ - get dcLicense(): string { - return this.firstMetadataValue('dc.rights.license'); + public dcLicense(language: string): string { + return this.firstMetadataValue('dc.rights.license', { language }); } /** * The sidebar text of this Collection * Corresponds to the metadata field dc.description.tableofcontents */ - get sidebarText(): string { - return this.firstMetadataValue('dc.description.tableofcontents'); + public sidebarText(language: string): string { + return this.firstMetadataValue('dc.description.tableofcontents', { language }); } getParentLinkKey(): keyof this['_links'] { diff --git a/src/app/core/shared/community.model.ts b/src/app/core/shared/community.model.ts index 31b00398ffb..90a24ce3191 100644 --- a/src/app/core/shared/community.model.ts +++ b/src/app/core/shared/community.model.ts @@ -83,32 +83,32 @@ export class Community extends DSpaceObject implements ChildHALResource, HandleO * The introductory text of this Community * Corresponds to the metadata field dc.description */ - get introductoryText(): string { - return this.firstMetadataValue('dc.description'); + public introductoryText(language: string): string { + return this.firstMetadataValue('dc.description', { language }); } /** * The short description: HTML * Corresponds to the metadata field dc.description.abstract */ - get shortDescription(): string { - return this.firstMetadataValue('dc.description.abstract'); + public shortDescription(language: string): string { + return this.firstMetadataValue('dc.description.abstract', { language }); } /** * The copyright text of this Community * Corresponds to the metadata field dc.rights */ - get copyrightText(): string { - return this.firstMetadataValue('dc.rights'); + public copyrightText(language: string): string { + return this.firstMetadataValue('dc.rights', { language }); } /** * The sidebar text of this Community * Corresponds to the metadata field dc.description.tableofcontents */ - get sidebarText(): string { - return this.firstMetadataValue('dc.description.tableofcontents'); + public sidebarText(language: string): string { + return this.firstMetadataValue('dc.description.tableofcontents', { language }); } getParentLinkKey(): keyof this['_links'] { diff --git a/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.html b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.html index 1d752869e5e..4484f367bdc 100644 --- a/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.html +++ b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.html @@ -33,13 +33,58 @@ - - - +
+
+
+ +
+
+
+ +
+
+
+ +
+ +
+ + +
+ +
+
+ +
+ +
+ + + + + +
+
+ +
+ +
+
+ + +
+
diff --git a/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.scss b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.scss index e69de29bb2d..7e1f2213861 100644 --- a/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.scss +++ b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.scss @@ -0,0 +1,3 @@ +.form-control { + margin-top: 2px; +} diff --git a/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts index 0c80ce0d1d9..5d2bcbbf0c4 100644 --- a/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts +++ b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts @@ -1,9 +1,11 @@ import { AsyncPipe, NgClass, + NgForOf, NgIf, } from '@angular/common'; import { + ChangeDetectorRef, Component, EventEmitter, Input, @@ -12,7 +14,10 @@ import { Output, ViewChild, } from '@angular/core'; -import { UntypedFormGroup } from '@angular/forms'; +import { + FormsModule, + ReactiveFormsModule, +} from '@angular/forms'; import { NgbModal, NgbModalRef, @@ -27,6 +32,7 @@ import { TranslateService, } from '@ngx-translate/core'; import { Operation } from 'fast-json-patch'; +import { ReplaceOperation } from 'fast-json-patch/module/core'; import { FileUploader } from 'ng2-file-upload'; import { BehaviorSubject, @@ -40,6 +46,8 @@ import { take, } from 'rxjs/operators'; +import { LangConfig } from '../../../../../config/lang-config.interface'; +import { environment } from '../../../../../environments/environment'; import { AuthService } from '../../../../core/auth/auth.service'; import { ObjectCacheService } from '../../../../core/cache/object-cache.service'; import { ComColDataService } from '../../../../core/data/comcol-data.service'; @@ -83,7 +91,10 @@ import { ComcolPageLogoComponent } from '../../comcol-page-logo/comcol-page-logo ComcolPageLogoComponent, NgIf, NgClass, + NgForOf, VarDirective, + ReactiveFormsModule, + FormsModule, ], standalone: true, }) @@ -122,12 +133,32 @@ export class ComColFormComponent implements On /** * The form model that represents the fields in the form */ - formModel: DynamicFormControlModel[]; + formModels: Map = new Map(); + + /** + * The form for the selected current language + */ + currentAlternativeForm: DynamicFormControlModel[]; + + /** + * The default language from config + */ + defaultLanguageCode: string; + + /** + * The current page language string + */ + defaultLanguage: string | null; /** - * The form group of this form + * The current page outlet string */ - formGroup: UntypedFormGroup; + currentLanguageCode: string | null; + + /** + * All languages used by application + */ + languages: LangConfig[]; /** * The uploader configuration options @@ -184,21 +215,27 @@ export class ComColFormComponent implements On protected authService: AuthService, protected requestService: RequestService, protected objectCache: ObjectCacheService, - protected modalService: NgbModal){ + protected modalService: NgbModal, + protected cdr: ChangeDetectorRef){ } ngOnInit(): void { this.uploadFilesOptions.autoUpload = !this.isCreation; - if (hasValue(this.formModel)) { - this.formModel.forEach( - (fieldModel: DynamicInputModel) => { - fieldModel.value = this.dso.firstMetadataValue(fieldModel.name); - }, - ); - this.formGroup = this.formService.createFormGroup(this.formModel); + if (this.formModels.size > 0) { + this.formModels.forEach((formModel, language) => { + formModel.forEach( + (fieldModel: DynamicInputModel) => { + fieldModel.value = this.dso.firstMetadataValue(fieldModel.name, { language }); + }, + ); + }); this.updateFieldTranslations(); + if (this.currentLanguageCode) { + this.currentAlternativeForm = this.formModels.get(this.currentLanguageCode); + } + this.translate.onLangChange .subscribe(() => { this.updateFieldTranslations(); @@ -237,16 +274,46 @@ export class ComColFormComponent implements On */ onSubmit() { const formMetadata = {} as MetadataMap; - this.formModel.forEach((fieldModel: DynamicInputModel) => { - const value: MetadataValue = { - value: fieldModel.value as string, - language: null, - } as any; - if (formMetadata.hasOwnProperty(fieldModel.name)) { - formMetadata[fieldModel.name].push(value); - } else { - formMetadata[fieldModel.name] = [value]; - } + const operations: Map> = new Map(); + + this.formModels.forEach((formModel, language) => { + formModel.forEach( + (fieldModel: DynamicInputModel) => { + const value: MetadataValue = { + value: fieldModel.value as string, + language, + } as any; + + if (formMetadata.hasOwnProperty(fieldModel.name)) { + formMetadata[fieldModel.name].push(value); + } else { + formMetadata[fieldModel.name] = [value]; + } + + const key = `/metadata/${fieldModel.name}`; + + const keyExistAndAtLeastOneValueIsNotNull: boolean = (fieldModel.value !== null || this.dso.firstMetadataValue(fieldModel.name, { language }) !== null); + + if ( keyExistAndAtLeastOneValueIsNotNull) { + if (operations.has(key)) { + const operation: Operation = operations.get(key); + operation.value.push({ + value: fieldModel.value, + language, + }); + } else { + operations.set(key, { + op: 'replace', + path: key, + value: [{ + value: fieldModel.value as string, + language, + }], + }); + } + } + }, + ); }); const updatedDSO = Object.assign({}, this.dso, { @@ -257,49 +324,58 @@ export class ComColFormComponent implements On type: Community.type, }); - const operations: Operation[] = []; - this.formModel.forEach((fieldModel: DynamicInputModel) => { - if (fieldModel.value !== this.dso.firstMetadataValue(fieldModel.name)) { - operations.push({ - op: 'replace', - path: `/metadata/${fieldModel.name}`, - value: { - value: fieldModel.value, - language: null, - }, - }); - } - }); - if (this.isCreation) { this.submitForm.emit({ dso: updatedDSO, uploader: hasValue(this.uploaderComponent) ? this.uploaderComponent.uploader : undefined, - operations: operations, + operations: [...operations.values()], }); } else { this.submitForm.emit({ dso: updatedDSO, - operations: operations, + operations: [...operations.values()], }); } } + changeLanguage() { + // Because the ds-form require destroy (we cannot change formModel without destroy) we need to remove the component from template + this.currentAlternativeForm = null; + // Detect changes push the form to rerender, that cause the destroy of the form + this.cdr.detectChanges(); + // And then we can add a component again by providing a new language form + this.currentAlternativeForm = this.formModels.get(this.currentLanguageCode); + } + + /** + * Initialize language method that provide all necessary information for creation, validation, labaling & form submission + */ + initializeLanguage() { + this.defaultLanguageCode = environment.defaultLanguage; + this.defaultLanguage = environment.languages.find(lang => lang.code === this.defaultLanguageCode).label; + + this.languages = environment.languages.filter(lang => lang.code !== this.defaultLanguageCode); + this.currentLanguageCode = this.languages.length > 0 ? this.languages[0].code : null; + } + /** * Used the update translations of errors and labels on init and on language change */ private updateFieldTranslations() { - this.formModel.forEach( - (fieldModel: DynamicInputModel) => { - fieldModel.label = this.translate.instant(this.type.value + this.LABEL_KEY_PREFIX + fieldModel.id); - if (isNotEmpty(fieldModel.validators)) { - fieldModel.errorMessages = {}; - Object.keys(fieldModel.validators).forEach((key) => { - fieldModel.errorMessages[key] = this.translate.instant(this.type.value + this.ERROR_KEY_PREFIX + fieldModel.id + '.' + key); - }); - } - }, - ); + [this.defaultLanguageCode, ...this.languages.map(lang => lang.code)].forEach(lang => { + const langFormModel = this.formModels.get(lang); + langFormModel.forEach( + (fieldModel: DynamicInputModel) => { + fieldModel.label = this.translate.instant(this.type.value + this.LABEL_KEY_PREFIX + fieldModel.id.replace(`-${lang}`, '')); + if (isNotEmpty(fieldModel.validators)) { + fieldModel.errorMessages = {}; + Object.keys(fieldModel.validators).forEach((key) => { + fieldModel.errorMessages[key] = this.translate.instant(this.type.value + this.ERROR_KEY_PREFIX + fieldModel.id.replace(`-${lang}`, '') + '.' + key); + }); + } + }, + ); + }); } /** diff --git a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.html b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.html index 6b5cb23252a..ef6f6f5ee0e 100644 --- a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.html +++ b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.html @@ -9,7 +9,7 @@

{{ dsoNameService.getName(object) }}

-

{{object.shortDescription}}

+

{{shortDescription}}

diff --git a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts index 178c1bd5b9b..e09a9022076 100644 --- a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts +++ b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts @@ -7,7 +7,10 @@ import { Input, } from '@angular/core'; import { RouterLink } from '@angular/router'; -import { TranslateModule } from '@ngx-translate/core'; +import { + TranslateModule, + TranslateService, +} from '@ngx-translate/core'; import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; import { LinkService } from '../../../core/cache/builders/link.service'; @@ -41,6 +44,7 @@ export class CollectionGridElementComponent extends AbstractListableElementCompo constructor( public dsoNameService: DSONameService, private linkService: LinkService, + public translateService: TranslateService, ) { super(dsoNameService); } diff --git a/src/app/shared/object-grid/community-grid-element/community-grid-element.component.html b/src/app/shared/object-grid/community-grid-element/community-grid-element.component.html index c00c26d3fe6..d0c876ae294 100644 --- a/src/app/shared/object-grid/community-grid-element/community-grid-element.component.html +++ b/src/app/shared/object-grid/community-grid-element/community-grid-element.component.html @@ -9,7 +9,7 @@

{{ dsoNameService.getName(object) }}

-

{{object.shortDescription}}

+

{{shortDescription}}

diff --git a/src/app/shared/object-grid/community-grid-element/community-grid-element.component.ts b/src/app/shared/object-grid/community-grid-element/community-grid-element.component.ts index c134af774e3..c8bd70e20ae 100644 --- a/src/app/shared/object-grid/community-grid-element/community-grid-element.component.ts +++ b/src/app/shared/object-grid/community-grid-element/community-grid-element.component.ts @@ -7,7 +7,10 @@ import { Input, } from '@angular/core'; import { RouterLink } from '@angular/router'; -import { TranslateModule } from '@ngx-translate/core'; +import { + TranslateModule, + TranslateService, +} from '@ngx-translate/core'; import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; import { LinkService } from '../../../core/cache/builders/link.service'; @@ -40,6 +43,7 @@ export class CommunityGridElementComponent extends AbstractListableElementCompon constructor( public dsoNameService: DSONameService, private linkService: LinkService, + public translateService: TranslateService, ) { super(dsoNameService); } diff --git a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.html b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.html index 4a097b46dc0..69d59173958 100644 --- a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.html +++ b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.html @@ -10,7 +10,7 @@

{{ dsoNameService.getName(dso) }}

-

{{dso.shortDescription}}

+

{{shortDescription}}

diff --git a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts index 8700541a6ce..e1a3bcaa585 100644 --- a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts @@ -7,7 +7,10 @@ import { Input, } from '@angular/core'; import { RouterLink } from '@angular/router'; -import { TranslateModule } from '@ngx-translate/core'; +import { + TranslateModule, + TranslateService, +} from '@ngx-translate/core'; import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; import { LinkService } from '../../../../core/cache/builders/link.service'; @@ -42,6 +45,7 @@ export class CollectionSearchResultGridElementComponent extends SearchResultGrid constructor( public dsoNameService: DSONameService, + public translateService: TranslateService, private linkService: LinkService, protected truncatableService: TruncatableService, protected bitstreamDataService: BitstreamDataService, diff --git a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.html b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.html index 63b61396132..9d6fe7ed6ad 100644 --- a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.html +++ b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.html @@ -10,7 +10,7 @@

{{ dsoNameService.getName(dso) }}

-

{{dso.shortDescription}}

+

{{shortDescription}}

diff --git a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.ts index e83182b33af..73c8b0fc99b 100644 --- a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.ts @@ -7,7 +7,10 @@ import { Input, } from '@angular/core'; import { RouterLink } from '@angular/router'; -import { TranslateModule } from '@ngx-translate/core'; +import { + TranslateModule, + TranslateService, +} from '@ngx-translate/core'; import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; import { LinkService } from '../../../../core/cache/builders/link.service'; @@ -45,6 +48,7 @@ export class CommunitySearchResultGridElementComponent extends SearchResultGridE constructor( public dsoNameService: DSONameService, + public translateService: TranslateService, private linkService: LinkService, protected truncatableService: TruncatableService, protected bitstreamDataService: BitstreamDataService, diff --git a/src/app/shared/object-list/community-list-element/community-list-element.component.html b/src/app/shared/object-list/community-list-element/community-list-element.component.html index d63abd96725..ab4a67c4c71 100644 --- a/src/app/shared/object-list/community-list-element/community-list-element.component.html +++ b/src/app/shared/object-list/community-list-element/community-list-element.component.html @@ -8,6 +8,6 @@   {{object.archivedItemsCount}}
-
- {{object.shortDescription}} +
+ {{shorDescription}}
diff --git a/src/app/shared/object-list/community-list-element/community-list-element.component.ts b/src/app/shared/object-list/community-list-element/community-list-element.component.ts index adde4420ec8..b343992207c 100644 --- a/src/app/shared/object-list/community-list-element/community-list-element.component.ts +++ b/src/app/shared/object-list/community-list-element/community-list-element.component.ts @@ -1,6 +1,7 @@ import { NgIf } from '@angular/common'; import { Component } from '@angular/core'; import { RouterLink } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; import { Community } from '../../../core/shared/community.model'; @@ -23,6 +24,7 @@ export class CommunityListElementComponent extends AbstractListableElementCompon constructor( public dsoNameService: DSONameService, + public translateService: TranslateService, ) { super(dsoNameService); } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 7da72f0fb3a..b634cede6bc 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1148,6 +1148,10 @@ "collection.edit.tabs.mapper.head": "Item Mapper", + "collection.edit.tabs.multilingual-editor": "Multilingual content editor", + + "collection.edit.tabs.default-language": "Default language", + "collection.edit.tabs.item-mapper.title": "Collection Edit - Item Mapper", "collection.edit.item-mapper.cancel": "Cancel", diff --git a/src/assets/i18n/pl.json5 b/src/assets/i18n/pl.json5 index f90855f9a67..7fb01b91b64 100644 --- a/src/assets/i18n/pl.json5 +++ b/src/assets/i18n/pl.json5 @@ -755,6 +755,8 @@ "collection.edit.head": "Edytuj kolekcję", "collection.edit.breadcrumbs": "Edytuj kolekcję", "collection.edit.tabs.mapper.head": "Item Mapper", + "collection.edit.tabs.multilingual-editor": "Wielojęzyczny edytor", + "collection.edit.tabs.default-language": "Język podstawowy", "collection.edit.tabs.item-mapper.title": "Edytuj kolekcję - Item Mapper", "collection.edit.item-mapper.cancel": "Anuluj", "collection.edit.item-mapper.collection": "Kolekcja: \"{{name}}\"", From 76e64ec8f85178cdc4e34897f2b834da4b52a904 Mon Sep 17 00:00:00 2001 From: pcg-kk Date: Fri, 24 May 2024 21:59:05 +0200 Subject: [PATCH 2/7] feat: next test fix feat: first test fix feat: fix unit --- .../comcol-form/comcol-form.component.spec.ts | 64 +++++++++++-------- .../comcol-form/comcol-form.component.ts | 2 +- .../shared/mocks/translate.service.mock.ts | 12 ++++ .../collection-list-element.component.html | 4 +- .../collection-list-element.component.spec.ts | 3 + .../collection-list-element.component.ts | 11 +++- .../community-list-element.component.spec.ts | 3 + ...-search-result-list-element.component.html | 2 +- ...arch-result-list-element.component.spec.ts | 3 + ...on-search-result-list-element.component.ts | 15 +++++ ...-search-result-list-element.component.html | 2 +- ...arch-result-list-element.component.spec.ts | 3 + ...ty-search-result-list-element.component.ts | 16 +++++ 13 files changed, 109 insertions(+), 31 deletions(-) diff --git a/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.spec.ts b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.spec.ts index 2035c313fe6..30df19b3a79 100644 --- a/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.spec.ts +++ b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.spec.ts @@ -16,7 +16,10 @@ import { DynamicFormService, DynamicInputModel, } from '@ng-dynamic-forms/core'; -import { TranslateModule } from '@ngx-translate/core'; +import { + TranslateModule, + TranslateService, +} from '@ngx-translate/core'; import { Operation } from 'fast-json-patch'; import { of as observableOf } from 'rxjs'; @@ -28,6 +31,7 @@ import { Community } from '../../../../core/shared/community.model'; import { hasValue } from '../../../empty.util'; import { FormComponent } from '../../../form/form.component'; import { AuthServiceMock } from '../../../mocks/auth.service.mock'; +import { translateServiceStub } from '../../../mocks/translate.service.mock'; import { NotificationsService } from '../../../notifications/notifications.service'; import { createSuccessfulRemoteDataObject$ } from '../../../remote-data.utils'; import { NotificationsServiceStub } from '../../../testing/notifications-service.stub'; @@ -55,8 +59,8 @@ describe('ComColFormComponent', () => { const dcTitle = 'dc.title'; const dcAbstract = 'dc.description.abstract'; - const abstractMD = { [dcAbstract]: [{ value: 'Community description', language: null }] }; - const newTitleMD = { [dcTitle]: [{ value: 'New Community Title', language: null }] }; + const abstractMD = { [dcAbstract]: [{ value: 'Community description', language: 'en_US' }] }; + const newTitleMD = { [dcTitle]: [{ value: 'New Community Title', language: 'en_US' }] }; const formModel = [ new DynamicInputModel({ id: 'title', @@ -103,6 +107,7 @@ describe('ComColFormComponent', () => { { provide: AuthService, useValue: new AuthServiceMock() }, { provide: RequestService, useValue: requestServiceStub }, { provide: ObjectCacheService, useValue: objectCacheStub }, + { provide: TranslateService, useValue: translateServiceStub }, ], schemas: [NO_ERRORS_SCHEMA], }) @@ -132,7 +137,7 @@ describe('ComColFormComponent', () => { describe('onSubmit', () => { beforeEach(() => { spyOn(comp.submitForm, 'emit'); - comp.formModel = formModel; + comp.formModels.set('en_US', formModel); }); it('should emit the new version of the community', () => { @@ -143,37 +148,38 @@ describe('ComColFormComponent', () => { { op: 'replace', path: '/metadata/dc.title', - value: { + value: [{ value: 'New Community Title', - language: null, - }, + language: 'en_US', + }], }, { op: 'replace', path: '/metadata/dc.description.abstract', - value: { + value: [{ value: 'Community description', - language: null, - }, + language: 'en_US', + }], }, ]; + const expectedDso = Object.assign({}, comp.dso, { + metadata: { + 'dc.title': [{ + value: 'New Community Title', + language: 'en_US', + }], + 'dc.description.abstract': [{ + value: 'Community description', + language: 'en_US', + }], + }, + type: Community.type, + }); + expect(comp.submitForm.emit).toHaveBeenCalledWith( { - dso: Object.assign({}, comp.dso, { - metadata: { - 'dc.title': [{ - value: 'New Community Title', - language: null, - }], - 'dc.description.abstract': [{ - value: 'Community description', - language: null, - }], - }, - type: Community.type, - }, - ), + dso: expectedDso, operations: operations, }, ); @@ -314,8 +320,16 @@ describe('ComColFormComponent', () => { function initComponent(dso: Community) { fixture = TestBed.createComponent(ComColFormComponent); comp = fixture.componentInstance; - comp.formModel = []; + comp.formModels.set('en_US', formModel); + comp.defaultLanguageCode = 'en_US'; comp.dso = dso; + comp.dso.firstMetadataValue = (name, language) => { + if (name === 'dc.title') { + return newTitleMD[dcTitle][0].value; + } else if (name === 'dc.description.abstract') { + return abstractMD[dcAbstract][0].value; + } + }; (comp as any).type = Community.type; comp.uploaderComponent = { uploader: {} } as any; diff --git a/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts index 5d2bcbbf0c4..82fde741ca6 100644 --- a/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts +++ b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts @@ -158,7 +158,7 @@ export class ComColFormComponent implements On /** * All languages used by application */ - languages: LangConfig[]; + languages: LangConfig[] = []; /** * The uploader configuration options diff --git a/src/app/shared/mocks/translate.service.mock.ts b/src/app/shared/mocks/translate.service.mock.ts index ecb87007e26..bae94be0452 100644 --- a/src/app/shared/mocks/translate.service.mock.ts +++ b/src/app/shared/mocks/translate.service.mock.ts @@ -1,4 +1,6 @@ +import { EventEmitter } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; +import { of } from 'rxjs'; export function getMockTranslateService(): TranslateService { return jasmine.createSpyObj('translateService', { @@ -6,5 +8,15 @@ export function getMockTranslateService(): TranslateService { use: jasmine.createSpy('use'), instant: jasmine.createSpy('instant'), setDefaultLang: jasmine.createSpy('setDefaultLang'), + currentLang: 'en_US', }); } + +export const translateServiceStub = { + get: () => of('translated-text'), + instant: () => 'translated-text', + onLangChange: new EventEmitter(), + onTranslationChange: new EventEmitter(), + onDefaultLangChange: new EventEmitter(), + currentLang: 'en_US', +}; diff --git a/src/app/shared/object-list/collection-list-element/collection-list-element.component.html b/src/app/shared/object-list/collection-list-element/collection-list-element.component.html index 1c4f68fbcce..e349d91e82d 100644 --- a/src/app/shared/object-list/collection-list-element/collection-list-element.component.html +++ b/src/app/shared/object-list/collection-list-element/collection-list-element.component.html @@ -8,6 +8,6 @@   {{object.archivedItemsCount}}
-
- {{object.shortDescription}} +
+ {{shortDescription}}
diff --git a/src/app/shared/object-list/collection-list-element/collection-list-element.component.spec.ts b/src/app/shared/object-list/collection-list-element/collection-list-element.component.spec.ts index 6d360c3f5e2..ff6f67bb059 100644 --- a/src/app/shared/object-list/collection-list-element/collection-list-element.component.spec.ts +++ b/src/app/shared/object-list/collection-list-element/collection-list-element.component.spec.ts @@ -9,10 +9,12 @@ import { } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { ActivatedRoute } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; import { Collection } from '../../../core/shared/collection.model'; import { DSONameServiceMock } from '../../mocks/dso-name.service.mock'; +import { translateServiceStub } from '../../mocks/translate.service.mock'; import { ActivatedRouteStub } from '../../testing/active-router.stub'; import { CollectionListElementComponent } from './collection-list-element.component'; @@ -72,6 +74,7 @@ describe('CollectionListElementComponent', () => { { provide: DSONameService, useValue: new DSONameServiceMock() }, { provide: 'objectElementProvider', useValue: (mockCollectionWithAbstract) }, { provide: ActivatedRoute, useValue: new ActivatedRouteStub() }, + { provide: TranslateService, useValue: translateServiceStub }, ], schemas: [NO_ERRORS_SCHEMA], }).overrideComponent(CollectionListElementComponent, { diff --git a/src/app/shared/object-list/collection-list-element/collection-list-element.component.ts b/src/app/shared/object-list/collection-list-element/collection-list-element.component.ts index c03598d9547..360ad015a36 100644 --- a/src/app/shared/object-list/collection-list-element/collection-list-element.component.ts +++ b/src/app/shared/object-list/collection-list-element/collection-list-element.component.ts @@ -1,7 +1,9 @@ import { NgIf } from '@angular/common'; import { Component } from '@angular/core'; import { RouterLink } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; import { Collection } from '../../../core/shared/collection.model'; import { ViewMode } from '../../../core/shared/view-mode.model'; import { listableObjectComponent } from '../../object-collection/shared/listable-object/listable-object.decorator'; @@ -18,4 +20,11 @@ import { AbstractListableElementComponent } from '../../object-collection/shared * Component representing list element for a collection */ @listableObjectComponent(Collection, ViewMode.ListElement) -export class CollectionListElementComponent extends AbstractListableElementComponent {} +export class CollectionListElementComponent extends AbstractListableElementComponent { + constructor( + public dsoNameService: DSONameService, + public translateService: TranslateService, + ) { + super(dsoNameService); + } +} diff --git a/src/app/shared/object-list/community-list-element/community-list-element.component.spec.ts b/src/app/shared/object-list/community-list-element/community-list-element.component.spec.ts index cb34d6719c1..7322ca03c69 100644 --- a/src/app/shared/object-list/community-list-element/community-list-element.component.spec.ts +++ b/src/app/shared/object-list/community-list-element/community-list-element.component.spec.ts @@ -9,10 +9,12 @@ import { } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { ActivatedRoute } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; import { Community } from '../../../core/shared/community.model'; import { DSONameServiceMock } from '../../mocks/dso-name.service.mock'; +import { translateServiceStub } from '../../mocks/translate.service.mock'; import { ActivatedRouteStub } from '../../testing/active-router.stub'; import { CommunityListElementComponent } from './community-list-element.component'; @@ -49,6 +51,7 @@ describe('CommunityListElementComponent', () => { { provide: DSONameService, useValue: new DSONameServiceMock() }, { provide: 'objectElementProvider', useValue: (mockCommunityWithAbstract) }, { provide: ActivatedRoute, useValue: new ActivatedRouteStub() }, + { provide: TranslateService, useValue: translateServiceStub }, ], schemas: [NO_ERRORS_SCHEMA], }).overrideComponent(CommunityListElementComponent, { diff --git a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.html b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.html index 17b5d50d90f..9c5270a3d9a 100644 --- a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.html +++ b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.html @@ -4,6 +4,6 @@ -
+
diff --git a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts index 911c0d355fa..f88ef1c8412 100644 --- a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts @@ -10,12 +10,14 @@ import { } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { ActivatedRoute } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; import { APP_CONFIG } from '../../../../../config/app-config.interface'; import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; import { Collection } from '../../../../core/shared/collection.model'; import { DSONameServiceMock } from '../../../mocks/dso-name.service.mock'; +import { translateServiceStub } from '../../../mocks/translate.service.mock'; import { CollectionSearchResult } from '../../../object-collection/shared/collection-search-result.model'; import { ActivatedRouteStub } from '../../../testing/active-router.stub'; import { TruncatableService } from '../../../truncatable/truncatable.service'; @@ -73,6 +75,7 @@ describe('CollectionSearchResultListElementComponent', () => { { provide: APP_CONFIG, useValue: environmentUseThumbs }, { provide: ActivatedRoute, useValue: new ActivatedRouteStub() }, { provide: ThemeService, useValue: getMockThemeService() }, + { provide: TranslateService, useValue: translateServiceStub }, ], schemas: [NO_ERRORS_SCHEMA], }).overrideComponent(CollectionSearchResultListElementComponent, { diff --git a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.ts b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.ts index 2641792b02b..c463569cb07 100644 --- a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.ts +++ b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.ts @@ -4,15 +4,23 @@ import { } from '@angular/common'; import { Component, + Inject, OnInit, } from '@angular/core'; import { RouterLink } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { + APP_CONFIG, + AppConfig, +} from '../../../../../config/app-config.interface'; +import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; import { Collection } from '../../../../core/shared/collection.model'; import { ViewMode } from '../../../../core/shared/view-mode.model'; import { ThemedBadgesComponent } from '../../../object-collection/shared/badges/themed-badges.component'; import { CollectionSearchResult } from '../../../object-collection/shared/collection-search-result.model'; import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; +import { TruncatableService } from '../../../truncatable/truncatable.service'; import { SearchResultListElementComponent } from '../search-result-list-element.component'; @Component({ @@ -33,6 +41,13 @@ export class CollectionSearchResultListElementComponent extends SearchResultList */ showThumbnails: boolean; + constructor(protected truncatableService: TruncatableService, + public dsoNameService: DSONameService, + public translateService: TranslateService, + @Inject(APP_CONFIG) protected appConfig?: AppConfig) { + super(truncatableService, dsoNameService, appConfig); + } + ngOnInit(): void { super.ngOnInit(); this.showThumbnails = this.showThumbnails ?? this.appConfig.browseBy.showThumbnails; diff --git a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.html b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.html index f5d68031599..c3da40c4870 100644 --- a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.html +++ b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.html @@ -4,6 +4,6 @@ -
+
diff --git a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts index 3ef9f33d109..37e02d2b568 100644 --- a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts @@ -10,12 +10,14 @@ import { } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { ActivatedRoute } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; import { APP_CONFIG } from '../../../../../config/app-config.interface'; import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; import { Community } from '../../../../core/shared/community.model'; import { DSONameServiceMock } from '../../../mocks/dso-name.service.mock'; +import { translateServiceStub } from '../../../mocks/translate.service.mock'; import { CommunitySearchResult } from '../../../object-collection/shared/community-search-result.model'; import { ActivatedRouteStub } from '../../../testing/active-router.stub'; import { TruncatableService } from '../../../truncatable/truncatable.service'; @@ -73,6 +75,7 @@ describe('CommunitySearchResultListElementComponent', () => { { provide: APP_CONFIG, useValue: environmentUseThumbs }, { provide: ActivatedRoute, useValue: new ActivatedRouteStub() }, { provide: ThemeService, useValue: getMockThemeService() }, + { provide: TranslateService, useValue: translateServiceStub }, ], schemas: [NO_ERRORS_SCHEMA], }).overrideComponent(CommunitySearchResultListElementComponent, { diff --git a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.ts b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.ts index e8e3c579592..5d250f0ae4f 100644 --- a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.ts +++ b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.ts @@ -4,15 +4,23 @@ import { } from '@angular/common'; import { Component, + Inject, OnInit, } from '@angular/core'; import { RouterLink } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { + APP_CONFIG, + AppConfig, +} from '../../../../../config/app-config.interface'; +import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; import { Community } from '../../../../core/shared/community.model'; import { ViewMode } from '../../../../core/shared/view-mode.model'; import { ThemedBadgesComponent } from '../../../object-collection/shared/badges/themed-badges.component'; import { CommunitySearchResult } from '../../../object-collection/shared/community-search-result.model'; import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; +import { TruncatableService } from '../../../truncatable/truncatable.service'; import { SearchResultListElementComponent } from '../search-result-list-element.component'; @Component({ @@ -32,6 +40,14 @@ export class CommunitySearchResultListElementComponent extends SearchResultListE */ showThumbnails: boolean; + constructor(protected truncatableService: TruncatableService, + public dsoNameService: DSONameService, + public translateService: TranslateService, + @Inject(APP_CONFIG) protected appConfig: AppConfig, + ) { + super(truncatableService, dsoNameService, appConfig); + } + ngOnInit(): void { super.ngOnInit(); this.showThumbnails = this.showThumbnails ?? this.appConfig.browseBy.showThumbnails; From 2f472a5b5ab71ac21d235992d82e9e14b62930a0 Mon Sep 17 00:00:00 2001 From: pcg-kk Date: Tue, 28 May 2024 19:51:26 +0200 Subject: [PATCH 3/7] feat: fix e2e --- cypress/e2e/collection-create.cy.ts | 4 ++-- cypress/e2e/community-create.cy.ts | 4 ++-- .../comcol-forms/comcol-form/comcol-form.component.html | 2 +- .../comcol-forms/comcol-form/comcol-form.component.scss | 4 ++++ 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/cypress/e2e/collection-create.cy.ts b/cypress/e2e/collection-create.cy.ts index 29f7dd5cacb..423464233f8 100644 --- a/cypress/e2e/collection-create.cy.ts +++ b/cypress/e2e/collection-create.cy.ts @@ -5,9 +5,9 @@ beforeEach(() => { it('should show loading component while saving', () => { const title = 'Test Collection Title'; - cy.get('#title').type(title); + cy.get('#title-en').type(title); - cy.get('button[type="submit"]').click(); + cy.get('button[type="button"].btn-primary').click(); cy.get('ds-loading').should('be.visible'); }); diff --git a/cypress/e2e/community-create.cy.ts b/cypress/e2e/community-create.cy.ts index 96bc003ba2a..205f270db14 100644 --- a/cypress/e2e/community-create.cy.ts +++ b/cypress/e2e/community-create.cy.ts @@ -5,9 +5,9 @@ beforeEach(() => { it('should show loading component while saving', () => { const title = 'Test Community Title'; - cy.get('#title').type(title); + cy.get('#title-en').type(title); - cy.get('button[type="submit"]').click(); + cy.get('button[type="button"].btn-primary').click(); cy.get('ds-loading').should('be.visible'); }); diff --git a/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.html b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.html index 4484f367bdc..2098bbcf86b 100644 --- a/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.html +++ b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.html @@ -79,7 +79,7 @@
-
+
diff --git a/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.scss b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.scss index 7e1f2213861..c674c211e47 100644 --- a/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.scss +++ b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.scss @@ -1,3 +1,7 @@ .form-control { margin-top: 2px; } + +.form-submit { + gap: 20px; +} From 44d5341db2b47b78cfa542b377f64e6cd16f3dad Mon Sep 17 00:00:00 2001 From: pcg-kk Date: Tue, 28 May 2024 21:37:09 +0200 Subject: [PATCH 4/7] feat: fix e2e --- .../comcol/comcol-forms/comcol-form/comcol-form.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.html b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.html index 2098bbcf86b..5663716314b 100644 --- a/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.html +++ b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.html @@ -59,7 +59,7 @@
-
From cbd44c84733ffb8eaa3cff2153262f2910d7f5da Mon Sep 17 00:00:00 2001 From: pcg-kk Date: Mon, 10 Feb 2025 21:39:30 +0100 Subject: [PATCH 5/7] fix: changes after code review --- src/app/collection-page/collection-page.component.html | 8 ++++---- src/app/collection-page/collection-page.component.ts | 8 ++++++++ src/app/community-page/community-page.component.html | 8 ++++---- src/app/community-page/community-page.component.ts | 8 ++++++++ .../comcol-forms/comcol-form/comcol-form.component.ts | 4 ++-- 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/app/collection-page/collection-page.component.html b/src/app/collection-page/collection-page.component.html index bae9bdb3e45..1679ef54ae8 100644 --- a/src/app/collection-page/collection-page.component.html +++ b/src/app/collection-page/collection-page.component.html @@ -23,12 +23,12 @@ @@ -44,10 +44,10 @@ -
+
diff --git a/src/app/collection-page/collection-page.component.ts b/src/app/collection-page/collection-page.component.ts index 62cdca1c6ff..5b3fbb9e827 100644 --- a/src/app/collection-page/collection-page.component.ts +++ b/src/app/collection-page/collection-page.component.ts @@ -55,6 +55,7 @@ import { PaginationComponentOptions } from '../shared/pagination/pagination-comp import { VarDirective } from '../shared/utils/var.directive'; import { ViewTrackerComponent } from '../statistics/angulartics/dspace/view-tracker.component'; import { getCollectionPageRoute } from './collection-page-routing-paths'; +import { environment } from '../../environments/environment'; @Component({ selector: 'ds-base-collection-page', @@ -100,6 +101,11 @@ export class CollectionPageComponent implements OnInit { */ collectionPageRoute$: Observable; + /** + * The current language of the page + */ + currentLanguage: string = environment.defaultLanguage; + constructor( protected route: ActivatedRoute, protected router: Router, @@ -111,6 +117,8 @@ export class CollectionPageComponent implements OnInit { } ngOnInit(): void { + this.currentLanguage = this.translateService.currentLang; + this.collectionRD$ = this.route.data.pipe( map((data) => data.dso as RemoteData), redirectOn4xx(this.router, this.authService), diff --git a/src/app/community-page/community-page.component.html b/src/app/community-page/community-page.component.html index 7707cb61623..4f412ed9fba 100644 --- a/src/app/community-page/community-page.component.html +++ b/src/app/community-page/community-page.component.html @@ -13,10 +13,10 @@ - + - @@ -30,9 +30,9 @@ -
+
- +
diff --git a/src/app/community-page/community-page.component.ts b/src/app/community-page/community-page.component.ts index 8681cf8151b..ec961d167e7 100644 --- a/src/app/community-page/community-page.component.ts +++ b/src/app/community-page/community-page.component.ts @@ -48,6 +48,7 @@ import { ViewTrackerComponent } from '../statistics/angulartics/dspace/view-trac import { getCommunityPageRoute } from './community-page-routing-paths'; import { ThemedCollectionPageSubCollectionListComponent } from './sections/sub-com-col-section/sub-collection-list/themed-community-page-sub-collection-list.component'; import { ThemedCommunityPageSubCommunityListComponent } from './sections/sub-com-col-section/sub-community-list/themed-community-page-sub-community-list.component'; +import { environment } from '../../environments/environment'; @Component({ selector: 'ds-base-community-page', @@ -95,6 +96,11 @@ export class CommunityPageComponent implements OnInit { */ logoRD$: Observable>; + /** + * The current language of the page + */ + currentLanguage: string = environment.defaultLanguage; + /** * Route to the community page */ @@ -112,6 +118,8 @@ export class CommunityPageComponent implements OnInit { } ngOnInit(): void { + this.currentLanguage = this.translateService.currentLang; + this.communityRD$ = this.route.data.pipe( map((data) => data.dso as RemoteData), redirectOn4xx(this.router, this.authService), diff --git a/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts index 82fde741ca6..b6e2bf90613 100644 --- a/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts +++ b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts @@ -292,7 +292,7 @@ export class ComColFormComponent implements On const key = `/metadata/${fieldModel.name}`; - const keyExistAndAtLeastOneValueIsNotNull: boolean = (fieldModel.value !== null || this.dso.firstMetadataValue(fieldModel.name, { language }) !== null); + const keyExistAndAtLeastOneValueIsNotNull: boolean = (hasValue(fieldModel.value) || hasValue(this.dso.firstMetadataValue(fieldModel.name, { language }))); if ( keyExistAndAtLeastOneValueIsNotNull) { if (operations.has(key)) { @@ -354,7 +354,7 @@ export class ComColFormComponent implements On this.defaultLanguageCode = environment.defaultLanguage; this.defaultLanguage = environment.languages.find(lang => lang.code === this.defaultLanguageCode).label; - this.languages = environment.languages.filter(lang => lang.code !== this.defaultLanguageCode); + this.languages = environment.languages.filter(lang => lang.code !== this.defaultLanguageCode && (lang.active === true)); this.currentLanguageCode = this.languages.length > 0 ? this.languages[0].code : null; } From 9518554b65e6084f85913d395ac34da00f8a07be Mon Sep 17 00:00:00 2001 From: pcg-kk Date: Mon, 10 Feb 2025 22:29:29 +0100 Subject: [PATCH 6/7] fix: order of elements --- src/app/collection-page/collection-page.component.ts | 2 +- src/app/community-page/community-page.component.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/collection-page/collection-page.component.ts b/src/app/collection-page/collection-page.component.ts index 5b3fbb9e827..679ea06fbf9 100644 --- a/src/app/collection-page/collection-page.component.ts +++ b/src/app/collection-page/collection-page.component.ts @@ -24,6 +24,7 @@ import { take, } from 'rxjs/operators'; +import { environment } from '../../environments/environment'; import { AuthService } from '../core/auth/auth.service'; import { DSONameService } from '../core/breadcrumbs/dso-name.service'; import { SortOptions } from '../core/cache/models/sort-options.model'; @@ -55,7 +56,6 @@ import { PaginationComponentOptions } from '../shared/pagination/pagination-comp import { VarDirective } from '../shared/utils/var.directive'; import { ViewTrackerComponent } from '../statistics/angulartics/dspace/view-tracker.component'; import { getCollectionPageRoute } from './collection-page-routing-paths'; -import { environment } from '../../environments/environment'; @Component({ selector: 'ds-base-collection-page', diff --git a/src/app/community-page/community-page.component.ts b/src/app/community-page/community-page.component.ts index ec961d167e7..ea930a2ea06 100644 --- a/src/app/community-page/community-page.component.ts +++ b/src/app/community-page/community-page.component.ts @@ -24,6 +24,7 @@ import { mergeMap, } from 'rxjs/operators'; +import { environment } from '../../environments/environment'; import { AuthService } from '../core/auth/auth.service'; import { DSONameService } from '../core/breadcrumbs/dso-name.service'; import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service'; @@ -48,7 +49,6 @@ import { ViewTrackerComponent } from '../statistics/angulartics/dspace/view-trac import { getCommunityPageRoute } from './community-page-routing-paths'; import { ThemedCollectionPageSubCollectionListComponent } from './sections/sub-com-col-section/sub-collection-list/themed-community-page-sub-collection-list.component'; import { ThemedCommunityPageSubCommunityListComponent } from './sections/sub-com-col-section/sub-community-list/themed-community-page-sub-community-list.component'; -import { environment } from '../../environments/environment'; @Component({ selector: 'ds-base-community-page', From 577209ab172a51928c98beb31b07bd2199ba011f Mon Sep 17 00:00:00 2001 From: pcg-kk Date: Tue, 11 Feb 2025 19:59:20 +0100 Subject: [PATCH 7/7] fix: order of elements --- .../comcol/comcol-forms/comcol-form/comcol-form.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts index b6e2bf90613..e63f3ef2b85 100644 --- a/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts +++ b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts @@ -131,7 +131,7 @@ export class ComColFormComponent implements On ERROR_KEY_PREFIX = '.form.errors.'; /** - * The form model that represents the fields in the form + * The map of form model that represents the fields in the form */ formModels: Map = new Map();