diff --git a/packages/store/entity-store.ts b/packages/store/entity-store.ts index 0716fd2..70512ae 100644 --- a/packages/store/entity-store.ts +++ b/packages/store/entity-store.ts @@ -1,3 +1,4 @@ +import { toSignal } from '@angular/core/rxjs-interop'; import { Id, produce, ProducerOptions } from '@tethys/cdk/immutable'; import { isFunction } from '@tethys/cdk/is'; import { Observable } from 'rxjs'; @@ -13,6 +14,7 @@ import { import { Store } from './store'; import { PaginationInfo, StoreOptions, UpdateStatePredicate } from './types'; import { coerceArray } from './utils'; +import { Signal, computed } from '@angular/core'; export interface EntityStoreOptions extends ProducerOptions, StoreOptions { referencesIdKeys?: ReferenceArrayExtractAllowKeys; @@ -46,10 +48,16 @@ export class EntityStore, TEnti private isSingleEntity: boolean; + /** + * @deprecated 请使用 snapshot.entities + */ get entities() { return this.snapshot.entities; } + /** + * @deprecated 请使用 snapshot.entity + */ get entity() { return this.snapshot.entity; } @@ -58,10 +66,19 @@ export class EntityStore, TEnti return state.entities; }); + // 临时添加,后期使用 entities 替代你 + private entitiesSignal: Signal; + entity$ = this.select$((state) => { return state.entity; }); + // 临时添加,后期使用 entity 替代你 + private entitySignal: Signal; + + /** + * @deprecated 请使用 snapshot.activeId + */ get activeId(): Id | null { return this.snapshot.activeId || null; } @@ -70,6 +87,10 @@ export class EntityStore, TEnti return state.activeId || null; }); + /** + * @deprecated 请使用 snapshot + */ + get activeEntity(): TEntity | null { return this.snapshot.activeId ? this.getEntityById(this.snapshot.activeId) : null; } @@ -93,6 +114,14 @@ export class EntityStore, TEnti shareReplay(1) ); + entitiesWithRefs = computed(() => { + const entities = this.entitiesSignal(); + if (!entities) { + return entities; + } + return entities.map((entity) => this.buildRefs(entity)); + }); + entityWithRefs$ = this.entity$.pipe( map((entity) => { if (!entity) { @@ -103,6 +132,14 @@ export class EntityStore, TEnti shareReplay(1) ); + entityWithRefs = computed(() => { + const entity = this.entitySignal(); + if (!entity) { + return entity; + } + return this.buildRefs(entity); + }); + private buildRefs(entity: TEntity) { const newEntity = { ...entity }; if (this['onCombineRefs']) { @@ -156,6 +193,12 @@ export class EntityStore, TEnti throw new Error(`idKey is required in EntityStore`); } this.buildReferencesIdMap(); + this.entitiesSignal = toSignal(this.entities$); + this.entitySignal = toSignal(this.entity$); + // this.entities = toSignal(this.entities$); + // this.entity = toSignal(this.entity$); + // this.activeId = toSignal(this.activeId$); + // this.activeEntity = toSignal(this.activeEntity$); } /** @@ -426,7 +469,7 @@ export class EntityStore, TEnti this.next(state); } - private getEntityById(id: Id): TEntity | null { + protected getEntityById(id: Id): TEntity | null { if (this.isSingleEntity) { return (this.snapshot.entity[this.options.idKey] as Id) === id ? this.snapshot.entity : null; } else { diff --git a/packages/store/test/entity-store-refs.spec.ts b/packages/store/test/entity-store-refs.spec.ts index ee7ca02..2fca4da 100644 --- a/packages/store/test/entity-store-refs.spec.ts +++ b/packages/store/test/entity-store-refs.spec.ts @@ -22,9 +22,9 @@ describe('Store: EntityStore with refs', () => { updated_by?: string; refs?: { group?: GroupInfo; - created_by: UserInfo; + created_by?: UserInfo; project?: { _id: string; name: string }; - parents: string[]; + parents?: string[]; }; } @@ -67,8 +67,8 @@ describe('Store: EntityStore with refs', () => { } onCombineRefs(entity: TaskInfo, referencesIdMap: ReferencesIdDictionary, references: TaskReferences) { - entity.refs.group = referencesIdMap.groups[entity.group_id]; - entity.refs.created_by = referencesIdMap.users[entity.created_by]; + entity.refs.group = referencesIdMap.groups && referencesIdMap.groups[entity.group_id]; + entity.refs.created_by = referencesIdMap.users && referencesIdMap.users[entity.created_by]; } } @@ -164,7 +164,7 @@ describe('Store: EntityStore with refs', () => { const entitiesWithRefsSub = jasmine.createSpy('entitiesWithRefsSub'); tasksStore.entitiesWithRefs$.subscribe(entitiesWithRefsSub); expect(entitiesWithRefsSub).toHaveBeenCalledTimes(1); - expect(entitiesWithRefsSub).toHaveBeenCalledWith([ + const expectedEntitiesWithRefs: TaskInfo[] = [ { _id: 'task-1', title: 'task 1', @@ -185,12 +185,14 @@ describe('Store: EntityStore with refs', () => { created_by: { uid: '2', name: 'user 2' } } } - ]); + ]; + expect(entitiesWithRefsSub).toHaveBeenCalledWith(expectedEntitiesWithRefs); expect(tasksStore.snapshot.references).toEqual({ groups: initialGroups, users: initialUsers }); + expect(tasksStore.entitiesWithRefs()).toEqual(expectedEntitiesWithRefs); }); it('should get correct refs with directly visit references by entitiesWithRefs$', () => { @@ -198,6 +200,7 @@ describe('Store: EntityStore with refs', () => { _id: `project-new-1`, name: `project-new name 1` }; + const tasksStore = injectStoreForTest( TasksStore, { @@ -227,7 +230,7 @@ describe('Store: EntityStore with refs', () => { const entitiesWithRefsSub = jasmine.createSpy('entitiesWithRefsSub'); tasksStore.entitiesWithRefs$.subscribe(entitiesWithRefsSub); expect(entitiesWithRefsSub).toHaveBeenCalledTimes(1); - expect(entitiesWithRefsSub).toHaveBeenCalledWith([ + const expectedEntitiesWithRefs = [ { _id: 'task-1', title: 'task 1', @@ -246,7 +249,9 @@ describe('Store: EntityStore with refs', () => { project: project } } - ]); + ]; + expect(entitiesWithRefsSub).toHaveBeenCalledWith(expectedEntitiesWithRefs); + expect(tasksStore.entitiesWithRefs()).toEqual(expectedEntitiesWithRefs); }); describe('add', () => { @@ -543,10 +548,10 @@ describe('Store: EntityStore with refs', () => { } } ); - const entitiesWithRefsSub = jasmine.createSpy('entitiesWithRefsSub'); - taskDetailStore.entityWithRefs$.subscribe(entitiesWithRefsSub); - expect(entitiesWithRefsSub).toHaveBeenCalledTimes(1); - expect(entitiesWithRefsSub).toHaveBeenCalledWith({ + const entityWithRefsSub = jasmine.createSpy('entityWithRefs'); + taskDetailStore.entityWithRefs$.subscribe(entityWithRefsSub); + expect(entityWithRefsSub).toHaveBeenCalledTimes(1); + const expectedEntityWithRefs = { _id: 'task-3', title: 'task 3', group_id: 'group-1', @@ -555,12 +560,14 @@ describe('Store: EntityStore with refs', () => { group: { _id: 'group-1', name: 'group 1' }, created_by: { uid: '1', name: 'user 1' } } - }); + }; + expect(entityWithRefsSub).toHaveBeenCalledWith(expectedEntityWithRefs); expect(taskDetailStore.snapshot.references).toEqual({ groups: initialGroups, users: initialUsers }); + expect(taskDetailStore.entityWithRefs()).toEqual(expectedEntityWithRefs); }); it('should get correct refs with directly visit references by entitiesWithRefs$', () => { @@ -589,10 +596,10 @@ describe('Store: EntityStore with refs', () => { entity.refs.project = references.project; }; - const entitiesWithRefsSub = jasmine.createSpy('entitiesWithRefsSub'); - taskDetailStore.entityWithRefs$.subscribe(entitiesWithRefsSub); - expect(entitiesWithRefsSub).toHaveBeenCalledTimes(1); - expect(entitiesWithRefsSub).toHaveBeenCalledWith({ + const entityWithRefsSub = jasmine.createSpy('entityWithRefsSub'); + taskDetailStore.entityWithRefs$.subscribe(entityWithRefsSub); + expect(entityWithRefsSub).toHaveBeenCalledTimes(1); + const expectedEntitiesWithRefs = { _id: 'task-3', title: 'task 3', group_id: 'group-1', @@ -600,7 +607,9 @@ describe('Store: EntityStore with refs', () => { refs: { project: project } - }); + }; + expect(entityWithRefsSub).toHaveBeenCalledWith(expectedEntitiesWithRefs); + expect(taskDetailStore.entityWithRefs()).toEqual(expectedEntitiesWithRefs); }); it(`update with new group`, () => {