diff --git a/projects/solidify-frontend/src/lib/core/helpers/form-validation.helper.ts b/projects/solidify-frontend/src/lib/core/helpers/form-validation.helper.ts index a6a8b6439b795eb00ba2f1411efae4d2e44d0dbc..4663e1da8ebb12600ab0a1cce9431411c7fa1459 100644 --- a/projects/solidify-frontend/src/lib/core/helpers/form-validation.helper.ts +++ b/projects/solidify-frontend/src/lib/core/helpers/form-validation.helper.ts @@ -33,6 +33,7 @@ import { } from "rxjs"; import {tap} from "rxjs/operators"; import { + isInstanceOf, isNullOrUndefined, isNullOrUndefinedOrWhiteString, isTrue, @@ -99,6 +100,35 @@ export class FormValidationHelper { return Array.from(MappingObjectUtil.values(errors)).join(". "); } + static getListAbstractControlFromFormGroup(formGroup: FormGroup): AbstractControl[] { + const listFormControl = []; + Object.keys(formGroup.controls).forEach(key => { + listFormControl.push(formGroup.controls[key]); + }); + return listFormControl; + } + + static getListFormControlFromFormGroup(formGroup: FormGroup): FormControl[] { + return this.getListAbstractControlFromFormGroup(formGroup).filter(c => isInstanceOf(c, FormControl)); + } + + static getListFormArrayFromFormGroup(formGroup: FormGroup): FormArray[] { + return this.getListAbstractControlFromFormGroup(formGroup).filter(c => isInstanceOf(c, FormArray)); + } + + static getListFormGroupFromFormGroup(formGroup: FormGroup): FormGroup[] { + return this.getListAbstractControlFromFormGroup(formGroup).filter(c => isInstanceOf(c, FormGroup)); + } + + static getControlName(c: AbstractControl): string | undefined { + const parent = c?.parent; + if (isNullOrUndefined(parent) || isInstanceOf(parent, FormArray)) { + return undefined; + } + const parentControls = parent.controls; + return Object.keys(parentControls).find(name => c === parentControls[name]) || undefined; + } + static hasRequiredFieldByName(form: FormGroup, abstractControlName: string): boolean { const formControl = this.getFormControl(form, abstractControlName); return this.hasRequiredField(formControl); diff --git a/projects/solidify-frontend/src/lib/core/models/dto/base-relation-resource.model.ts b/projects/solidify-frontend/src/lib/core/models/dto/base-relation-resource.model.ts index 6341eaf75d6d8dbaf4f7cffc5f40b93c4c3d943b..2ad5763ed176febb41876f41f03ff257009d1e0d 100644 --- a/projects/solidify-frontend/src/lib/core/models/dto/base-relation-resource.model.ts +++ b/projects/solidify-frontend/src/lib/core/models/dto/base-relation-resource.model.ts @@ -21,9 +21,12 @@ * ----------------------------------------------------------------------------------------------%% */ +import {ChangeInfo} from "./change-info.model"; export type BaseRelationResourceType = BaseRelationResource; export interface BaseRelationResource { - + compositeKey?: string; + creation?: ChangeInfo; + lastUpdate?: ChangeInfo; } diff --git a/projects/solidify-frontend/src/lib/core/models/dto/base-resource-with-relation.model.ts b/projects/solidify-frontend/src/lib/core/models/dto/base-resource-with-relation.model.ts new file mode 100644 index 0000000000000000000000000000000000000000..e93b293d855f255c7bea1e39bd3ec58b719d9f69 --- /dev/null +++ b/projects/solidify-frontend/src/lib/core/models/dto/base-resource-with-relation.model.ts @@ -0,0 +1,38 @@ +/*- + * %%---------------------------------------------------------------------------------------------- + * Solidify Framework - Solidify Frontend - base-resource-with-relation.model.ts + * SPDX-License-Identifier: GPL-2.0-or-later + * %----------------------------------------------------------------------------------------------% + * Copyright (C) 2017 - 2024 University of Geneva + * %----------------------------------------------------------------------------------------------% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-2.0.html>. + * ----------------------------------------------------------------------------------------------%% + */ + +import {BaseRelationResourceType} from "./base-relation-resource.model"; +import {BaseResource} from "./base-resource.model"; +import {ChangeInfo} from "./change-info.model"; + +export type BaseResourceWithRelationType<URelation extends BaseRelationResourceType> = BaseResourceWithRelation<URelation>; + +export interface BaseResourceWithRelation<URelation extends BaseRelationResourceType> extends BaseResource { + resId?: string; + joinResource?: URelation; +} + +export type BaseResourceWithRelationExtended<URelation extends BaseRelationResourceType> = { + creation?: ChangeInfo; + lastUpdate?: ChangeInfo; +} & BaseResourceWithRelation<URelation>; diff --git a/projects/solidify-frontend/src/lib/core/models/public_api.ts b/projects/solidify-frontend/src/lib/core/models/public_api.ts index b237af15c409b6c5c0536d7e81afdee4dace9cf9..74bbfb6b0869e3ddf77d886d36fd628634e9ff3a 100644 --- a/projects/solidify-frontend/src/lib/core/models/public_api.ts +++ b/projects/solidify-frontend/src/lib/core/models/public_api.ts @@ -44,6 +44,7 @@ export * from "./dto/base-resource-logo.model"; export * from "./dto/base-resource-thumbnail.model"; export * from "./dto/base-resource-with-labels.model"; export * from "./dto/base-resource-with-logo.model"; +export * from "./dto/base-resource-with-relation.model"; export * from "./dto/change-info.model"; export * from "./dto/citation.model"; export * from "./dto/collection-typed.model"; diff --git a/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/multi-relation-2-tiers-action.helper.ts b/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/multi-relation-2-tiers-action.helper.ts new file mode 100644 index 0000000000000000000000000000000000000000..9f0bd5ed985c024ace0180deaa3b7fbad308e2a2 --- /dev/null +++ b/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/multi-relation-2-tiers-action.helper.ts @@ -0,0 +1,114 @@ +/*- + * %%---------------------------------------------------------------------------------------------- + * Solidify Framework - Solidify Frontend - multi-relation-2-tiers-action.helper.ts + * SPDX-License-Identifier: GPL-2.0-or-later + * %----------------------------------------------------------------------------------------------% + * Copyright (C) 2017 - 2024 University of Geneva + * %----------------------------------------------------------------------------------------------% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-2.0.html>. + * ----------------------------------------------------------------------------------------------%% + */ + +import {BaseRelationResourceType} from "../../../models/dto/base-relation-resource.model"; +import {BaseResourceWithRelationType} from "../../../models/dto/base-resource-with-relation.model"; +import {BaseResourceType} from "../../../models/dto/base-resource.model"; +import {MultiRelation2TiersNameSpace} from "./multi-relation-2-tiers-namespace.model"; +import {MultiRelation2TiersAction} from "./multi-relation-2-tiers.action"; + +export class MultiRelation2TiersActionHelper { + static getAll(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.GetAll>): MultiRelation2TiersAction.GetAll { + return new relation2TiersNameSpace.GetAll(...args); + } + + static getAllSuccess<TResource extends BaseResourceType>(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.GetAllSuccess>): MultiRelation2TiersAction.GetAllSuccess<TResource> { + return new relation2TiersNameSpace.GetAllSuccess(...args); + } + + static getAllFail(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.GetAllFail>): MultiRelation2TiersAction.GetAllFail { + return new relation2TiersNameSpace.GetAllFail(...args); + } + + static getById(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.GetById>): MultiRelation2TiersAction.GetById { + return new relation2TiersNameSpace.GetById(...args); + } + + static getByIdSuccess<TResource extends BaseResourceType>(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.GetByIdSuccess>): MultiRelation2TiersAction.GetByIdSuccess<TResource> { + return new relation2TiersNameSpace.GetByIdSuccess(...args); + } + + static getByIdFail(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.GetByIdFail>): MultiRelation2TiersAction.GetByIdFail { + return new relation2TiersNameSpace.GetByIdFail(...args); + } + + static create<URelation extends BaseRelationResourceType>(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.Create>): MultiRelation2TiersAction.Create<URelation> { + return new relation2TiersNameSpace.Create(...args); + } + + static createSuccess<TResource extends BaseResourceWithRelationType<URelation>, URelation extends BaseRelationResourceType>(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.CreateSuccess>): MultiRelation2TiersAction.CreateSuccess<TResource, URelation> { + return new relation2TiersNameSpace.CreateSuccess(...args); + } + + static createFail<URelation extends BaseRelationResourceType>(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.CreateFail>): MultiRelation2TiersAction.CreateFail<URelation> { + return new relation2TiersNameSpace.CreateFail(...args); + } + + static deleteList(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.DeleteList>): MultiRelation2TiersAction.DeleteList { + return new relation2TiersNameSpace.DeleteList(...args); + } + + static deleteListSuccess(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.DeleteListSuccess>): MultiRelation2TiersAction.DeleteListSuccess { + return new relation2TiersNameSpace.DeleteListSuccess(...args); + } + + static deleteListFail(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.DeleteListFail>): MultiRelation2TiersAction.DeleteListFail { + return new relation2TiersNameSpace.DeleteListFail(...args); + } + + static delete(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.Delete>): MultiRelation2TiersAction.Delete { + return new relation2TiersNameSpace.Delete(...args); + } + + static deleteSuccess(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.DeleteSuccess>): MultiRelation2TiersAction.DeleteSuccess { + return new relation2TiersNameSpace.DeleteSuccess(...args); + } + + static deleteFail(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.DeleteFail>): MultiRelation2TiersAction.DeleteFail { + return new relation2TiersNameSpace.DeleteFail(...args); + } + + static update<TResource extends BaseResourceWithRelationType<URelation>, URelation extends BaseRelationResourceType>(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.Update>): MultiRelation2TiersAction.Update<TResource, URelation> { + return new relation2TiersNameSpace.Update(...args); + } + + static updateSuccess<TResource extends BaseResourceWithRelationType<URelation>, URelation extends BaseRelationResourceType>(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.UpdateSuccess>): MultiRelation2TiersAction.UpdateSuccess<TResource, URelation> { + return new relation2TiersNameSpace.UpdateSuccess(...args); + } + + static updateFail<TResource extends BaseResourceWithRelationType<URelation>, URelation extends BaseRelationResourceType>(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.UpdateFail>): MultiRelation2TiersAction.UpdateFail<TResource, URelation> { + return new relation2TiersNameSpace.UpdateFail(...args); + } + + static updateRelation<TRelation extends BaseRelationResourceType>(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.UpdateRelation>): MultiRelation2TiersAction.UpdateRelation<TRelation> { + return new relation2TiersNameSpace.UpdateRelation(...args); + } + + static updateRelationSuccess<TRelation extends BaseRelationResourceType>(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.UpdateRelationSuccess>): MultiRelation2TiersAction.UpdateRelationSuccess<TRelation> { + return new relation2TiersNameSpace.UpdateRelationSuccess(...args); + } + + static updateRelationFail<TRelation extends BaseRelationResourceType>(relation2TiersNameSpace: MultiRelation2TiersNameSpace, ...args: ConstructorParameters<typeof MultiRelation2TiersAction.UpdateRelationFail>): MultiRelation2TiersAction.UpdateRelationFail<TRelation> { + return new relation2TiersNameSpace.UpdateRelationFail(...args); + } +} diff --git a/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/multi-relation-2-tiers-namespace.model.ts b/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/multi-relation-2-tiers-namespace.model.ts new file mode 100644 index 0000000000000000000000000000000000000000..c94693c7e0198d89141c09dc15f0fd6e4a739d75 --- /dev/null +++ b/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/multi-relation-2-tiers-namespace.model.ts @@ -0,0 +1,49 @@ +/*- + * %%---------------------------------------------------------------------------------------------- + * Solidify Framework - Solidify Frontend - multi-relation-2-tiers-namespace.model.ts + * SPDX-License-Identifier: GPL-2.0-or-later + * %----------------------------------------------------------------------------------------------% + * Copyright (C) 2017 - 2024 University of Geneva + * %----------------------------------------------------------------------------------------------% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-2.0.html>. + * ----------------------------------------------------------------------------------------------%% + */ + +import {BaseResourceStoreNameSpace} from "../../../models/stores/base-resource-store-namespace.model"; +import {StoreActionClass} from "../../../models/stores/state-action.model"; + +export interface MultiRelation2TiersNameSpace extends BaseResourceStoreNameSpace { + GetAll: StoreActionClass; + GetAllSuccess: StoreActionClass; + GetAllFail: StoreActionClass; + GetById: StoreActionClass; + GetByIdSuccess: StoreActionClass; + GetByIdFail: StoreActionClass; + Create: StoreActionClass; + CreateSuccess: StoreActionClass; + CreateFail: StoreActionClass; + DeleteList: StoreActionClass; + DeleteListSuccess: StoreActionClass; + DeleteListFail: StoreActionClass; + Delete: StoreActionClass; + DeleteSuccess: StoreActionClass; + DeleteFail: StoreActionClass; + Update: StoreActionClass; + UpdateSuccess: StoreActionClass; + UpdateFail: StoreActionClass; + UpdateRelation: StoreActionClass; + UpdateRelationSuccess: StoreActionClass; + UpdateRelationFail: StoreActionClass; +} diff --git a/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/multi-relation-2-tiers-options.model.ts b/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/multi-relation-2-tiers-options.model.ts new file mode 100644 index 0000000000000000000000000000000000000000..6f47daf275199ba91d0163b05172b6ec6299ea51 --- /dev/null +++ b/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/multi-relation-2-tiers-options.model.ts @@ -0,0 +1,32 @@ +/*- + * %%---------------------------------------------------------------------------------------------- + * Solidify Framework - Solidify Frontend - multi-relation-2-tiers-options.model.ts + * SPDX-License-Identifier: GPL-2.0-or-later + * %----------------------------------------------------------------------------------------------% + * Copyright (C) 2017 - 2024 University of Geneva + * %----------------------------------------------------------------------------------------------% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-2.0.html>. + * ----------------------------------------------------------------------------------------------%% + */ + +import {ApiResourceNamePartialEnum} from "../../../enums/partial/api-resource-name-partial.enum"; +import {ExtendEnum} from "../../../types/extend-enum.type"; +import {BaseResourceOptions} from "../base/base-resource-options.model"; +import {MultiRelation2TiersNameSpace} from "./multi-relation-2-tiers-namespace.model"; + +export interface MultiRelation2TiersOptions extends BaseResourceOptions { + nameSpace: MultiRelation2TiersNameSpace; + resourceName: ExtendEnum<ApiResourceNamePartialEnum>; +} diff --git a/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/multi-relation-2-tiers-state.model.ts b/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/multi-relation-2-tiers-state.model.ts new file mode 100644 index 0000000000000000000000000000000000000000..eea9af7478fd11cea60974e9dd58ec185c2366a7 --- /dev/null +++ b/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/multi-relation-2-tiers-state.model.ts @@ -0,0 +1,30 @@ +/*- + * %%---------------------------------------------------------------------------------------------- + * Solidify Framework - Solidify Frontend - multi-relation-2-tiers-state.model.ts + * SPDX-License-Identifier: GPL-2.0-or-later + * %----------------------------------------------------------------------------------------------% + * Copyright (C) 2017 - 2024 University of Geneva + * %----------------------------------------------------------------------------------------------% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-2.0.html>. + * ----------------------------------------------------------------------------------------------%% + */ + +import {BaseResourceType} from "../../../models/dto/base-resource.model"; +import {BaseResourceStateModel} from "../../../models/stores/base-resource-state.model"; + +export interface MultiRelation2TiersStateModel<TResource extends BaseResourceType> extends BaseResourceStateModel { + selected: TResource[] | undefined; + current: TResource | undefined; +} diff --git a/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/multi-relation-2-tiers.action.ts b/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/multi-relation-2-tiers.action.ts new file mode 100644 index 0000000000000000000000000000000000000000..2cd74486fc299ca84690b763089fcf436ce549da --- /dev/null +++ b/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/multi-relation-2-tiers.action.ts @@ -0,0 +1,178 @@ +/*- + * %%---------------------------------------------------------------------------------------------- + * Solidify Framework - Solidify Frontend - multi-relation-2-tiers.action.ts + * SPDX-License-Identifier: GPL-2.0-or-later + * %----------------------------------------------------------------------------------------------% + * Copyright (C) 2017 - 2024 University of Geneva + * %----------------------------------------------------------------------------------------------% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-2.0.html>. + * ----------------------------------------------------------------------------------------------%% + */ + +import {BaseRelationResourceType} from "../../../models/dto/base-relation-resource.model"; +import {BaseResourceWithRelationType} from "../../../models/dto/base-resource-with-relation.model"; +import {BaseResourceType} from "../../../models/dto/base-resource.model"; +import {CollectionTyped} from "../../../models/dto/collection-typed.model"; +import {QueryParameters} from "../../../models/query-parameters/query-parameters.model"; +import { + BaseAction, + BaseSubActionFail, + BaseSubActionSuccess, +} from "../../../models/stores/base.action"; +import {MultiRelation2TiersNameSpace} from "./multi-relation-2-tiers-namespace.model"; + +export namespace MultiRelation2TiersAction { + export class GetAll extends BaseAction { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Get All"; + + constructor(public parentId: string, public queryParameters?: QueryParameters, public keepCurrentContext: boolean = false) { + super(); + } + } + + export class GetAllSuccess<TResource extends BaseResourceType> extends BaseSubActionSuccess<GetAll> { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Get All Success"; + + constructor(public parentAction: GetAll, public list: CollectionTyped<TResource>) { + super(parentAction); + } + } + + export class GetAllFail extends BaseSubActionFail<GetAll> { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Get All Fail"; + } + + export class GetById extends BaseAction { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Get By Id"; + + constructor(public parentId: string, public resId: string, public keepCurrentContext: boolean = false) { + super(); + } + } + + export class GetByIdSuccess<TResource extends BaseResourceType> extends BaseSubActionSuccess<GetById> { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Get By Id Success"; + + constructor(public parentAction: GetById, public model: TResource) { + super(parentAction); + } + } + + export class GetByIdFail extends BaseSubActionFail<GetById> { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Get By Id Fail"; + } + + export class Create<URelation extends BaseRelationResourceType> extends BaseAction { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Create"; + + constructor(public parentId: string, public resId: string, public relation: URelation) { + super(); + } + } + + export class CreateSuccess<TResource extends BaseResourceWithRelationType<URelation>, URelation extends BaseRelationResourceType> extends BaseSubActionSuccess<Create<URelation>> { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Create Success"; + + constructor(public parentAction: Create<URelation>, public result: TResource) { + super(parentAction); + } + } + + export class CreateFail<URelation extends BaseRelationResourceType> extends BaseSubActionFail<Create<URelation>> { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Create Fail"; + } + + export class DeleteList extends BaseAction { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Delete List"; + + constructor(public parentId: string, public listResId: string[]) { + super(); + } + } + + export class DeleteListSuccess extends BaseSubActionSuccess<DeleteList> { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Delete ListSuccess"; + } + + export class DeleteListFail extends BaseSubActionFail<DeleteList> { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Delete ListFail"; + } + + export class Delete extends BaseAction { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Delete"; + + constructor(public parentId: string, public resId: string, public compositeKey: string) { + super(); + } + } + + export class DeleteSuccess extends BaseSubActionSuccess<Delete> { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Delete Success"; + } + + export class DeleteFail extends BaseSubActionFail<Delete> { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Delete Fail"; + } + + export class Update<TResource extends BaseResourceWithRelationType<URelation>, URelation extends BaseRelationResourceType> extends BaseAction { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Update"; + + constructor(public parentId: string, public newRelation: TResource[]) { + super(); + } + } + + export class UpdateSuccess<TResource extends BaseResourceWithRelationType<URelation>, URelation extends BaseRelationResourceType> extends BaseSubActionSuccess<Update<TResource, URelation>> { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Update Success"; + + constructor(public parentAction: Update<TResource, URelation>, public parentId: string) { + super(parentAction); + } + } + + export class UpdateFail<TResource extends BaseResourceWithRelationType<URelation>, URelation extends BaseRelationResourceType> extends BaseSubActionFail<Update<TResource, URelation>> { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Update Fail"; + + constructor(public parentAction: Update<TResource, URelation>, public parentId: string) { + super(parentAction); + } + } + + export class UpdateRelation<URelation extends BaseRelationResourceType> extends BaseAction { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Update Relation"; + + constructor(public parentId: string, public resId: string, public relation: URelation) { + super(); + } + } + + export class UpdateRelationSuccess<URelation extends BaseRelationResourceType> extends BaseSubActionSuccess<UpdateRelation<URelation>> { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Update Relation Success"; + + constructor(public parentAction: UpdateRelation<URelation>) { + super(parentAction); + } + } + + export class UpdateRelationFail<URelation extends BaseRelationResourceType> extends BaseSubActionFail<UpdateRelation<URelation>> { + static readonly type: string = "[{0}] Multi Relation 2 Tiers : Update Relation Fail"; + + constructor(public parentAction: UpdateRelation<URelation>) { + super(parentAction); + } + } +} + +export const multiRelation2TiersActionNameSpace: MultiRelation2TiersNameSpace = MultiRelation2TiersAction; diff --git a/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/multi-relation-2-tiers.state.ts b/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/multi-relation-2-tiers.state.ts new file mode 100644 index 0000000000000000000000000000000000000000..d01a6de4ea21571c22519dfe2110d25d82dcd714 --- /dev/null +++ b/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/multi-relation-2-tiers.state.ts @@ -0,0 +1,364 @@ +/*- + * %%---------------------------------------------------------------------------------------------- + * Solidify Framework - Solidify Frontend - multi-relation-2-tiers.state.ts + * SPDX-License-Identifier: GPL-2.0-or-later + * %----------------------------------------------------------------------------------------------% + * Copyright (C) 2017 - 2024 University of Geneva + * %----------------------------------------------------------------------------------------------% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-2.0.html>. + * ----------------------------------------------------------------------------------------------%% + */ + +import {Inject} from "@angular/core"; +import { + Actions, + Store, +} from "@ngxs/store"; +import { + Observable, + of, +} from "rxjs"; +import { + catchError, + map, + tap, +} from "rxjs/operators"; +import {SOLIDIFY_CONSTANTS} from "../../../constants"; +import {RegisterDefaultAction} from "../../../decorators/store.decorator"; +import {ApiResourceNamePartialEnum} from "../../../enums/partial/api-resource-name-partial.enum"; +import {DefaultSolidifyEnvironment} from "../../../environments/environment.solidify-defaults"; +import {SolidifyStateError} from "../../../errors/solidify-state.error"; +import {ApiService} from "../../../http/api.service"; +import {ENVIRONMENT} from "../../../injection-tokens/environment.injection-token"; +import {BaseRelationResourceType} from "../../../models/dto/base-relation-resource.model"; +import {BaseResourceWithRelationType} from "../../../models/dto/base-resource-with-relation.model"; +import {BaseResourceType} from "../../../models/dto/base-resource.model"; +import {CollectionTyped} from "../../../models/dto/collection-typed.model"; +import {SolidifyHttpErrorResponseModel} from "../../../models/errors/solidify-http-error-response.model"; +import {QueryParameters} from "../../../models/query-parameters/query-parameters.model"; +import {NotifierService} from "../../../models/services/notifier-service.model"; +import {BaseResourceStateModel} from "../../../models/stores/base-resource-state.model"; +import {ActionSubActionCompletionsWrapper} from "../../../models/stores/base.action"; +import {SolidifyStateContext} from "../../../models/stores/state-context.model"; +import { + isNonEmptyArray, + isNullOrUndefined, + isNullOrUndefinedOrWhiteString, +} from "../../../tools/is/is.tool"; +import {ExtendEnum} from "../../../types/extend-enum.type"; +import {ArrayUtil} from "../../../utils/array.util"; +import {ObjectUtil} from "../../../utils/object.util"; +import {ofSolidifyActionCompleted} from "../../../utils/stores/store.tool"; +import {StoreUtil} from "../../../utils/stores/store.util"; +import { + BaseResourceState, + defaultBaseResourceStateInitValue, +} from "../base/base-resource.state"; +import {MultiRelation2TiersActionHelper} from "./multi-relation-2-tiers-action.helper"; +import {MultiRelation2TiersNameSpace} from "./multi-relation-2-tiers-namespace.model"; +import {MultiRelation2TiersOptions} from "./multi-relation-2-tiers-options.model"; +import {MultiRelation2TiersStateModel} from "./multi-relation-2-tiers-state.model"; +import {MultiRelation2TiersAction} from "./multi-relation-2-tiers.action"; + +export const defaultMultiRelation2TiersStateInitValue: <TResourceType extends BaseResourceType> () => MultiRelation2TiersStateModel<TResourceType> = () => + ({ + ...defaultBaseResourceStateInitValue(), + selected: undefined, + current: undefined, + }); + +// @dynamic +export abstract class MultiRelation2TiersState<TStateModel extends BaseResourceStateModel, TResource extends BaseResourceWithRelationType<URelation>, URelation extends BaseRelationResourceType> extends BaseResourceState<TStateModel> { + protected readonly _resourceName: ExtendEnum<ApiResourceNamePartialEnum>; + protected declare readonly _nameSpace: MultiRelation2TiersNameSpace; + protected declare readonly _optionsState: MultiRelation2TiersOptions; + + protected constructor(protected _apiService: ApiService, + protected _store: Store, + protected _notificationService: NotifierService, + protected _actions$: Actions, + @Inject(ENVIRONMENT) protected readonly _environment: DefaultSolidifyEnvironment, + protected _options: MultiRelation2TiersOptions) { + super(_apiService, _store, _notificationService, _actions$, _environment, _options, MultiRelation2TiersState); + this._resourceName = this._optionsState.resourceName; + } + + protected static _getDefaultOptions(): MultiRelation2TiersOptions | any { + let defaultOptions: MultiRelation2TiersOptions | any = {} as MultiRelation2TiersOptions; + defaultOptions = Object.assign(BaseResourceState._getDefaultOptions(), defaultOptions); + return defaultOptions; + } + + private _evaluateSubResourceUrl(parentId: string): string { + return this._urlResource + SOLIDIFY_CONSTANTS.URL_SEPARATOR + parentId + SOLIDIFY_CONSTANTS.URL_SEPARATOR + this._resourceName; + } + + @RegisterDefaultAction((multiRelation2TiersNameSpace: MultiRelation2TiersNameSpace) => multiRelation2TiersNameSpace.GetAll) + getAll<U>(ctx: SolidifyStateContext<MultiRelation2TiersStateModel<TResource>>, action: MultiRelation2TiersAction.GetAll): Observable<CollectionTyped<U>> { + let reset = {}; + if (!action.keepCurrentContext) { + reset = { + total: 0, + selected: undefined, + }; + } + ctx.patchState({ + isLoadingCounter: ctx.getState().isLoadingCounter + 1, + queryParameters: StoreUtil.getQueryParametersToApply(action.queryParameters, ctx), + ...reset, + }); + return this._getAll<U>(ctx, action) + .pipe( + tap((collection: CollectionTyped<U>) => { + ctx.dispatch(MultiRelation2TiersActionHelper.getAllSuccess<U>(this._nameSpace, action, collection)); + }), + catchError((error: SolidifyHttpErrorResponseModel) => { + ctx.dispatch(MultiRelation2TiersActionHelper.getAllFail(this._nameSpace, action)); + throw new SolidifyStateError(this, error); + }), + ); + } + + protected override _callGetAllEndpoint<U>(ctx: SolidifyStateContext<MultiRelation2TiersStateModel<TResource>>, action: MultiRelation2TiersAction.GetAll, queryParameters: QueryParameters): Observable<CollectionTyped<U>> { + const url = this._evaluateSubResourceUrl(action.parentId); + return this._apiService.getCollection<U>(url, queryParameters); + } + + @RegisterDefaultAction((multiRelation2TiersNameSpace: MultiRelation2TiersNameSpace) => multiRelation2TiersNameSpace.GetAllSuccess) + getAllSuccess(ctx: SolidifyStateContext<MultiRelation2TiersStateModel<TResource>>, action: MultiRelation2TiersAction.GetAllSuccess<TResource>): void { + ctx.patchState({ + selected: action.list._data, + isLoadingCounter: ctx.getState().isLoadingCounter - 1, + }); + } + + @RegisterDefaultAction((multiRelation2TiersNameSpace: MultiRelation2TiersNameSpace) => multiRelation2TiersNameSpace.GetAllFail) + getAllFail(ctx: SolidifyStateContext<MultiRelation2TiersStateModel<TResource>>, action: MultiRelation2TiersAction.GetAllFail): void { + ctx.patchState({ + isLoadingCounter: ctx.getState().isLoadingCounter - 1, + }); + } + + @RegisterDefaultAction((multiRelation2TiersNameSpace: MultiRelation2TiersNameSpace) => multiRelation2TiersNameSpace.GetById) + getById<U>(ctx: SolidifyStateContext<MultiRelation2TiersStateModel<TResource>>, action: MultiRelation2TiersAction.GetById): Observable<U> { + let reset = {}; + if (!action.keepCurrentContext) { + reset = { + current: undefined, + }; + } + ctx.patchState({ + isLoadingCounter: ctx.getState().isLoadingCounter + 1, + ...reset, + }); + const url = this._evaluateSubResourceUrl(action.parentId); + return this._apiService.getById<U>(url, action.resId) + .pipe( + tap((model: U) => { + ctx.dispatch(MultiRelation2TiersActionHelper.getByIdSuccess<U>(this._nameSpace, action, model)); + }), + catchError((error: SolidifyHttpErrorResponseModel) => { + ctx.dispatch(MultiRelation2TiersActionHelper.getByIdFail(this._nameSpace, action)); + throw new SolidifyStateError(this, error); + }), + ); + } + + @RegisterDefaultAction((multiRelation2TiersNameSpace: MultiRelation2TiersNameSpace) => multiRelation2TiersNameSpace.GetByIdSuccess) + getByIdSuccess(ctx: SolidifyStateContext<MultiRelation2TiersStateModel<TResource>>, action: MultiRelation2TiersAction.GetByIdSuccess<TResource>): void { + ctx.patchState({ + current: action.model, + isLoadingCounter: ctx.getState().isLoadingCounter - 1, + }); + } + + @RegisterDefaultAction((multiRelation2TiersNameSpace: MultiRelation2TiersNameSpace) => multiRelation2TiersNameSpace.GetByIdFail) + getByIdFail(ctx: SolidifyStateContext<MultiRelation2TiersStateModel<TResource>>, action: MultiRelation2TiersAction.GetByIdFail): void { + ctx.patchState({ + isLoadingCounter: ctx.getState().isLoadingCounter - 1, + }); + } + + @RegisterDefaultAction((multiRelation2TiersNameSpace: MultiRelation2TiersNameSpace) => multiRelation2TiersNameSpace.Create) + create(ctx: SolidifyStateContext<MultiRelation2TiersStateModel<TResource>>, action: MultiRelation2TiersAction.Create<URelation>): Observable<TResource> { + const url = this._evaluateSubResourceUrl(action.parentId); + return this._apiService.post<URelation, TResource>(`${url}/${action.resId}`, action.relation) + .pipe( + tap(result => { + ctx.dispatch(MultiRelation2TiersActionHelper.createSuccess<TResource, URelation>(this._nameSpace, action, result)); + }), + catchError((error: SolidifyHttpErrorResponseModel) => { + ctx.dispatch(MultiRelation2TiersActionHelper.createFail(this._nameSpace, action)); + throw new SolidifyStateError(this, error); + }), + ); + } + + @RegisterDefaultAction((multiRelation2TiersNameSpace: MultiRelation2TiersNameSpace) => multiRelation2TiersNameSpace.DeleteList) + deleteList(ctx: SolidifyStateContext<MultiRelation2TiersStateModel<TResource>>, action: MultiRelation2TiersAction.DeleteList): Observable<string[]> { + if (action.listResId.length === 0) { + ctx.dispatch(MultiRelation2TiersActionHelper.deleteListSuccess(this._nameSpace, action)); + return; + } + const url = this._evaluateSubResourceUrl(action.parentId); + return this._apiService.delete<string[]>(url, action.listResId) + .pipe( + tap(() => { + ctx.dispatch(MultiRelation2TiersActionHelper.deleteListSuccess(this._nameSpace, action)); + }), + catchError((error: SolidifyHttpErrorResponseModel) => { + ctx.dispatch(MultiRelation2TiersActionHelper.deleteListFail(this._nameSpace, action)); + throw new SolidifyStateError(this, error); + }), + ); + } + + @RegisterDefaultAction((multiRelation2TiersNameSpace: MultiRelation2TiersNameSpace) => multiRelation2TiersNameSpace.Delete) + delete(ctx: SolidifyStateContext<MultiRelation2TiersStateModel<TResource>>, action: MultiRelation2TiersAction.Delete): Observable<number> { + const url = this._evaluateSubResourceUrl(action.parentId); + return this._apiService.delete<number>(url + SOLIDIFY_CONSTANTS.URL_SEPARATOR + action.resId) + .pipe( + tap(() => { + ctx.dispatch(MultiRelation2TiersActionHelper.deleteSuccess(this._nameSpace, action)); + }), + catchError((error: SolidifyHttpErrorResponseModel) => { + ctx.dispatch(MultiRelation2TiersActionHelper.deleteFail(this._nameSpace, action)); + throw new SolidifyStateError(this, error); + }), + ); + } + + @RegisterDefaultAction((multiRelation2TiersNameSpace: MultiRelation2TiersNameSpace) => multiRelation2TiersNameSpace.UpdateRelation) + updateRelation(ctx: SolidifyStateContext<MultiRelation2TiersStateModel<TResource>>, action: MultiRelation2TiersAction.UpdateRelation<URelation>): Observable<URelation> { + const url = this._evaluateSubResourceUrl(action.parentId); + return this._apiService.patchById<URelation>(url, action.resId, action.relation) + .pipe( + tap(() => { + ctx.dispatch(MultiRelation2TiersActionHelper.updateRelationSuccess<URelation>(this._nameSpace, action)); + }), + catchError((error: SolidifyHttpErrorResponseModel) => { + ctx.dispatch(MultiRelation2TiersActionHelper.updateRelationFail<URelation>(this._nameSpace, action)); + throw new SolidifyStateError(this, error); + }), + ); + } + + @RegisterDefaultAction((multiRelation2TiersNameSpace: MultiRelation2TiersNameSpace) => multiRelation2TiersNameSpace.Update) + update(ctx: SolidifyStateContext<MultiRelation2TiersStateModel<TResource>>, action: MultiRelation2TiersAction.Update<TResource, URelation>): void { + ctx.patchState({ + isLoadingCounter: ctx.getState().isLoadingCounter + 1, + }); + + this.subscribe(this._internalUpdate(ctx, action).pipe(tap(success => { + if (success) { + ctx.dispatch(MultiRelation2TiersActionHelper.updateSuccess(this._nameSpace, action, action.parentId)); + } else { + ctx.dispatch(MultiRelation2TiersActionHelper.updateFail(this._nameSpace, action, action.parentId)); + } + }))); + } + + protected _internalUpdate(ctx: SolidifyStateContext<MultiRelation2TiersStateModel<TResource>>, action: MultiRelation2TiersAction.Update<TResource, URelation>): Observable<boolean> { + const listOld = isNullOrUndefined(ctx.getState().selected) ? [] : ctx.getState().selected; + const listNew = action.newRelation; + + const diff = ArrayUtil.diff(listOld, listNew, (a: TResource, b: TResource) => { + if (isNullOrUndefinedOrWhiteString(a?.joinResource?.compositeKey) && isNullOrUndefinedOrWhiteString(b?.joinResource?.compositeKey)) { + return false; // Allow to manage new resource + } + return a?.joinResource?.compositeKey === b?.joinResource?.compositeKey; + }); + + const listActions: ActionSubActionCompletionsWrapper[] = []; + + const listActionToAdd: ActionSubActionCompletionsWrapper<MultiRelation2TiersAction.Create<URelation>>[] = listNew + .filter(resource => isNullOrUndefinedOrWhiteString(resource?.joinResource?.compositeKey)) + .map(resource => ({ + action: MultiRelation2TiersActionHelper.create(this._nameSpace, action.parentId, resource.resId, resource.joinResource), + subActionCompletions: [ + this._actions$.pipe(ofSolidifyActionCompleted(this._nameSpace.CreateSuccess)), + this._actions$.pipe(ofSolidifyActionCompleted(this._nameSpace.CreateFail)), + ], + })); + + const listActionToDelete: ActionSubActionCompletionsWrapper<MultiRelation2TiersAction.Delete>[] = diff.missingInArrayB.map(resource => ({ + action: MultiRelation2TiersActionHelper.delete(this._nameSpace, action.parentId, resource.resId, resource.joinResource.compositeKey), + subActionCompletions: [ + this._actions$.pipe(ofSolidifyActionCompleted(this._nameSpace.DeleteSuccess)), + this._actions$.pipe(ofSolidifyActionCompleted(this._nameSpace.DeleteFail)), + ], + })); + + let listActionToUpdate = []; + if (isNonEmptyArray(diff.common)) { + // Check if difference present on join resource parameters + const listIdInCommon = diff.common.map(c => c.joinResource.compositeKey); + const oldInCommon = listOld.filter(item => listIdInCommon.includes(item.joinResource.compositeKey)); + const newInCommon = listNew.filter(item => listIdInCommon.includes(item.joinResource.compositeKey)); + const diffCommon = ArrayUtil.diff(oldInCommon, newInCommon, (a: TResource, b: TResource) => { + if (a?.joinResource?.compositeKey !== b?.joinResource?.compositeKey) { + return false; + } + const oldJoinResource = ObjectUtil.clone(a?.joinResource); + delete oldJoinResource.compositeKey; + delete oldJoinResource.creation; + delete oldJoinResource.lastUpdate; + const newJoinResource = ObjectUtil.clone(b?.joinResource); + delete newJoinResource.compositeKey; + delete newJoinResource.creation; + delete newJoinResource.lastUpdate; + return JSON.stringify(oldJoinResource) === JSON.stringify(newJoinResource); + }); + + listActionToUpdate = diffCommon.presentOnlyInArrayB.map(resource => ({ + action: MultiRelation2TiersActionHelper.updateRelation<URelation>(this._nameSpace, action.parentId, resource.resId, resource.joinResource), + subActionCompletions: [ + this._actions$.pipe(ofSolidifyActionCompleted(this._nameSpace.UpdateRelationSuccess)), + this._actions$.pipe(ofSolidifyActionCompleted(this._nameSpace.UpdateRelationFail)), + ], + })); + } + + listActions.push(...listActionToAdd); + listActions.push(...listActionToUpdate); + listActions.push(...listActionToDelete); + + if (isNonEmptyArray(listActions)) { + return StoreUtil.dispatchSequentialActionAndWaitForSubActionsCompletion( + ctx, + listActions, + ).pipe( + map(result => result.success), + ); + } + return of(true); + } + + @RegisterDefaultAction((multiRelation2TiersNameSpace: MultiRelation2TiersNameSpace) => multiRelation2TiersNameSpace.UpdateSuccess) + updateSuccess(ctx: SolidifyStateContext<MultiRelation2TiersStateModel<TResource>>, action: MultiRelation2TiersAction.UpdateSuccess<TResource, URelation>): void { + ctx.patchState({ + isLoadingCounter: ctx.getState().isLoadingCounter - 1, + selected: undefined, + }); + } + + @RegisterDefaultAction((multiRelation2TiersNameSpace: MultiRelation2TiersNameSpace) => multiRelation2TiersNameSpace.UpdateFail) + updateFail(ctx: SolidifyStateContext<MultiRelation2TiersStateModel<TResource>>, action: MultiRelation2TiersAction.UpdateFail<TResource, URelation>): void { + ctx.patchState({ + isLoadingCounter: ctx.getState().isLoadingCounter - 1, + }); + ctx.dispatch(MultiRelation2TiersActionHelper.getAll(this._nameSpace, action.parentId)); + } +} diff --git a/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/public_api.ts b/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/public_api.ts new file mode 100644 index 0000000000000000000000000000000000000000..cabad77e5e0a34c91a898645ff10f68b2e08ada0 --- /dev/null +++ b/projects/solidify-frontend/src/lib/core/stores/abstract/multi-relation-2-tiers/public_api.ts @@ -0,0 +1,32 @@ +/*- + * %%---------------------------------------------------------------------------------------------- + * Solidify Framework - Solidify Frontend - public_api.ts + * SPDX-License-Identifier: GPL-2.0-or-later + * %----------------------------------------------------------------------------------------------% + * Copyright (C) 2017 - 2024 University of Geneva + * %----------------------------------------------------------------------------------------------% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-2.0.html>. + * ----------------------------------------------------------------------------------------------%% + */ + + +export * from "./multi-relation-2-tiers.action"; +export * from "./multi-relation-2-tiers.state"; +export * from "./multi-relation-2-tiers-action.helper"; +export * from "./multi-relation-2-tiers-namespace.model"; +export * from "./multi-relation-2-tiers-options.model"; +export * from "./multi-relation-2-tiers-state.model"; + + diff --git a/projects/solidify-frontend/src/lib/core/stores/public_api.ts b/projects/solidify-frontend/src/lib/core/stores/public_api.ts index 97353baeac518966327fb208b6955fd46ea57c45..2d38c1c9b471345b5e0fec10b0c9c9fcbefe3663 100644 --- a/projects/solidify-frontend/src/lib/core/stores/public_api.ts +++ b/projects/solidify-frontend/src/lib/core/stores/public_api.ts @@ -27,6 +27,7 @@ export * from "./abstract/association-no-sql-read-only/public_api"; export * from "./abstract/association-remote/public_api"; export * from "./abstract/association/public_api"; export * from "./abstract/composition/public_api"; +export * from "./abstract/multi-relation-2-tiers/public_api"; export * from "./abstract/relation-2-tiers/public_api"; export * from "./abstract/relation-3-tiers/public_api"; export * from "./abstract/resource/public_api"; diff --git a/projects/solidify-frontend/src/lib/core/utils/array.util.ts b/projects/solidify-frontend/src/lib/core/utils/array.util.ts index 000f510a41c709e156eb1586e3c280b8abd241ae..c166d75453b877b853e75260f0758a045d58812d 100644 --- a/projects/solidify-frontend/src/lib/core/utils/array.util.ts +++ b/projects/solidify-frontend/src/lib/core/utils/array.util.ts @@ -54,7 +54,7 @@ export class ArrayUtil { * @param arrayA * @param arrayB */ - static diff<T>(arrayA: T[], arrayB: T[], comparator: (a: T, b, T) => boolean = undefined): ArrayDiffResult<T> { + static diff<T>(arrayA: T[], arrayB: T[], comparator: (a: T, b: T) => boolean = undefined): ArrayDiffResult<T> { /* eslint-disable no-console */ if (isNullOrUndefined(arrayA)) { console.warn("'arrayA' param should not be null"); diff --git a/projects/solidify-frontend/src/lib/core/utils/stores/memoized.util.ts b/projects/solidify-frontend/src/lib/core/utils/stores/memoized.util.ts index 4919c47332aec217dcd21d10d5b20ba2e58b4c13..89551a50efbf5fb28c65df580b167890ddeaf792 100644 --- a/projects/solidify-frontend/src/lib/core/utils/stores/memoized.util.ts +++ b/projects/solidify-frontend/src/lib/core/utils/stores/memoized.util.ts @@ -47,6 +47,8 @@ import {AssociationState} from "../../stores/abstract/association/association.st import {BasicState} from "../../stores/abstract/base/basic.state"; import {CompositionStateModel} from "../../stores/abstract/composition/composition-state.model"; import {CompositionState} from "../../stores/abstract/composition/composition.state"; +import {MultiRelation2TiersStateModel} from "../../stores/abstract/multi-relation-2-tiers/multi-relation-2-tiers-state.model"; +import {MultiRelation2TiersState} from "../../stores/abstract/multi-relation-2-tiers/multi-relation-2-tiers.state"; import {Relation2TiersStateModel} from "../../stores/abstract/relation-2-tiers/relation-2-tiers-state.model"; import {Relation2TiersState} from "../../stores/abstract/relation-2-tiers/relation-2-tiers.state"; import {Relation3TiersStateModel} from "../../stores/abstract/relation-3-tiers/relation-3-tiers-state.model"; @@ -117,6 +119,7 @@ export class MemoizedUtil { static selected<TStateModel extends AssociationStateModel<TResource> | AssociationNoSqlReadOnlyStateModel<TResource> | AssociationRemoteStateModel<TResource> + | MultiRelation2TiersStateModel<TResource> | Relation2TiersStateModel<TResource> | Relation3TiersStateModel<TResource> , TResource extends BaseResourceType, TRelation extends BaseRelationResourceType>( @@ -124,6 +127,7 @@ export class MemoizedUtil { ctor: Type<AssociationState<TStateModel, TResource>> | Type<AssociationNoSqlReadOnlyState<TStateModel, TResource>> | Type<AssociationRemoteState<TStateModel, TResource>> + | Type<MultiRelation2TiersState<TStateModel, TResource, TRelation>> | Type<Relation2TiersState<TStateModel, TResource, TRelation>> | Type<Relation3TiersState<TStateModel, TResource, TRelation>>, ): Observable<TResource[]> { @@ -133,6 +137,7 @@ export class MemoizedUtil { static selectedSignal<TStateModel extends AssociationStateModel<TResource> | AssociationNoSqlReadOnlyStateModel<TResource> | AssociationRemoteStateModel<TResource> + | MultiRelation2TiersStateModel<TResource> | Relation2TiersStateModel<TResource> | Relation3TiersStateModel<TResource> , TResource extends BaseResourceType, TRelation extends BaseRelationResourceType>( @@ -140,6 +145,7 @@ export class MemoizedUtil { ctor: Type<AssociationState<TStateModel, TResource>> | Type<AssociationNoSqlReadOnlyState<TStateModel, TResource>> | Type<AssociationRemoteState<TStateModel, TResource>> + | Type<MultiRelation2TiersState<TStateModel, TResource, TRelation>> | Type<Relation2TiersState<TStateModel, TResource, TRelation>> | Type<Relation3TiersState<TStateModel, TResource, TRelation>>, ): Signal<TResource[]> { @@ -149,6 +155,7 @@ export class MemoizedUtil { static selectedSnapshot<TStateModel extends AssociationStateModel<TResource> | AssociationNoSqlReadOnlyStateModel<TResource> | AssociationRemoteStateModel<TResource> + | MultiRelation2TiersStateModel<TResource> | Relation2TiersStateModel<TResource> | Relation3TiersStateModel<TResource> , TResource extends BaseResourceType, TRelation extends BaseRelationResourceType>( @@ -156,6 +163,7 @@ export class MemoizedUtil { ctor: Type<AssociationState<TStateModel, TResource>> | Type<AssociationNoSqlReadOnlyState<TStateModel, TResource>> | Type<AssociationRemoteState<TStateModel, TResource>> + | Type<MultiRelation2TiersState<TStateModel, TResource, TRelation>> | Type<Relation2TiersState<TStateModel, TResource, TRelation>> | Type<Relation3TiersState<TStateModel, TResource, TRelation>>, ): TResource[] { @@ -291,6 +299,7 @@ export type MemoizedUtilState<TResource extends BaseResourceType> = AssociationS | AssociationNoSqlReadOnlyStateModel<TResource> | AssociationRemoteStateModel<TResource> | CompositionStateModel<TResource> + | MultiRelation2TiersStateModel<TResource> | Relation2TiersStateModel<TResource> | Relation3TiersStateModel<TResource> | ResourceStateModel<TResource> @@ -303,6 +312,7 @@ export type MemoizedUtilStateType<TStateModel extends MemoizedUtilState<TResourc | Type<AssociationNoSqlReadOnlyState<TStateModel, TResource>> | Type<AssociationRemoteState<TStateModel, TResource>> | Type<CompositionState<TStateModel, TResource>> + | Type<MultiRelation2TiersState<TStateModel, TResource, TRelation>> | Type<Relation2TiersState<TStateModel, TResource, TRelation>> | Type<Relation3TiersState<TStateModel, TResource, TRelation>> | Type<ResourceState<TStateModel, TResource>>; diff --git a/projects/solidify-frontend/src/lib/core/utils/string.util.ts b/projects/solidify-frontend/src/lib/core/utils/string.util.ts index 65094ac018e635bb58d7fe5506873e340f8da1ee..0a0c2e2e4ce5e921ef9ddd58218377739231cd2a 100644 --- a/projects/solidify-frontend/src/lib/core/utils/string.util.ts +++ b/projects/solidify-frontend/src/lib/core/utils/string.util.ts @@ -34,14 +34,14 @@ export class StringUtil { static format(str: string, ...val: string[]): string { for (let i = 0; i < val.length; i++) { - str = StringUtil.replaceAll(str, `{${i}}`, val[i]); + str = this.replaceAll(str, `{${i}}`, val[i]); } return str; } static formatKeyValue(str: string, ...val: KeyValue[]): string { val.forEach(v => { - str = StringUtil.replaceAll(str, `{${v.key}}`, v.value); + str = this.replaceAll(str, `{${v.key}}`, v.value); }); return str; } @@ -58,12 +58,12 @@ export class StringUtil { } static convertSpinalCaseToPascalCase(origin: string): string { - origin = origin.replace("-", " "); + origin = this.replaceAll(origin, "-", " "); return ChangeCase.pascalCase(origin); } static convertSpinalCaseToCamelCase(origin: string): string { - origin = origin.replace("-", " "); + origin = this.replaceAll(origin, "-", " "); return ChangeCase.camelCase(origin); } @@ -80,7 +80,7 @@ export class StringUtil { * @param origin */ static convertToSpinalCase(origin: string): string { - origin = origin.replace(" ", "-"); + origin = this.replaceAll(origin, " ", "-"); return ChangeCase.kebabCase(origin); } @@ -89,7 +89,7 @@ export class StringUtil { * @param origin */ static convertToSnakeCase(origin: string): string { - origin = origin.replace(" ", "_"); + origin = this.replaceAll(origin, " ", "_"); return ChangeCase.snakeCase(origin); } @@ -101,6 +101,16 @@ export class StringUtil { return ChangeCase.pascalCase(origin); } + /** + * Two words + * @param value + */ + static convertToSentence(value: string): string { + value = StringUtil.convertToSnakeCase(value); + value = StringUtil.capitalize(value); + return this.replaceAll(value, "_", " "); + } + static replaceAll(str: string, oldChar: string, newChar: string): string { const strSplitter = str.split(oldChar); return strSplitter.join(newChar); @@ -110,7 +120,7 @@ export class StringUtil { if (isNullOrUndefined(value)) { return value; } - value = StringUtil.replaceAll(value, "’", "'"); + value = this.replaceAll(value, "’", "'"); return value .normalize("NFD") // Unicode normalization (decomposition of accented characters) .replace(/[\u0300-\u036f]/g, "") // Remove diacritical marks @@ -121,15 +131,15 @@ export class StringUtil { if (isNullOrUndefined(value)) { return value; } - value = StringUtil.replaceAll(value, "\\", replacementChar); - value = StringUtil.replaceAll(value, "/", replacementChar); - value = StringUtil.replaceAll(value, ":", replacementChar); - value = StringUtil.replaceAll(value, "*", replacementChar); - value = StringUtil.replaceAll(value, "?", replacementChar); - value = StringUtil.replaceAll(value, "\"", replacementChar); - value = StringUtil.replaceAll(value, "<", replacementChar); - value = StringUtil.replaceAll(value, ">", replacementChar); - value = StringUtil.replaceAll(value, "|", replacementChar); + value = this.replaceAll(value, "\\", replacementChar); + value = this.replaceAll(value, "/", replacementChar); + value = this.replaceAll(value, ":", replacementChar); + value = this.replaceAll(value, "*", replacementChar); + value = this.replaceAll(value, "?", replacementChar); + value = this.replaceAll(value, "\"", replacementChar); + value = this.replaceAll(value, "<", replacementChar); + value = this.replaceAll(value, ">", replacementChar); + value = this.replaceAll(value, "|", replacementChar); return value; } }