@ngrx-traits/common 14.0.1 → 14.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/async-action/async-action.trait.d.ts +6 -2
  2. package/crud-entities/crud-entities.trait.d.ts +1 -0
  3. package/entities-pagination/entities-pagination.model.d.ts +3 -2
  4. package/entities-pagination/entities-pagination.trait.d.ts +3 -2
  5. package/entities-sync-to-route-query-params/entities-sync-to-route-query-params.d.ts +30 -0
  6. package/entities-sync-to-route-query-params/index.d.ts +1 -0
  7. package/esm2020/async-action/async-action.trait.mjs +7 -3
  8. package/esm2020/crud-entities/crud-entities.trait.mjs +2 -1
  9. package/esm2020/entities-pagination/entities-pagination.model.mjs +1 -1
  10. package/esm2020/entities-pagination/entities-pagination.trait.effects.mjs +4 -4
  11. package/esm2020/entities-pagination/entities-pagination.trait.mjs +4 -3
  12. package/esm2020/entities-pagination/entities-pagination.trait.mutators.mjs +13 -2
  13. package/esm2020/entities-pagination/entities-pagination.trait.reducer.mjs +2 -10
  14. package/esm2020/entities-sync-to-route-query-params/entities-sync-to-route-query-params.mjs +126 -0
  15. package/esm2020/entities-sync-to-route-query-params/index.mjs +2 -0
  16. package/esm2020/filter-entities/filter-entities.trait.mjs +2 -1
  17. package/esm2020/index.mjs +2 -1
  18. package/esm2020/load-entity/load-entity.traits.mjs +5 -1
  19. package/esm2020/reset/reset.trait.mjs +2 -4
  20. package/esm2020/select-entities/select-entities.trait.mjs +2 -1
  21. package/esm2020/select-entity/select-entity.trait.mjs +2 -1
  22. package/esm2020/set-entity/set-entity.trait.mjs +5 -1
  23. package/esm2020/sort-entities/sort-entities.trait.mjs +3 -1
  24. package/esm2020/sort-entities/sort-entities.trait.mutators.mjs +8 -1
  25. package/esm2020/sort-entities/sort-entities.trait.reducer.mjs +2 -15
  26. package/fesm2015/ngrx-traits-common.mjs +156 -25
  27. package/fesm2015/ngrx-traits-common.mjs.map +1 -1
  28. package/fesm2020/ngrx-traits-common.mjs +167 -36
  29. package/fesm2020/ngrx-traits-common.mjs.map +1 -1
  30. package/filter-entities/filter-entities.trait.d.ts +1 -0
  31. package/index.d.ts +1 -0
  32. package/load-entity/load-entity.traits.d.ts +4 -0
  33. package/package.json +5 -4
  34. package/reset/reset.trait.d.ts +1 -3
  35. package/select-entities/select-entities.trait.d.ts +1 -0
  36. package/select-entity/select-entity.trait.d.ts +1 -0
  37. package/set-entity/set-entity.trait.d.ts +4 -0
  38. package/sort-entities/sort-entities.trait.d.ts +2 -0
@@ -2,10 +2,11 @@ import { createReducer, on, createAction, props, createSelector } from '@ngrx/st
2
2
  import { insertIf, createTraitFactory, TraitEffect, toMap, camelCaseToSentence, capitalize } from '@ngrx-traits/core';
3
3
  import { createEntityAdapter } from '@ngrx/entity';
4
4
  import * as i0 from '@angular/core';
5
- import { Injectable } from '@angular/core';
5
+ import { Injectable, inject } from '@angular/core';
6
6
  import { EMPTY, timer, of, pipe, asyncScheduler } from 'rxjs';
7
- import { debounce, concatMap, first, map, distinctUntilChanged, startWith, pairwise, concatMapTo, tap, filter } from 'rxjs/operators';
7
+ import { debounce, concatMap, first, map, distinctUntilChanged, startWith, pairwise, concatMapTo, filter, mapTo, tap, delay } from 'rxjs/operators';
8
8
  import { createEffect, ofType, concatLatestFrom } from '@ngrx/effects';
9
+ import { ActivatedRoute, Router } from '@angular/router';
9
10
 
10
11
  const loadEntitiesTraitKey = 'loadEntities';
11
12
 
@@ -274,6 +275,7 @@ function createFilterTraitActions(actionsGroupKey, entitiesName) {
274
275
  * extends LoadEntitiesState<Todo>, FilterEntitiesState<TodoFilter>{}
275
276
  *
276
277
  * const traits = createEntityFeatureFactory(
278
+ * {entityName: 'Todo'},
277
279
  * addLoadEntitiesTrait<Todo>(),
278
280
  * //addFilterEntitiesTrait<Todo,TodoFilter>() // no params uses remote filtering
279
281
  * addFilterEntitiesTrait<Todo,TodoFilter>({filterFn: (filter, entity) => // local filtering
@@ -475,15 +477,7 @@ function createPaginationTraitReducer(initialState, allActions, allSelectors, al
475
477
  };
476
478
  }
477
479
  const filterRemote = !allConfigs?.filter?.filterFn;
478
- return createReducer(initialState, on(allActions.loadEntitiesPage, (state, { index }) => ({
479
- ...state,
480
- pagination: {
481
- ...state.pagination,
482
- currentPage: index,
483
- requestPage: index,
484
- },
485
- status: 'loading',
486
- })), on(allActions.setEntitiesRequestPage, (state, { index }) => ({
480
+ return createReducer(initialState, on(allActions.loadEntitiesPage, (state, { index }) => allMutators.setEntitiesPage(state, index)), on(allActions.setEntitiesRequestPage, (state, { index }) => ({
487
481
  ...state,
488
482
  pagination: {
489
483
  ...state.pagination,
@@ -515,12 +509,12 @@ function createPaginationTraitEffects(allActions, allSelectors) {
515
509
  this.preloadNextPage$ = createEffect(() => {
516
510
  return this.actions$.pipe(ofType(allActions.loadEntitiesPageSuccess), concatMapTo(this.store
517
511
  .select(allSelectors.selectEntitiesCurrentPageInfo)
518
- .pipe(first())), tap(console.log), filter((pageInfo) => !!pageInfo.total &&
512
+ .pipe(first())), filter((pageInfo) => !!pageInfo.total &&
519
513
  pageInfo.hasNext &&
520
514
  pageInfo.cacheType !== 'full'), concatMap((pageInfo) => this.store
521
515
  .select(allSelectors
522
516
  .isEntitiesNextPageInCache)
523
- .pipe(first(), map((isInCache) => (!isInCache && pageInfo) || undefined))), tap(console.log), filter((pageInfo) => !!pageInfo), concatMap((pageInfo) => [
517
+ .pipe(first(), map((isInCache) => (!isInCache && pageInfo) || undefined))), filter((pageInfo) => !!pageInfo), concatMap((pageInfo) => [
524
518
  allActions.setEntitiesRequestPage({ index: pageInfo.pageIndex + 1 }),
525
519
  allActions.loadEntities(),
526
520
  ]));
@@ -611,11 +605,22 @@ function createPaginationTraitMutators(allSelectors, allConfigs) {
611
605
  }
612
606
  return state;
613
607
  }
614
- return { mergePaginatedEntities };
608
+ function setEntitiesPage(state, index) {
609
+ return {
610
+ ...state,
611
+ pagination: {
612
+ ...state.pagination,
613
+ currentPage: index,
614
+ requestPage: index,
615
+ },
616
+ status: 'loading',
617
+ };
618
+ }
619
+ return { mergePaginatedEntities, setEntitiesPage };
615
620
  }
616
621
 
617
622
  /**
618
- * Generates ngrx code to paginate an list of entities, this has 3 cache `cacheType`
623
+ * Generates ngrx code to paginate a list of entities, this has 3 cache `cacheType`
619
624
  * - 'full': The full result is cache in memory and split in pages to render, useful
620
625
  * for small result but not so small that requires been render in pages
621
626
  * - 'partial': Backend returns partial results because is are to big, this has a cache a few pages forward
@@ -636,9 +641,10 @@ function createPaginationTraitMutators(allSelectors, allConfigs) {
636
641
  * // The following trait config
637
642
  *
638
643
  * export interface TestState
639
- * extends EntityAndStatusState<Todo>,SingleSelectionState{}
644
+ * extends EntityAndStatusState<Todo>,EntitiesPaginationState{}
640
645
  *
641
646
  * const traits = createEntityFeatureFactory(
647
+ * {entityName: 'Todo'},
642
648
  * addLoadEntitiesTrait<Todo>(),
643
649
  * addEntitiesPaginationTrait<Todo>()
644
650
  * )({
@@ -840,6 +846,7 @@ function createSelectEntitiesTraitMutators({ isAllEntitiesSelected, }) {
840
846
  * extends EntityAndStatusState<Todo>,MultipleSelectionState{}
841
847
  *
842
848
  * const traits = createEntityFeatureFactory(
849
+ * {entityName: 'Todo'},
843
850
  * addLoadEntitiesTrait<Todo>(),
844
851
  * addSelectEntitiesTrait<Todo>()
845
852
  * )({
@@ -970,6 +977,7 @@ function createSelectEntityTraitMutators() {
970
977
  * extends EntityAndStatusState<Todo>,SelectEntityState{}
971
978
  *
972
979
  * const traits = createEntityFeatureFactory(
980
+ * {entityName: 'Todo'},
973
981
  * addLoadEntitiesTrait<Todo>(),
974
982
  * addSelectEntityTrait<Todo>()
975
983
  * )({
@@ -1233,6 +1241,7 @@ function createCrudTraitMutators(allConfigs) {
1233
1241
  * extends EntityAndStatusState<Todo>, CrudState<Todo>{}
1234
1242
  *
1235
1243
  * const traits = createEntityFeatureFactory(
1244
+ * {entityName: 'Todo'},
1236
1245
  * addLoadEntitiesTrait<Todo>(),
1237
1246
  * addCrudEntitiesTrait<Todo>()
1238
1247
  * )({
@@ -1335,7 +1344,14 @@ function sortData(data, sort) {
1335
1344
  }
1336
1345
 
1337
1346
  function createSortTraitMutators({ selectEntitiesList }, allConfigs) {
1347
+ const { remote } = allConfigs.sort;
1338
1348
  function sortEntities({ active, direction }, state) {
1349
+ if (remote) {
1350
+ return {
1351
+ ...state,
1352
+ sort: { ...state.sort, current: { active, direction } },
1353
+ };
1354
+ }
1339
1355
  const { adapter } = allConfigs.loadEntities;
1340
1356
  const entities = selectEntitiesList(state);
1341
1357
  const sortedIds = sortData(entities, { active, direction }).map((v) => adapter.selectId(v));
@@ -1361,20 +1377,7 @@ function createSortInitialState(previousInitialState, allConfigs) {
1361
1377
  };
1362
1378
  }
1363
1379
  function createSortTraitReducer(initialState, allActions, allMutators, allConfigs) {
1364
- const { remote } = allConfigs.sort;
1365
- return createReducer(initialState, on(allActions.sortEntities, (state, { active, direction }) => !remote
1366
- ? allMutators.sortEntities({ active, direction }, state)
1367
- : {
1368
- ...state,
1369
- sort: { ...state.sort, current: { active, direction } },
1370
- }), on(allActions.resetEntitiesSort, (state) => state.sort?.default
1371
- ? !remote
1372
- ? allMutators.sortEntities(state.sort?.default, state)
1373
- : {
1374
- ...state,
1375
- sort: { ...state.sort, current: state.sort?.default },
1376
- }
1377
- : state));
1380
+ return createReducer(initialState, on(allActions.sortEntities, (state, { active, direction }) => allMutators.sortEntities({ active, direction }, state)), on(allActions.resetEntitiesSort, (state) => allMutators.sortEntities(state.sort?.default, state)));
1378
1381
  }
1379
1382
 
1380
1383
  function createSortTraitSelectors() {
@@ -1431,8 +1434,10 @@ function createSortTraitActions(actionsGroupKey, entitiesName) {
1431
1434
  * extends EntityAndStatusState<Todo>, SortState<Todo>{}
1432
1435
  *
1433
1436
  * const traits = createEntityFeatureFactory(
1437
+ * {entityName: 'Todo'},
1434
1438
  * addLoadEntitiesTrait<Todo>(),
1435
1439
  * addSortEntitiesTrait<Todo>({
1440
+ * remote: true,
1436
1441
  * defaultSort: {active:'id', direction:'asc'}
1437
1442
  * })
1438
1443
  * )({
@@ -1476,10 +1481,8 @@ function addSortEntitiesTrait({ remote, defaultSort, }) {
1476
1481
  * @example
1477
1482
  * // The following trait config
1478
1483
  *
1479
- * export interface TestState
1480
- * extends EntityAndStatusState<Todo>,FilterState<TodoFilter>{}
1481
- *
1482
1484
  * const traits = createEntityFeatureFactory(
1485
+ * {entityName: 'Todo'},
1483
1486
  * addLoadEntitiesTrait<Todo>(),
1484
1487
  * addResetEntitiesStateTrait()
1485
1488
  * )({
@@ -1521,10 +1524,14 @@ function addResetEntitiesStateTrait(traitConfig = {}) {
1521
1524
  * @returns the trait factory
1522
1525
  *
1523
1526
  * @example
1527
+ *
1528
+ * export interface TestState
1529
+ * extends AsyncActionState<'createClient'>{}
1530
+ *
1524
1531
  * // The following trait config
1525
1532
  * const traits = createEntityFeatureFactory(
1526
- * {entityName: 'Todo'},
1527
- * addAsyncActionTrait({
1533
+ * {entityName: 'Todo'},
1534
+ * addAsyncActionTrait({
1528
1535
  * name: 'createClient',
1529
1536
  * actionProps: props<{ name: string }>(),
1530
1537
  * actionSuccessProps: props<{ id: string }>(),
@@ -1625,6 +1632,10 @@ function addAsyncActionTrait({ name, actionProps, actionSuccessProps, actionFail
1625
1632
  * @returns the trait factory
1626
1633
  *
1627
1634
  * @example
1635
+ *
1636
+ * export interface TestState
1637
+ * extends LoadEntityState<Client,'client'>{}
1638
+ *
1628
1639
  * const traits = createEntityFeatureFactory(
1629
1640
  * ...addLoadEntityTraits({
1630
1641
  * entityName: 'client',
@@ -1691,6 +1702,10 @@ function addLoadEntityTraits({ entityName, actionProps, actionSuccessProps, acti
1691
1702
  * @returns the trait factory
1692
1703
  *
1693
1704
  * @example
1705
+ *
1706
+ * export interface TestState
1707
+ * extends SetEntityState<Client,'client'>{}
1708
+ *
1694
1709
  * const traits = createEntityFeatureFactory(
1695
1710
  * addSetEntityTraits({
1696
1711
  * entityName: 'client',
@@ -1739,9 +1754,125 @@ function addSetEntityTrait({ entityName, actionProps, }) {
1739
1754
  });
1740
1755
  }
1741
1756
 
1757
+ /**
1758
+ * Generates ngrx code necessary to load and set to the current route query params for the filter, sort and paging traits
1759
+ *
1760
+ * @example
1761
+ *
1762
+ * const traits = createEntityFeatureFactory(
1763
+ * {entityName: 'Todo'},
1764
+ * addLoadEntitiesTrait<Todo>(),
1765
+ * addFilterEntitiesTrait(),
1766
+ * addSortEntitiesTrait<Todo>({
1767
+ * remote: true,
1768
+ * defaultSort: {active:'id', direction:'asc'}
1769
+ * })
1770
+ * addEntitiesPaginationTrait<Todo>(),
1771
+ * addEntitiesSyncToRouteQueryParams()
1772
+ * )({
1773
+ * actionsGroupKey: '[Todos]',
1774
+ * featureSelector: createFeatureSelector<TestState>>(
1775
+ * 'todos',
1776
+ * ),
1777
+ * });
1778
+ *
1779
+ *
1780
+ * // generated actions
1781
+ * traits.actions.loadTodosUsingRouteQueryParams()
1782
+ */
1783
+ function addEntitiesSyncToRouteQueryParams() {
1784
+ let setEntitiesRouteQueryParams;
1785
+ return createTraitFactory({
1786
+ key: 'entitiesSyncToRouteQueryParams',
1787
+ depends: [entitiesPaginationTraitKey, sortTraitKey, filterEntitiesTraitKey],
1788
+ actions({ actionsGroupKey, entitiesName }) {
1789
+ const actions = {
1790
+ loadEntitiesUsingRouteQueryParams: createAction(`${actionsGroupKey} Load ${entitiesName} Using Route Query Params`),
1791
+ };
1792
+ setEntitiesRouteQueryParams = createAction(`${actionsGroupKey} Set ${entitiesName} Route Query Params`, props());
1793
+ return { ...actions, setEntitiesRouteQueryParams };
1794
+ },
1795
+ reducer({ initialState, allMutators: m }) {
1796
+ const allMutators = m;
1797
+ return createReducer(initialState, on(setEntitiesRouteQueryParams, (state, { params: p }) => {
1798
+ const params = { ...p };
1799
+ let newState = state;
1800
+ if (params.page) {
1801
+ newState = allMutators.setEntitiesPage(newState, +params.page);
1802
+ delete params.page;
1803
+ }
1804
+ if (params.sortActive) {
1805
+ newState = allMutators.sortEntities({
1806
+ active: params.sortActive,
1807
+ direction: params.sortDirection,
1808
+ }, newState);
1809
+ delete params.sortActive;
1810
+ delete params.sortDirection;
1811
+ }
1812
+ if (Object.keys(params).length) {
1813
+ newState = allMutators.setEntitiesFilters(params, newState);
1814
+ }
1815
+ return newState;
1816
+ }));
1817
+ },
1818
+ effects({ allActions: a }) {
1819
+ const allActions = a;
1820
+ class SyncEntitiesStateToUrlEffect extends TraitEffect {
1821
+ constructor() {
1822
+ super(...arguments);
1823
+ this.activatedRoute = inject(ActivatedRoute);
1824
+ this.router = inject(Router);
1825
+ this.loadUrlParams$ = createEffect(() => {
1826
+ return this.actions$.pipe(ofType(allActions.loadEntitiesUsingRouteQueryParams), concatLatestFrom(() => this.activatedRoute.queryParams), map(([_, params]) => setEntitiesRouteQueryParams({ params })));
1827
+ });
1828
+ this.setUrlParams$ = createEffect(() => {
1829
+ return this.actions$.pipe(ofType(setEntitiesRouteQueryParams), mapTo(allActions.loadEntities()));
1830
+ });
1831
+ this.onFilter$ = !!allActions.filterEntities &&
1832
+ createEffect(() => {
1833
+ return this.actions$.pipe(ofType(allActions.filterEntities), tap(({ filters }) => {
1834
+ this.updateUrl(filters);
1835
+ }));
1836
+ }, { dispatch: false });
1837
+ this.onSort$ = !!allActions.sortEntities &&
1838
+ createEffect(() => {
1839
+ return this.actions$.pipe(ofType(allActions.sortEntities), delay(0), tap(({ active, direction }) => {
1840
+ this.updateUrl({
1841
+ sortActive: active,
1842
+ sortDirection: direction,
1843
+ });
1844
+ }));
1845
+ }, { dispatch: false });
1846
+ this.onPaginate$ = !!allActions.loadEntitiesPage &&
1847
+ createEffect(() => {
1848
+ return this.actions$.pipe(ofType(allActions.loadEntitiesPage), tap(({ index }) => {
1849
+ this.updateUrl({
1850
+ page: index,
1851
+ });
1852
+ }));
1853
+ }, { dispatch: false });
1854
+ }
1855
+ updateUrl(queryParams) {
1856
+ this.router.navigate([], {
1857
+ relativeTo: this.activatedRoute,
1858
+ queryParams,
1859
+ queryParamsHandling: 'merge', // remove to replace all query params by provided
1860
+ });
1861
+ }
1862
+ }
1863
+ SyncEntitiesStateToUrlEffect.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: SyncEntitiesStateToUrlEffect, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
1864
+ SyncEntitiesStateToUrlEffect.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: SyncEntitiesStateToUrlEffect });
1865
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: SyncEntitiesStateToUrlEffect, decorators: [{
1866
+ type: Injectable
1867
+ }] });
1868
+ return [SyncEntitiesStateToUrlEffect];
1869
+ },
1870
+ });
1871
+ }
1872
+
1742
1873
  /**
1743
1874
  * Generated bundle index. Do not edit.
1744
1875
  */
1745
1876
 
1746
- export { ChangeType, _isNumberValue, addAsyncActionTrait, addCrudEntitiesTrait, addEntitiesPaginationTrait, addFilterEntitiesTrait, addLoadEntitiesTrait, addLoadEntityTraits, addResetEntitiesStateTrait, addSelectEntitiesTrait, addSelectEntityTrait, addSetEntityTrait, addSortEntitiesTrait, clearEntitiesSelection, crudEntitiesTraitKey, deselectEntities, entitiesPaginationTraitKey, filterEntitiesTraitKey, loadEntitiesTraitKey, selectEntities, selectEntityTraitKey, selectTotalSelectedEntities, sortData, sortTraitKey, toggleSelectEntities };
1877
+ export { ChangeType, _isNumberValue, addAsyncActionTrait, addCrudEntitiesTrait, addEntitiesPaginationTrait, addEntitiesSyncToRouteQueryParams, addFilterEntitiesTrait, addLoadEntitiesTrait, addLoadEntityTraits, addResetEntitiesStateTrait, addSelectEntitiesTrait, addSelectEntityTrait, addSetEntityTrait, addSortEntitiesTrait, clearEntitiesSelection, crudEntitiesTraitKey, deselectEntities, entitiesPaginationTraitKey, filterEntitiesTraitKey, loadEntitiesTraitKey, selectEntities, selectEntityTraitKey, selectTotalSelectedEntities, sortData, sortTraitKey, toggleSelectEntities };
1747
1878
  //# sourceMappingURL=ngrx-traits-common.mjs.map