Skip to content

Commit

Permalink
Merge pull request #2 from guillotinaweb/issue-ancestors-selector
Browse files Browse the repository at this point in the history
Add getAncestors selector
  • Loading branch information
ebrehault authored Sep 26, 2019
2 parents 8c8fd57 + b473230 commit 3c3a7d4
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true

Expand Down
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# 1.0.1 (2019-09-26)

- Add getAncestors selector

# 1.0.0 (2019-09-04)

- Initial version
- Initial version
4 changes: 2 additions & 2 deletions projects/ngx-state-traverser/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ngx-state-traverser",
"version": "1.0.0",
"version": "1.0.1",
"peerDependencies": {
"@angular/common": "^8.1.1",
"@angular/core": "^8.1.1",
Expand All @@ -9,4 +9,4 @@
"@ngrx/store": "^7.4.0",
"angular-traversal": "^1.0.6"
}
}
}
42 changes: 37 additions & 5 deletions projects/ngx-state-traverser/src/lib/selector.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import { createFeatureSelector, createSelector, select, MemoizedSelector, Store } from '@ngrx/store';
import { createFeatureSelector, createSelector, select, Store } from '@ngrx/store';
import { TraversingState, TraversingStateFeatures } from './state';
import { Target } from 'angular-traversal';
import { map, filter } from 'rxjs/operators';
import { map, filter, tap } from 'rxjs/operators';
import { TraverserActions } from './actions';
import { Observable } from 'rxjs';

export namespace TraverserSelectors {
export class Missing {
path: string;

constructor(path: string) {
this.path = path;
}
};
}

type ContextOrMissing = {[key: string]: any} | Missing;
type ContextOrMissing = { [key: string]: any } | Missing;

function _getParentPath(state: TraversingState): string {
let targetPath = state.target.contextPath;
Expand Down Expand Up @@ -53,7 +55,7 @@ export namespace TraverserSelectors {

export const getContext = createSelector(
traversalSelector,
(state: TraversingState): {[key: string]: any} => state.target.context
(state: TraversingState): { [key: string]: any } => state.target.context
);

export function TraverserContext<T>(store: Store<any>) {
Expand All @@ -78,6 +80,36 @@ export namespace TraverserSelectors {
}
);

export const getAncestors = createSelector(
traversalSelector,
(state: TraversingState, path: string): ContextOrMissing[] => {
const ancestorPaths = path.split('/').filter(chunk => !!chunk).reduce((allChunks, chunk) => {
if (allChunks.length === 0) {
allChunks.push(`/${chunk}`);
} else {
allChunks.push(`${allChunks[allChunks.length - 1]}/${chunk}`);
}
return allChunks;
}, [] as string[]);

const ancestors: ContextOrMissing[] = ancestorPaths.map(ancestor => state.collection[ancestor] || new Missing(ancestor));
return ancestors.filter(ancestor => !ancestor['isForbidden']);
}
);

export function TraverseToAncestors<T>(store: Store<any>, path: string): Observable<(T | undefined)[]> {
return store.pipe(
select(getAncestors, path),
tap(ancestors => ancestors.forEach(ancestor => {
if (ancestor instanceof Missing) {
store.dispatch(new TraverserActions.Traverse(ancestor.path));
}
})),
filter(ancestors => ancestors.every(ancestor => !(ancestor instanceof Missing))),
map(ancestors => ancestors as T[])
);
}

export function TraverseToParent<T>(store: Store<any>) {
return store.pipe(
select(getParent),
Expand Down

0 comments on commit 3c3a7d4

Please sign in to comment.