Skip to content

Commit

Permalink
feat: added resetEntitiesFilter and isEntitiesFilterChanged to withEn…
Browse files Browse the repository at this point in the history
…tities*Filter

- Added resetEntitiesFilter and isEntitiesFilterChanged to withEntities*Filter
- Small fixes on namind and required fields in withCalls and withCallStatus
  • Loading branch information
Gabriel Guerrero authored and gabrielguerrero committed Apr 17, 2024
1 parent 8e4cc87 commit e4e5d70
Show file tree
Hide file tree
Showing 11 changed files with 149 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export type CallStateMethods = {
} & {
setLoaded: () => void;
} & {
setError: () => void;
setError: (error?: unknown) => void;
};
export type NamedCallState<Prop extends string> = {
[K in Prop as `${K}CallStatus`]: CallStatus;
Expand All @@ -44,7 +44,7 @@ export type NamedCallStateMethods<Prop extends string> = {
} & {
[K in Prop as `set${Capitalize<string & K>}Loaded`]: () => void;
} & {
[K in Prop as `set${Capitalize<string & K>}Error`]: () => void;
[K in Prop as `set${Capitalize<string & K>}Error`]: (error?: unknown) => void;
};

/**
Expand Down
2 changes: 1 addition & 1 deletion libs/ngrx-traits/signals/src/lib/with-calls/with-calls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export function withCalls<
? Calls[K]['resultProp'] extends string
? Calls[K]['resultProp']
: `${K & string}Result`
: `${K & string}Result`]?: ExtractCallResultType<Calls[K]>;
: `${K & string}Result`]: ExtractCallResultType<Calls[K]>;
};
signals: NamedCallStateComputed<keyof Calls & string>;
methods: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ export function getWithEntitiesFilterKeys(config?: { collection?: string }) {
filterEntitiesKey: collection
? `filter${capitalizedProp}Entities`
: 'filterEntities',
isEntitiesFilterChangedKey: collection
? `is${capitalizedProp}FilterChanged`
: 'isEntitiesFilterChanged',
resetEntitiesFilterKey: collection
? `reset${capitalizedProp}Filter`
: 'resetEntitiesFilter',
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
patchState,
signalStoreFeature,
SignalStoreFeature,
withComputed,
withMethods,
withState,
} from '@ngrx/signals';
Expand All @@ -27,21 +28,49 @@ export type NamedEntitiesFilterState<Collection extends string, Filter> = {
[K in Collection as `${K}Filter`]: Filter;
};

export type EntitiesFilterComputed = {
isEntitiesFilterChanged: Signal<boolean>;
};
export type NamedEntitiesFilterComputed<Collection extends string> = {
[K in Collection as `is${Capitalize<string & K>}FilterChanged`]: Signal<boolean>;
};

export type EntitiesFilterMethods<Filter> = {
filterEntities: (options: {
filter: Filter;
debounce?: number;
patch?: boolean;
forceLoad?: boolean;
}) => void;
filterEntities: (
options:
| {
filter: Filter;
debounce?: number;
patch?: false | undefined;
forceLoad?: boolean;
}
| {
filter: Partial<Filter>;
debounce?: number;
patch: true;
forceLoad?: boolean;
},
) => void;
resetEntitiesFilter: () => void;
};
export type NamedEntitiesFilterMethods<Collection extends string, Filter> = {
[K in Collection as `filter${Capitalize<string & K>}Entities`]: (options: {
filter: Filter;
debounce?: number;
patch?: boolean;
forceLoad?: boolean;
}) => void;
[K in Collection as `filter${Capitalize<string & K>}Entities`]: (
options:
| {
filter: Filter;
debounce?: number;
patch?: false | undefined;
forceLoad?: boolean;
}
| {
filter: Partial<Filter>;
debounce?: number;
patch: true;
forceLoad?: boolean;
},
) => void;
} & {
[K in Collection as `reset${Capitalize<string & K>}Filter`]: () => void;
};

/**
Expand Down Expand Up @@ -93,7 +122,7 @@ export function withEntitiesLocalFilter<
},
{
state: EntitiesFilterState<Filter>;
signals: {};
signals: EntitiesFilterComputed;
methods: EntitiesFilterMethods<Filter>;
}
>;
Expand Down Expand Up @@ -150,7 +179,7 @@ export function withEntitiesLocalFilter<
},
{
state: NamedEntitiesFilterState<Collection, Filter>;
signals: {};
signals: NamedEntitiesFilterComputed<Collection>;
methods: NamedEntitiesFilterMethods<Collection, Filter>;
}
>;
Expand All @@ -169,9 +198,22 @@ export function withEntitiesLocalFilter<
collection?: Collection;
}): SignalStoreFeature<any, any> {
const { entityMapKey, idsKey } = getWithEntitiesKeys(config);
const { filterEntitiesKey, filterKey } = getWithEntitiesFilterKeys(config);
const {
filterEntitiesKey,
filterKey,
resetEntitiesFilterKey,
isEntitiesFilterChangedKey,
} = getWithEntitiesFilterKeys(config);
return signalStoreFeature(
withState({ [filterKey]: defaultFilter }),
withComputed((state: Record<string, Signal<unknown>>) => {
const filter = state[filterKey] as Signal<Filter>;
return {
[isEntitiesFilterChangedKey]: computed(() => {
return JSON.stringify(filter()) !== JSON.stringify(defaultFilter);
}),
};
}),
withMethods((state: Record<string, Signal<unknown>>) => {
const filter = state[filterKey] as Signal<Filter>;
const entitiesMap = state[entityMapKey] as Signal<EntityMap<Entity>>;
Expand All @@ -180,31 +222,35 @@ export function withEntitiesLocalFilter<
// the ids array of the state with the filtered ids array, and the state.entities depends on it,
// so hour filter function needs the full list of entities always which will be always so we get them from entityMap
const entities = computed(() => Object.values(entitiesMap()));
return {
[filterEntitiesKey]: rxMethod<{
filter: Filter;
debounce?: number;
patch?: boolean;
forceLoad?: boolean;
}>(
pipe(
debounceFilterPipe(filter),
tap((value) => {
const newEntities = entities().filter((entity) => {
return filterFn(entity, value.filter);
});
patchState(
state as StateSignal<EntitiesFilterState<Filter>>,
{
[filterKey]: value.filter,
},
{
[idsKey]: newEntities.map((entity) => entity.id),
},
);
}),
),
const filterEntities = rxMethod<{
filter: Filter;
debounce?: number;
patch?: boolean;
forceLoad?: boolean;
}>(
pipe(
debounceFilterPipe(filter),
tap((value) => {
const newEntities = entities().filter((entity) => {
return filterFn(entity, value.filter);
});
patchState(
state as StateSignal<EntitiesFilterState<Filter>>,
{
[filterKey]: value.filter,
},
{
[idsKey]: newEntities.map((entity) => entity.id),
},
);
}),
),
);
return {
[filterEntitiesKey]: filterEntities,
[resetEntitiesFilterKey]: () => {
filterEntities({ filter: defaultFilter });
},
};
}),
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Signal } from '@angular/core';
import { computed, Signal } from '@angular/core';
import {
patchState,
signalStoreFeature,
SignalStoreFeature,
withComputed,
withMethods,
withState,
} from '@ngrx/signals';
Expand Down Expand Up @@ -219,30 +220,47 @@ export function withEntitiesRemoteFilter<
defaultFilter: Filter;
}): SignalStoreFeature<any, any> {
const { setLoadingKey } = getWithCallStatusKeys({ prop: config.collection });
const { filterKey, filterEntitiesKey } = getWithEntitiesFilterKeys(config);
const {
filterKey,
filterEntitiesKey,
resetEntitiesFilterKey,
isEntitiesFilterChangedKey,
} = getWithEntitiesFilterKeys(config);
return signalStoreFeature(
withState({ [filterKey]: defaultFilter }),
withComputed((state: Record<string, Signal<unknown>>) => {
const filter = state[filterKey] as Signal<Filter>;
return {
[isEntitiesFilterChangedKey]: computed(() => {
return JSON.stringify(filter()) !== JSON.stringify(defaultFilter);
}),
};
}),
withMethods((state: Record<string, Signal<unknown>>) => {
const setLoading = state[setLoadingKey] as () => void;
const filter = state[filterKey] as Signal<Filter>;

return {
[filterEntitiesKey]: rxMethod<{
filter: Filter;
debounce?: number;
patch?: boolean;
forceLoad?: boolean;
}>(
pipe(
debounceFilterPipe(filter),
tap((value) => {
setLoading();
patchState(state as StateSignal<EntitiesFilterState<Filter>>, {
[filterKey]: value.filter,
});
}),
),
const filterEntities = rxMethod<{
filter: Filter;
debounce?: number;
patch?: boolean;
forceLoad?: boolean;
}>(
pipe(
debounceFilterPipe(filter),
tap((value) => {
setLoading();
patchState(state as StateSignal<EntitiesFilterState<Filter>>, {
[filterKey]: value.filter,
});
}),
),
);
return {
[filterEntitiesKey]: filterEntities,
[resetEntitiesFilterKey]: () => {
filterEntities({ filter: defaultFilter });
},
};
}),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ import { getWithEntitiesLocalPaginationKeys } from '../with-entities-pagination/
import { getWithEntitiesSortKeys } from '../with-entities-sort/with-entities-sort.util';

export type EntitiesMultiSelectionState = {
selectedIdsMap: Record<string | number, boolean>;
entitiesSelectedIdsMap: Record<string | number, boolean>;
};
export type NamedEntitiesMultiSelectionState<Collection extends string> = {
[K in Collection as `${K}SelectedIdsMap`]: Record<string | number, boolean>;
};

export type EntitiesMultiSelectionComputed<Entity> = {
selectedEntities: Signal<Entity[]>;
entitiesSelected: Signal<Entity[]>;
isAllEntitiesSelected: Signal<'all' | 'none' | 'some'>;
};
export type NamedEntitiesMultiSelectionComputed<
Expand Down Expand Up @@ -80,10 +80,10 @@ function getEntitiesMultiSelectionKeys(config?: { collection?: string }) {
return {
selectedIdsMapKey: collection
? `${config.collection}SelectedIdsMap`
: 'selectedIdsMap',
: 'entitiesSelectedIdsMap',
selectedEntitiesKey: collection
? `${config.collection}SelectedEntities`
: 'selectedEntities',
: 'entitiesSelected',
selectEntitiesKey: collection
? `select${capitalizedProp}Entities`
: 'selectEntities',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
} from './with-entities-local-pagination.util';

export type EntitiesPaginationLocalState = {
pagination: {
entitiesPagination: {
currentPage: number;
pageSize: number;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ export function getWithEntitiesLocalPaginationKeys(config?: {
const collection = config?.collection;
const capitalizedProp = collection && capitalize(collection);
return {
paginationKey: collection ? `${config.collection}Pagination` : 'pagination',
paginationKey: collection
? `${config.collection}Pagination`
: 'entitiesPagination',
entitiesCurrentPageKey: collection
? `${config.collection}CurrentPage`
: 'entitiesCurrentPage',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export type PaginationState = {
};

export type EntitiesPaginationRemoteState = {
pagination: PaginationState;
entitiesPagination: PaginationState;
};

export type NamedEntitiesPaginationRemoteState<Collection extends string> = {
Expand Down Expand Up @@ -591,7 +591,7 @@ export function withEntitiesRemotePagination<

function isEntitiesPageInCache(
page: number,
pagination: EntitiesPaginationRemoteState['pagination'],
pagination: EntitiesPaginationRemoteState['entitiesPagination'],
) {
const startIndex = page * pagination.pageSize;
let endIndex = startIndex + pagination.pageSize - 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ export function getWithEntitiesRemotePaginationKeys(config?: {
const collection = config?.collection;
const capitalizedProp = collection && capitalize(collection);
return {
paginationKey: collection ? `${config.collection}Pagination` : 'pagination',
paginationKey: collection
? `${config.collection}Pagination`
: 'entitiesPagination',
entitiesCurrentPageKey: collection
? `${config.collection}CurrentPage`
: 'entitiesCurrentPage',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ import { getWithEntitiesLocalPaginationKeys } from '../with-entities-pagination/
import { getWithEntitiesSortKeys } from '../with-entities-sort/with-entities-sort.util';

export type EntitiesSingleSelectionState = {
selectedId?: string | number;
entitiesSelectedId?: string | number;
};
export type NamedEntitiesSingleSelectionState<Collection extends string> = {
[K in Collection as `${K}SelectedId`]?: string | number;
};

export type EntitiesSingleSelectionComputed<Entity> = {
selectedEntity: Signal<Entity | undefined>;
entitiesSelectedEntity: Signal<Entity | undefined>;
};
export type NamedEntitiesSingleSelectionComputed<
Entity,
Expand Down Expand Up @@ -60,10 +60,12 @@ function getEntitiesSingleSelectionKeys(config?: { collection?: string }) {
const collection = config?.collection;
const capitalizedProp = collection && capitalize(collection);
return {
selectedIdKey: collection ? `${config.collection}SelectedId` : 'selectedId',
selectedIdKey: collection
? `${config.collection}SelectedId`
: 'entitiesSelectedId',
selectedEntityKey: collection
? `${config.collection}SelectedEntity`
: 'selectedEntity',
: 'entitiesSelectedEntity',
selectEntityKey: collection
? `select${capitalizedProp}Entity`
: 'selectEntity',
Expand Down

0 comments on commit e4e5d70

Please sign in to comment.