From d90298c159827f827312bac5882380c882a4dc8a Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Tue, 22 Aug 2023 15:11:11 +0800 Subject: [PATCH] BREAKING Typed `NaturalAbstractDetail.data` #9819 `NaturalAbstractDetail.data` is implicitly typed with the result of `service.resolve()`. If needed that type can be widened by specifying a type for extra properties in the generic, like so: ```ts class MyComponent extends NaturalAbstractDetail { } ``` `getConsolidatedForClient()` was dropped entirely without a replacement. It should never be used in our projects (and it was not). `getDefaultForClient()` was renamed into `getFormExtraFieldDefaultValues()` to better reflect its usage. It should never be called in projects, only within Natural itself. Projects were updated to instead call `getDefaultForServer()`. The overall behavior of both `NaturalAbstractModelService` and `NaturalAbstractDetail` is intact. --- package.json | 1 + projects/natural-editor/tsconfig.lib.json | 2 +- .../src/lib/classes/abstract-detail.ts | 39 +++++++++++++++---- .../src/lib/classes/abstract-editable-list.ts | 2 +- .../src/lib/classes/validators.spec.ts | 16 ++------ .../natural/src/lib/classes/validators.ts | 4 +- .../src/lib/modules/common/public-api.ts | 1 + .../modules/common/services/seo.service.ts | 11 ++++++ .../type-hierarchic-selector.component.ts | 5 +-- .../type-natural-select.component.ts | 9 ++--- .../classes/hierarchic-configuration.ts | 8 ++-- .../lib/services/abstract-model.service.ts | 28 +++++++------ .../natural/src/lib/testing/item.service.ts | 8 ++-- .../natural/src/lib/testing/null.service.ts | 2 +- .../natural/src/lib/testing/post.service.ts | 2 +- projects/natural/src/lib/types/types.ts | 14 +++++++ projects/natural/src/public-api.ts | 17 +++++++- projects/natural/tsconfig.lib.json | 2 +- src/app/detail/detail.component.html | 2 +- src/app/detail/detail.component.ts | 16 +++++++- src/app/relations/relations.component.html | 2 +- src/app/relations/relations.component.ts | 3 +- src/app/search/search.component.ts | 20 ++-------- tsconfig.json | 4 +- yarn.lock | 5 +++ 25 files changed, 143 insertions(+), 80 deletions(-) diff --git a/package.json b/package.json index d33b8515..f295be04 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "prosemirror-view": "^1.31.5", "rxjs": "^7.8.1", "tslib": "^2.5.3", + "type-fest": "^4.2.0", "zone.js": "~0.13.1" }, "devDependencies": { diff --git a/projects/natural-editor/tsconfig.lib.json b/projects/natural-editor/tsconfig.lib.json index 840f598e..d374180d 100644 --- a/projects/natural-editor/tsconfig.lib.json +++ b/projects/natural-editor/tsconfig.lib.json @@ -7,7 +7,7 @@ "declarationMap": true, "inlineSources": true, "types": [], - "lib": ["dom", "es2018"] + "lib": ["dom", "ES2022"] }, "exclude": ["src/test.ts", "**/*.spec.ts"] } diff --git a/projects/natural/src/lib/classes/abstract-detail.ts b/projects/natural/src/lib/classes/abstract-detail.ts index ceae36ed..14027341 100644 --- a/projects/natural/src/lib/classes/abstract-detail.ts +++ b/projects/natural/src/lib/classes/abstract-detail.ts @@ -5,7 +5,7 @@ import {kebabCase, merge, mergeWith, omit} from 'lodash-es'; import {NaturalAlertService} from '../modules/alert/alert.service'; import {NaturalAbstractPanel} from '../modules/panels/abstract-panel'; import {NaturalAbstractModelService} from '../services/abstract-model.service'; -import {ExtractTcreate, ExtractTone, ExtractTupdate, Literal} from '../types/types'; +import {ExtractResolve, ExtractTcreate, ExtractTone, ExtractTupdate, Literal} from '../types/types'; import {finalize} from 'rxjs/operators'; import {ifValid, validateAllFormControls} from './validators'; import {mergeOverrideArray} from './utility'; @@ -13,11 +13,17 @@ import {PaginatedData} from './data-source'; import {QueryVariables} from './query-variable-manager'; import {EMPTY, endWith, last, Observable, switchMap} from 'rxjs'; +/** + * `Data` contains in `model` either the model fetched from DB or default values (without ID). And besides `model`, + * any other extra keys defined by Extra. + */ +type Data = {model: {id?: string}} & ExtractResolve & Extra; + // @dynamic @Directive() export class NaturalAbstractDetail< TService extends NaturalAbstractModelService< - unknown, + {id: string}, any, PaginatedData, QueryVariables, @@ -28,6 +34,7 @@ export class NaturalAbstractDetail< unknown, any >, + ExtraResolve extends Literal = Record, > extends NaturalAbstractPanel implements OnInit @@ -35,9 +42,9 @@ export class NaturalAbstractDetail< /** * Empty placeholder for data retrieved by the server */ - public override data: any = { - model: {}, - }; + public override data: Data = { + model: this.service.getDefaultForServer(), + } as Data; /** * Form that manages the data from the controller @@ -65,6 +72,13 @@ export class NaturalAbstractDetail< */ protected readonly route = inject(ActivatedRoute); + /** + * Once set, this must not change anymore, especially not right after the creation mutation, + * so the form does not switch from creation mode to update mode without an actual reload of + * model from DB (by navigating to update page). + */ + #updatePage = false; + public constructor(protected readonly key: string, public readonly service: TService) { super(); } @@ -72,8 +86,9 @@ export class NaturalAbstractDetail< public ngOnInit(): void { if (!this.isPanel) { this.route.data.subscribe(data => { - this.data = merge({model: this.service.getConsolidatedForClient()}, data[this.key]); + this.data = merge({model: this.service.getDefaultForServer()}, data[this.key]); this.data = merge(this.data, omit(data, [this.key])); + this.#updatePage = !!this.data.model.id; this.initForm(); }); } else { @@ -85,8 +100,18 @@ export class NaturalAbstractDetail< this.showFabButton = index === 0; } + /** + * Returns whether `data.model` was fetched from DB, so we are on an update page, or if it is a new object + * with (only) default values, so we are on a creation page. + * + * This should be used instead of checking `data.model.id` directly, in order to type guard and get proper typing + */ + protected isUpdatePage(): this is {data: {model: ExtractTone}} { + return this.#updatePage; + } + public update(now = false): void { - if (!this.data.model.id) { + if (!this.isUpdatePage()) { return; } diff --git a/projects/natural/src/lib/classes/abstract-editable-list.ts b/projects/natural/src/lib/classes/abstract-editable-list.ts index 2860d460..89fa47c6 100644 --- a/projects/natural/src/lib/classes/abstract-editable-list.ts +++ b/projects/natural/src/lib/classes/abstract-editable-list.ts @@ -75,7 +75,7 @@ export class NaturalAbstractEditableList< */ public addItems(items: readonly T[]): void { items.forEach(item => { - const completedItem = merge(this.service.getConsolidatedForClient(), item); + const completedItem = merge(this.service.getDefaultForServer(), item); const lineFormGroup = this.service.getFormGroup(completedItem); this.formArray.push(lineFormGroup); }); diff --git a/projects/natural/src/lib/classes/validators.spec.ts b/projects/natural/src/lib/classes/validators.spec.ts index 1ea85797..0b5f37d4 100644 --- a/projects/natural/src/lib/classes/validators.spec.ts +++ b/projects/natural/src/lib/classes/validators.spec.ts @@ -1,13 +1,4 @@ -import { - available, - decimal, - deliverableEmail, - ifValid, - integer, - NaturalAbstractModelService, - unique, - urlValidator, -} from '@ecodev/natural'; +import {available, decimal, deliverableEmail, ifValid, integer, unique, urlValidator} from '@ecodev/natural'; import { AsyncValidatorFn, FormControl, @@ -19,6 +10,7 @@ import { import {TestScheduler} from 'rxjs/testing'; import {concat, forkJoin, NEVER, Observable, of, Subject, tap} from 'rxjs'; import {first} from 'rxjs/operators'; +import {UntypedModelService} from '../types/types'; function validate(validatorFn: ValidatorFn, expected: boolean, value: any): void { const control = new FormControl(); @@ -97,9 +89,7 @@ describe('unique', () => { cases.forEach(parameters => { it('with ' + JSON.stringify(parameters), done => { - const service = jasmine.createSpyObj< - NaturalAbstractModelService - >('NaturalAbstractModelService', ['count']); + const service = jasmine.createSpyObj('NaturalAbstractModelService', ['count']); service.count.and.returnValue(concat(of(parameters[1]), parameters[2] ? NEVER : NEVER)); const validator = unique('id', null, service); diff --git a/projects/natural/src/lib/classes/validators.ts b/projects/natural/src/lib/classes/validators.ts index db9372cd..8fd9145f 100644 --- a/projects/natural/src/lib/classes/validators.ts +++ b/projects/natural/src/lib/classes/validators.ts @@ -10,15 +10,15 @@ import { } from '@angular/forms'; import {Observable, of, timer} from 'rxjs'; import {filter, first, map, switchMap} from 'rxjs/operators'; -import {NaturalAbstractModelService} from '../services/abstract-model.service'; import {NaturalQueryVariablesManager, QueryVariables} from './query-variable-manager'; import {validTlds} from './tld'; import {FilterGroupCondition} from '../modules/search/classes/graphql-doctrine.types'; +import {UntypedModelService} from '../types/types'; /** * Returns an async validator function that checks that the form control value is unique */ -export function unique>( +export function unique( fieldName: string, excludedId: string | null | undefined, modelService: TService, diff --git a/projects/natural/src/lib/modules/common/public-api.ts b/projects/natural/src/lib/modules/common/public-api.ts index f22d1f71..5892e897 100644 --- a/projects/natural/src/lib/modules/common/public-api.ts +++ b/projects/natural/src/lib/modules/common/public-api.ts @@ -18,5 +18,6 @@ export { NaturalSeoBasic, NaturalSeoResolve, NaturalSeoCallback, + NaturalSeoResolveData, } from './services/seo.service'; export {provideSeo} from './services/seo.provider'; diff --git a/projects/natural/src/lib/modules/common/services/seo.service.ts b/projects/natural/src/lib/modules/common/services/seo.service.ts index 2d880d89..6800ba6a 100644 --- a/projects/natural/src/lib/modules/common/services/seo.service.ts +++ b/projects/natural/src/lib/modules/common/services/seo.service.ts @@ -42,6 +42,17 @@ export type NaturalSeoResolve = Robots & { */ export type NaturalSeoCallback = (routeData: Data) => NaturalSeoBasic; +/** + * Typically used to type the routing data received in the component, eg: + * + * ```ts + * class MyComponent extends NaturalAbstractDetail {} + * ``` + */ +export type NaturalSeoResolveData = { + seo: NaturalSeoBasic; +}; + interface Robots { /** * If given will be used as robots meta tag, otherwise fallback on default value diff --git a/projects/natural/src/lib/modules/dropdown-components/type-hierarchic-selector/type-hierarchic-selector.component.ts b/projects/natural/src/lib/modules/dropdown-components/type-hierarchic-selector/type-hierarchic-selector.component.ts index f63d0a1c..1013941a 100644 --- a/projects/natural/src/lib/modules/dropdown-components/type-hierarchic-selector/type-hierarchic-selector.component.ts +++ b/projects/natural/src/lib/modules/dropdown-components/type-hierarchic-selector/type-hierarchic-selector.component.ts @@ -1,7 +1,6 @@ import {Component} from '@angular/core'; import {NaturalQueryVariablesManager} from '../../../classes/query-variable-manager'; -import {NaturalAbstractModelService} from '../../../services/abstract-model.service'; -import {Literal} from '../../../types/types'; +import {UntypedModelService, Literal} from '../../../types/types'; import {NaturalHierarchicConfiguration} from '../../hierarchic-selector/classes/hierarchic-configuration'; import {OrganizedModelSelection} from '../../hierarchic-selector/hierarchic-selector/hierarchic-selector.service'; import {FilterGroupConditionField} from '../../search/classes/graphql-doctrine.types'; @@ -24,7 +23,7 @@ export type HierarchicFiltersConfiguration = Array; + service: UntypedModelService; config: NaturalHierarchicConfiguration[]; filters?: HierarchicFiltersConfiguration; } diff --git a/projects/natural/src/lib/modules/dropdown-components/type-natural-select/type-natural-select.component.ts b/projects/natural/src/lib/modules/dropdown-components/type-natural-select/type-natural-select.component.ts index c23a17e2..f9c29839 100644 --- a/projects/natural/src/lib/modules/dropdown-components/type-natural-select/type-natural-select.component.ts +++ b/projects/natural/src/lib/modules/dropdown-components/type-natural-select/type-natural-select.component.ts @@ -1,7 +1,6 @@ import {Component} from '@angular/core'; -import {NaturalAbstractModelService} from '../../../services/abstract-model.service'; import {FilterGroupConditionField} from '../../search/classes/graphql-doctrine.types'; -import {ExtractTone, ExtractVall} from '../../../types/types'; +import {ExtractTone, ExtractVall, UntypedModelService} from '../../../types/types'; import {AbstractAssociationSelectComponent} from '../abstract-association-select-component.directive'; import {EMPTY, Observable} from 'rxjs'; import {NaturalSelectComponent} from '../../select/select/select.component'; @@ -11,9 +10,7 @@ import {MatSelectModule} from '@angular/material/select'; import {MatFormFieldModule} from '@angular/material/form-field'; import {FormsModule, ReactiveFormsModule} from '@angular/forms'; -export interface TypeSelectNaturalConfiguration< - TService extends NaturalAbstractModelService, -> { +export interface TypeSelectNaturalConfiguration { service: TService; placeholder: string; filter?: ExtractVall['filter']; @@ -33,7 +30,7 @@ export interface TypeSelectNaturalConfiguration< ], }) export class TypeNaturalSelectComponent< - TService extends NaturalAbstractModelService, + TService extends UntypedModelService, > extends AbstractAssociationSelectComponent> { public getCondition(): FilterGroupConditionField { if (!this.isValid()) { diff --git a/projects/natural/src/lib/modules/hierarchic-selector/classes/hierarchic-configuration.ts b/projects/natural/src/lib/modules/hierarchic-selector/classes/hierarchic-configuration.ts index f1d2036c..8646d202 100644 --- a/projects/natural/src/lib/modules/hierarchic-selector/classes/hierarchic-configuration.ts +++ b/projects/natural/src/lib/modules/hierarchic-selector/classes/hierarchic-configuration.ts @@ -1,10 +1,8 @@ import {Type} from '@angular/core'; import {QueryVariables} from '../../../classes/query-variable-manager'; -import {NaturalAbstractModelService} from '../../../services/abstract-model.service'; +import {UntypedModelService} from '../../../types/types'; -type GenericModelService = NaturalAbstractModelService; - -export interface NaturalHierarchicConfiguration { +export interface NaturalHierarchicConfiguration { /** * An AbstractModelService to be used to fetch items */ @@ -66,7 +64,7 @@ export interface NaturalHierarchicConfiguration string; } -export interface NaturalHierarchicServiceConfiguration +export interface NaturalHierarchicServiceConfiguration extends NaturalHierarchicConfiguration { injectedService: T; } diff --git a/projects/natural/src/lib/services/abstract-model.service.ts b/projects/natural/src/lib/services/abstract-model.service.ts index 0054a5f4..dea3d0a0 100644 --- a/projects/natural/src/lib/services/abstract-model.service.ts +++ b/projects/natural/src/lib/services/abstract-model.service.ts @@ -61,10 +61,6 @@ export abstract class NaturalAbstractModelService< protected readonly deleteMutation: DocumentNode | null, ) {} - public getConsolidatedForClient(): (Vcreate['input'] | Vupdate['input']) & Literal { - return Object.assign(this.getDefaultForServer(), this.getDefaultForClient()); - } - /** * List of individual fields validators */ @@ -98,7 +94,7 @@ export abstract class NaturalAbstractModelService< } public getFormConfig(model: Literal): FormControls { - const values = this.getConsolidatedForClient(); + const values = {...this.getDefaultForServer(), ...this.getFormExtraFieldDefaultValues()}; const validators = this.getFormValidators(model); const asyncValidators = this.getFormAsyncValidators(model); const controls: FormControls = {}; @@ -455,13 +451,13 @@ export abstract class NaturalAbstractModelService< /** * Resolve model and items related to the model, if the id is provided, in order to show a form */ - public resolve(id: string): Observable> { + public resolve(id: string): Observable> { // Load model if id is given - let observable: Observable; + let observable: Observable; if (id) { observable = this.getOne(id); } else { - observable = of(this.getConsolidatedForClient() as Tone); + observable = of(this.getDefaultForServer() as Tone); } return observable.pipe( @@ -528,16 +524,24 @@ export abstract class NaturalAbstractModelService< * * This is typically useful when showing a form for creation */ - protected getDefaultForServer(): Vcreate['input'] | Vupdate['input'] { + public getDefaultForServer(): Vcreate['input'] { return {}; } /** - * Return empty object with some default values from frontend perspective + * You probably **should not** use this. + * + * If you are trying to *call* this method, instead you probably want to call `getDefaultForServer()` to get default + * values for a model, or `getFormConfig()` to get a configured form that includes extra form fields. + * + * If you are trying to *override* this method, instead you probably want to override `getDefaultForServer()`. * - * Where empty object must respect graphql XXXInput type, may need some default values for other fields + * The only and **very rare** reason to override this method is if the client needs extra form fields that cannot be + * accepted by the server (not part of `XXXInput` type) and that are strictly for the client form needs. In that case, + * then you can return default values for those extra form fields, and the form returned by `getFormConfig()` will + * include those extra fields. */ - protected getDefaultForClient(): Literal { + protected getFormExtraFieldDefaultValues(): Literal { return {}; } diff --git a/projects/natural/src/lib/testing/item.service.ts b/projects/natural/src/lib/testing/item.service.ts index ebc6f6a6..18aa6020 100644 --- a/projects/natural/src/lib/testing/item.service.ts +++ b/projects/natural/src/lib/testing/item.service.ts @@ -20,6 +20,8 @@ export interface Item { readonly parent: Item | null; } +export type ItemInput = Omit; + @Injectable({ providedIn: 'root', }) @@ -29,9 +31,9 @@ export class ItemService extends NaturalAbstractModelService< PaginatedData, QueryVariables, Item, - {input: Item}, + {input: ItemInput}, Item, - {id: string; input: Literal}, + {id: string; input: Partial}, boolean, {ids: string[]} > { @@ -103,7 +105,7 @@ export class ItemService extends NaturalAbstractModelService< return of(this.getItem(true, 2, id)); } - protected override getDefaultForClient(): Literal { + protected override getFormExtraFieldDefaultValues(): Literal { return { name: '', description: '', diff --git a/projects/natural/src/lib/testing/null.service.ts b/projects/natural/src/lib/testing/null.service.ts index 2be430fe..f10eb091 100644 --- a/projects/natural/src/lib/testing/null.service.ts +++ b/projects/natural/src/lib/testing/null.service.ts @@ -26,7 +26,7 @@ export class NullService extends NaturalAbstractModelService< super(apollo, naturalDebounceService, 'user', null, null, createPost, null, null); } - protected override getDefaultForServer(): PostInput { + public override getDefaultForServer(): PostInput { return { slug: '', blog: '', diff --git a/projects/natural/src/lib/testing/post.service.ts b/projects/natural/src/lib/testing/post.service.ts index 6941b079..a7ea1702 100644 --- a/projects/natural/src/lib/testing/post.service.ts +++ b/projects/natural/src/lib/testing/post.service.ts @@ -25,7 +25,7 @@ export class PostService extends NaturalAbstractModelService< super(apollo, naturalDebounceService, 'post', postQuery, postsQuery, createPost, updatePost, deletePosts); } - protected override getDefaultForServer(): PostInput { + public override getDefaultForServer(): PostInput { return { slug: '', blog: '', diff --git a/projects/natural/src/lib/types/types.ts b/projects/natural/src/lib/types/types.ts index 3482742e..afe0fc49 100644 --- a/projects/natural/src/lib/types/types.ts +++ b/projects/natural/src/lib/types/types.ts @@ -1,6 +1,7 @@ import {PaginatedData} from '../classes/data-source'; import {NaturalAbstractModelService, VariablesWithInput} from '../services/abstract-model.service'; import {QueryVariables} from '../classes/query-variable-manager'; +import {ObservedValueOf} from 'rxjs'; /** * An object literal with any keys and values @@ -235,3 +236,16 @@ export type ExtractVdelete

= P extends NaturalAbstractModelService< ? Vdelete : never : never; + +/** + * Extract the resolve type from a NaturalAbstractModelService + */ +export type ExtractResolve

= P extends NaturalAbstractModelService + ? ObservedValueOf> + : never; + +/** + * This should be avoided if possible, and instead use a more precise type with some constraints on it to ensure that the model + * service is able to fulfill its requirements. + */ +export type UntypedModelService = NaturalAbstractModelService; diff --git a/projects/natural/src/public-api.ts b/projects/natural/src/public-api.ts index f9715cee..12e16486 100644 --- a/projects/natural/src/public-api.ts +++ b/projects/natural/src/public-api.ts @@ -25,7 +25,22 @@ export * from './lib/services/link-mutation.service'; export {NaturalPersistenceService, NATURAL_PERSISTENCE_VALIDATOR} from './lib/services/persistence.service'; export * from './lib/services/swiss-parsing-date-adapter.service'; -export * from './lib/types/types'; +export { + Literal, + NameOrFullName, + ExtractTone, + ExtractVone, + ExtractTall, + ExtractTallOne, + ExtractVall, + ExtractTcreate, + ExtractVcreate, + ExtractTupdate, + ExtractVupdate, + ExtractTdelete, + ExtractVdelete, + ExtractResolve, +} from './lib/types/types'; export * from './lib/modules/alert/public-api'; export * from './lib/modules/columns-picker/public-api'; diff --git a/projects/natural/tsconfig.lib.json b/projects/natural/tsconfig.lib.json index 25fb4409..4bca3b86 100644 --- a/projects/natural/tsconfig.lib.json +++ b/projects/natural/tsconfig.lib.json @@ -5,7 +5,7 @@ "declaration": true, "inlineSources": true, "types": [], - "lib": ["dom", "es2018"], + "lib": ["dom", "ES2022"], "declarationMap": true }, "angularCompilerOptions": { diff --git a/src/app/detail/detail.component.html b/src/app/detail/detail.component.html index 55a661df..3ab5458a 100644 --- a/src/app/detail/detail.component.html +++ b/src/app/detail/detail.component.html @@ -27,7 +27,7 @@

NaturalAbstractDetail

- diff --git a/src/app/detail/detail.component.ts b/src/app/detail/detail.component.ts index 66d07263..cb055262 100644 --- a/src/app/detail/detail.component.ts +++ b/src/app/detail/detail.component.ts @@ -1,6 +1,6 @@ import {Component, OnInit} from '@angular/core'; import {collectErrors, NaturalAbstractDetail} from '@ecodev/natural'; -import {ItemService} from '../../../projects/natural/src/lib/testing/item.service'; +import {Item, ItemInput, ItemService} from '../../../projects/natural/src/lib/testing/item.service'; import {NaturalFixedButtonDetailComponent} from '../../../projects/natural/src/lib/modules/fixed-button-detail/fixed-button-detail.component'; import {CommonModule} from '@angular/common'; import {MatInputModule} from '@angular/material/input'; @@ -39,5 +39,19 @@ export class DetailComponent extends NaturalAbstractDetail implemen public constructor(service: ItemService) { super('detail', service); + + if (this.isUpdatePage()) { + this.doSomethingWithFetchedModel(this.data.model); + } else { + this.doSomethingWithDefaultValues(this.data.model); + } + } + + private doSomethingWithFetchedModel(model: Item): string { + return model.id; + } + + private doSomethingWithDefaultValues(model: ItemInput): boolean { + return 'id' in model; } } diff --git a/src/app/relations/relations.component.html b/src/app/relations/relations.component.html index 537d620e..42721952 100644 --- a/src/app/relations/relations.component.html +++ b/src/app/relations/relations.component.html @@ -3,7 +3,7 @@

natural-relations

>Use ItemService.watchAll() that always returns 5 elements. Seems to be buggy but it's normal. -
+
Hierarchic selector
diff --git a/src/app/relations/relations.component.ts b/src/app/relations/relations.component.ts index 4da6347c..0c2e2653 100644 --- a/src/app/relations/relations.component.ts +++ b/src/app/relations/relations.component.ts @@ -6,13 +6,14 @@ import {NoResultService} from '../../../projects/natural/src/lib/testing/no-resu import {NaturalRelationsComponent} from '../../../projects/natural/src/lib/modules/relations/relations.component'; import {FormsModule, ReactiveFormsModule} from '@angular/forms'; import {FlexModule} from '@ngbracket/ngx-layout/flex'; +import {CommonModule} from '@angular/common'; @Component({ selector: 'app-relations', templateUrl: './relations.component.html', styleUrls: ['./relations.component.scss'], standalone: true, - imports: [FlexModule, FormsModule, ReactiveFormsModule, NaturalRelationsComponent], + imports: [FlexModule, FormsModule, ReactiveFormsModule, NaturalRelationsComponent, CommonModule], }) export class RelationsComponent extends NaturalAbstractDetail implements OnInit { public hierarchicConfig: NaturalHierarchicConfiguration[] = [ diff --git a/src/app/search/search.component.ts b/src/app/search/search.component.ts index fe48ddc9..0a7726de 100644 --- a/src/app/search/search.component.ts +++ b/src/app/search/search.component.ts @@ -1,12 +1,11 @@ import {CommonModule} from '@angular/common'; -import {Component, OnInit, Type} from '@angular/core'; +import {Component, OnInit} from '@angular/core'; import {MatButtonModule} from '@angular/material/button'; import {ActivatedRoute, Router} from '@angular/router'; import { DropdownFacet, Filter, fromUrl, - NaturalAbstractModelService, NaturalSearchFacets, NaturalSearchSelections, toGraphQLDoctrineFilter, @@ -131,23 +130,10 @@ export class SearchComponent implements OnInit { component: TypeHierarchicSelectorComponent, configuration: { key: 'any', - service: this.errorService as unknown as NaturalAbstractModelService< - any, - any, - any, - any, - any, - any, - any, - any, - any, - any - >, + service: this.errorService, config: [ { - service: ErrorService as unknown as Type< - NaturalAbstractModelService - >, + service: ErrorService, parentsRelationNames: ['parent'], childrenRelationNames: ['parent'], selectableAtKey: 'any', diff --git a/tsconfig.json b/tsconfig.json index 54a723e4..d8e46e86 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,7 +7,7 @@ "declaration": false, "downlevelIteration": true, "experimentalDecorators": true, - "module": "es2020", + "module": "ES2022", "moduleResolution": "node", "importHelpers": true, "target": "ES2022", @@ -16,7 +16,7 @@ "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "typeRoots": ["node_modules/@types"], - "lib": ["es2018", "dom"], + "lib": ["ES2022", "dom"], "paths": { "@ecodev/natural": ["projects/natural/src/public-api"], "@ecodev/natural-editor": ["projects/natural-editor/src/public-api"] diff --git a/yarn.lock b/yarn.lock index e7f071ee..e6f83b04 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8259,6 +8259,11 @@ type-fest@^0.21.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== +type-fest@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.2.0.tgz#e259430307710e77721ecf6f545840acad72195f" + integrity sha512-5zknd7Dss75pMSED270A1RQS3KloqRJA9XbXLe0eCxyw7xXFb3rd+9B0UQ/0E+LQT6lnrLviEolYORlRWamn4w== + type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"