From eeb2c0efdbe11c87ffc018410aaa8fbca5d92529 Mon Sep 17 00:00:00 2001 From: Eric BREHAULT Date: Sun, 12 Jan 2020 09:44:24 +0100 Subject: [PATCH 1/5] fix build --- package.json | 2 +- projects/nst-test/src/app/file-info/file-info.component.html | 4 ++-- tslint.json | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 2f44296..f1de851 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "scripts": { "ng": "ng", "start": "ng serve", - "build": "ng build --prod nsc-test", + "build": "ng build --prod nst-test", "build:lib": "ng build --prod ngx-state-traverser && cp ./README.md ./dist/ngx-state-traverser/", "test": "jest", "lint": "ng lint", diff --git a/projects/nst-test/src/app/file-info/file-info.component.html b/projects/nst-test/src/app/file-info/file-info.component.html index acb2400..ed43dd6 100644 --- a/projects/nst-test/src/app/file-info/file-info.component.html +++ b/projects/nst-test/src/app/file-info/file-info.component.html @@ -1,2 +1,2 @@ -

Size: {{ (context | async).size }}

-

SHA: {{ (context | async).sha }}

+

Size: {{ (context | async)?.size }}

+

SHA: {{ (context | async)?.sha }}

diff --git a/tslint.json b/tslint.json index 9c729f9..2645463 100644 --- a/tslint.json +++ b/tslint.json @@ -45,6 +45,7 @@ true, "ignore-params" ], + "no-namespace": false, "no-non-null-assertion": true, "no-redundant-jsdoc": true, "no-switch-case-fall-through": true, From bd118e818f3f2b32af8481016fb33fa58507bf8f Mon Sep 17 00:00:00 2001 From: Eric BREHAULT Date: Mon, 13 Jan 2020 15:29:57 +0100 Subject: [PATCH 2/5] support tiles --- .../ngx-state-traverser/src/lib/actions.ts | 16 +++++++++++++- .../ngx-state-traverser/src/lib/effect.ts | 22 ++++++++++++++++++- .../ngx-state-traverser/src/lib/reducer.ts | 10 +++++++++ .../ngx-state-traverser/src/lib/selector.ts | 11 ++++++++++ projects/ngx-state-traverser/src/lib/state.ts | 2 ++ 5 files changed, 59 insertions(+), 2 deletions(-) diff --git a/projects/ngx-state-traverser/src/lib/actions.ts b/projects/ngx-state-traverser/src/lib/actions.ts index fd99f60..777fe0d 100644 --- a/projects/ngx-state-traverser/src/lib/actions.ts +++ b/projects/ngx-state-traverser/src/lib/actions.ts @@ -8,6 +8,8 @@ export namespace TraverserActions { Resolve = '[Traversal] Resolve', CleanTraverserResources = '[Traversal] Clean resources', UpdateTraverserResource = '[Traversal] Update resources', + LoadTile = '[Traversal] Load tile', + UpdateTile = '[Traversal] Set tile context', } export class Traverse implements Action { @@ -35,10 +37,22 @@ export namespace TraverserActions { constructor(readonly payload: {path: string, changes: {[key: string]: any}}) {} } + export class LoadTile implements Action { + readonly type = Types.LoadTile; + constructor(readonly payload: {tile: string, path: string}) {} + } + + export class UpdateTile implements Action { + readonly type = Types.UpdateTile; + constructor(readonly payload: {tile: string, target: Target}) {} + } + export type Actions = | Traverse | ResolveContext | Resolve | CleanTraverserResources - | UpdateTraverserResource; + | UpdateTraverserResource + | LoadTile + | UpdateTile; } diff --git a/projects/ngx-state-traverser/src/lib/effect.ts b/projects/ngx-state-traverser/src/lib/effect.ts index af3aa2f..b315008 100644 --- a/projects/ngx-state-traverser/src/lib/effect.ts +++ b/projects/ngx-state-traverser/src/lib/effect.ts @@ -3,7 +3,7 @@ import { Traverser } from 'angular-traversal'; import { TraverserActions } from './actions'; import { Actions, Effect, ofType } from '@ngrx/effects'; import { EMPTY } from 'rxjs'; -import { map, mergeMap, catchError } from 'rxjs/operators'; +import { map, mergeMap, catchError, tap } from 'rxjs/operators'; @Injectable() export class StateTraverserEffect { @@ -19,6 +19,18 @@ export class StateTraverserEffect { ) ); + @Effect() + watchTiles = this.actions + .pipe( + ofType('[Traversing] Watch'), + mergeMap(() => this.traverser.tileUpdates + .pipe( + map(({tile, target}) => new TraverserActions.UpdateTile({tile, target})), + catchError(() => EMPTY) + ) + ) + ); + @Effect() request = this.actions .pipe( @@ -30,6 +42,14 @@ export class StateTraverserEffect { ) ) ); + + @Effect({dispatch: false}) + loadTile = this.actions + .pipe( + ofType(TraverserActions.Types.LoadTile), + tap(action => this.traverser.loadTile(action.payload.tile, action.payload.path)) + ); + constructor( private readonly actions: Actions, private traverser: Traverser, diff --git a/projects/ngx-state-traverser/src/lib/reducer.ts b/projects/ngx-state-traverser/src/lib/reducer.ts index 9bad7c9..75b2d3e 100644 --- a/projects/ngx-state-traverser/src/lib/reducer.ts +++ b/projects/ngx-state-traverser/src/lib/reducer.ts @@ -39,6 +39,7 @@ export function reducer(state = initialState, action: TraverserActions.Actions): contextPath = contextPath.slice(0, -1); } return { + ...state, target: action.payload, collection: { ...state.collection, @@ -91,6 +92,15 @@ export function reducer(state = initialState, action: TraverserActions.Actions): } }; } + case TraverserActions.Types.UpdateTile: { + return { + ...state, + tiles: { + ...state.tiles, + [action.payload.tile]: action.payload.target, + } + }; + } default: { return state; } diff --git a/projects/ngx-state-traverser/src/lib/selector.ts b/projects/ngx-state-traverser/src/lib/selector.ts index 65da31d..6e66886 100644 --- a/projects/ngx-state-traverser/src/lib/selector.ts +++ b/projects/ngx-state-traverser/src/lib/selector.ts @@ -173,4 +173,15 @@ export namespace TraverserSelectors { map(context => (context as T)) ); } + + export function getTileContext(name: string) { + return createSelector( + traversalSelector, + (state: TraversingState): any => { + if (!!state.tiles[name]) { + return state.tiles[name].context; + } + } + ); + } } diff --git a/projects/ngx-state-traverser/src/lib/state.ts b/projects/ngx-state-traverser/src/lib/state.ts index 480afcc..dc0a937 100644 --- a/projects/ngx-state-traverser/src/lib/state.ts +++ b/projects/ngx-state-traverser/src/lib/state.ts @@ -7,6 +7,7 @@ export enum TraversingStateFeatures { export interface TraversingState { target: Target; collection: {[path: string]: any}; + tiles: {[name: string]: Target}; } export const initialState: TraversingState = { @@ -20,4 +21,5 @@ export const initialState: TraversingState = { view: 'view', }, collection: {}, + tiles: {}, }; From 10d7b7613693d14bd19f1a8e56a3c6921231b8fc Mon Sep 17 00:00:00 2001 From: Eric BREHAULT Date: Mon, 13 Jan 2020 15:30:12 +0100 Subject: [PATCH 3/5] tile example --- projects/nst-test/src/app/app.component.html | 7 ++++++- projects/nst-test/src/app/app.component.scss | 9 +++++++++ projects/nst-test/src/app/app.component.ts | 4 ++++ projects/nst-test/src/app/app.module.ts | 10 ++++++++-- .../src/app/folder/folder-details.component.html | 1 + .../src/app/folder/folder-details.component.ts | 16 ++++++++++++++++ .../src/app/folder/folder.component.html | 2 +- .../nst-test/src/app/folder/folder.component.ts | 14 +++++++++----- .../nst-test/src/app/no-details.component.ts | 9 +++++++++ 9 files changed, 63 insertions(+), 9 deletions(-) create mode 100644 projects/nst-test/src/app/folder/folder-details.component.html create mode 100644 projects/nst-test/src/app/folder/folder-details.component.ts create mode 100644 projects/nst-test/src/app/no-details.component.ts diff --git a/projects/nst-test/src/app/app.component.html b/projects/nst-test/src/app/app.component.html index 218aded..6daeb00 100644 --- a/projects/nst-test/src/app/app.component.html +++ b/projects/nst-test/src/app/app.component.html @@ -3,5 +3,10 @@
- +
+ +
+
\ No newline at end of file diff --git a/projects/nst-test/src/app/app.component.scss b/projects/nst-test/src/app/app.component.scss index e69de29..aa18c46 100644 --- a/projects/nst-test/src/app/app.component.scss +++ b/projects/nst-test/src/app/app.component.scss @@ -0,0 +1,9 @@ +section { + display: flex; + article { + width: 80%; + } + aside { + width: 20%; + } +} \ No newline at end of file diff --git a/projects/nst-test/src/app/app.component.ts b/projects/nst-test/src/app/app.component.ts index adfad17..a4dd347 100644 --- a/projects/nst-test/src/app/app.component.ts +++ b/projects/nst-test/src/app/app.component.ts @@ -5,6 +5,8 @@ import { FileInfoComponent } from './file-info/file-info.component'; import { FolderComponent } from './folder/folder.component'; import { Store } from '@ngrx/store'; import { TraversingState } from 'ngx-state-traverser'; +import { FolderDetailsComponent } from './folder/folder-details.component'; +import { NoDetailsComponent } from './no-details.component'; @Component({ selector: 'app-root', @@ -23,5 +25,7 @@ export class AppComponent { traverser.addView('view', 'file', FileComponent); traverser.addView('info', 'file', FileInfoComponent); traverser.addView('view', 'dir', FolderComponent); + traverser.addTile('details', '*', NoDetailsComponent); + traverser.addTile('details', 'dir', FolderDetailsComponent); } } diff --git a/projects/nst-test/src/app/app.module.ts b/projects/nst-test/src/app/app.module.ts index b8dd614..4295d16 100644 --- a/projects/nst-test/src/app/app.module.ts +++ b/projects/nst-test/src/app/app.module.ts @@ -21,6 +21,8 @@ import { StateTraverserModule } from 'ngx-state-traverser'; import { StoreModule } from '@ngrx/store'; import { StoreDevtoolsModule } from '@ngrx/store-devtools'; import { EffectsModule } from '@ngrx/effects'; +import { FolderDetailsComponent } from './folder/folder-details.component'; +import { NoDetailsComponent } from './no-details.component'; @NgModule({ declarations: [ @@ -28,7 +30,9 @@ import { EffectsModule } from '@ngrx/effects'; FileComponent, FolderComponent, FileInfoComponent, - NavigationComponent + NavigationComponent, + FolderDetailsComponent, + NoDetailsComponent, ], imports: [ StoreModule.forRoot({}), @@ -45,7 +49,9 @@ import { EffectsModule } from '@ngrx/effects'; entryComponents: [ FileComponent, FolderComponent, - FileInfoComponent + FileInfoComponent, + FolderDetailsComponent, + NoDetailsComponent, ], providers: [ { provide: Resolver, useClass: BasicHttpResolver }, diff --git a/projects/nst-test/src/app/folder/folder-details.component.html b/projects/nst-test/src/app/folder/folder-details.component.html new file mode 100644 index 0000000..1809e68 --- /dev/null +++ b/projects/nst-test/src/app/folder/folder-details.component.html @@ -0,0 +1 @@ +
This folder contains {{ (tileContext | async).length }} elements
\ No newline at end of file diff --git a/projects/nst-test/src/app/folder/folder-details.component.ts b/projects/nst-test/src/app/folder/folder-details.component.ts new file mode 100644 index 0000000..5b1eefc --- /dev/null +++ b/projects/nst-test/src/app/folder/folder-details.component.ts @@ -0,0 +1,16 @@ +import { Component } from '@angular/core'; +import { select, Store } from '@ngrx/store'; +import { TraverserSelectors, TraversingState } from 'ngx-state-traverser'; + +@Component({ + selector: 'app-folder-details', + templateUrl: './folder-details.component.html', +}) +export class FolderDetailsComponent { + + tileContext = this.store.pipe(select(TraverserSelectors.getTileContext('details'))); + + constructor(private readonly store: Store) { } + + +} diff --git a/projects/nst-test/src/app/folder/folder.component.html b/projects/nst-test/src/app/folder/folder.component.html index db12c87..13b43c0 100644 --- a/projects/nst-test/src/app/folder/folder.component.html +++ b/projects/nst-test/src/app/folder/folder.component.html @@ -2,6 +2,6 @@
  • {{ entry.name }} - +
  • diff --git a/projects/nst-test/src/app/folder/folder.component.ts b/projects/nst-test/src/app/folder/folder.component.ts index da8dc22..a1e0617 100644 --- a/projects/nst-test/src/app/folder/folder.component.ts +++ b/projects/nst-test/src/app/folder/folder.component.ts @@ -1,15 +1,19 @@ import { Component, OnInit } from '@angular/core'; import { select, Store } from '@ngrx/store'; -import { TraverserSelectors, TraversingState } from 'ngx-state-traverser'; +import { TraverserSelectors, TraversingState, TraverserActions } from 'ngx-state-traverser'; @Component({ - selector: 'app-folder', - templateUrl: './folder.component.html', + selector: 'app-folder', + templateUrl: './folder.component.html', }) export class FolderComponent { - context = this.store.pipe(select(TraverserSelectors.getContext)); + context = this.store.pipe(select(TraverserSelectors.getContext)); - constructor(private readonly store: Store) { } + constructor(private readonly store: Store) { } + + showDetails(path: string) { + this.store.dispatch(new TraverserActions.LoadTile({tile: 'details', path})); + } } diff --git a/projects/nst-test/src/app/no-details.component.ts b/projects/nst-test/src/app/no-details.component.ts new file mode 100644 index 0000000..f673c7c --- /dev/null +++ b/projects/nst-test/src/app/no-details.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'no-details', + template: 'No details here' +}) + +export class NoDetailsComponent { +} From 2f0508c8fe12a7696de59c2f037b7880eab35303 Mon Sep 17 00:00:00 2001 From: Eric BREHAULT Date: Tue, 28 Jan 2020 13:16:32 +0100 Subject: [PATCH 4/5] doc --- CHANGELOG.md | 4 ++++ README.md | 12 ++++++++++++ projects/ngx-state-traverser/package.json | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ed2919..cfd8d98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 1.1.0 (2020-01-28) + +- Tile support + # 1.0.6 (2019-11-02) - Add Travis and fix demo and test setup diff --git a/README.md b/README.md index 5c397f7..c05b5b8 100644 --- a/README.md +++ b/README.md @@ -105,3 +105,15 @@ this.store.dispatch(new TraverserActions.UpdateTraverserResource({ } })); ``` + +## Tiles + +With `angular-traversal`, we manage the main page view, but it also allows to define small blocks within the current page (named tiles). + +See the [angular-traversal documentation](https://github.com/guillotinaweb/angular-traversal#tiles) for more details. + +We can load a context in a tile by doing: + +```typescript +this.store.dispatch(new TraverserActions.LoadTile({tile: 'details', path})); +``` diff --git a/projects/ngx-state-traverser/package.json b/projects/ngx-state-traverser/package.json index 47238e2..9aafc30 100644 --- a/projects/ngx-state-traverser/package.json +++ b/projects/ngx-state-traverser/package.json @@ -1,6 +1,6 @@ { "name": "@guillotinaweb/ngx-state-traverser", - "version": "1.0.6", + "version": "1.1.0", "license": "MIT", "author": { "name": "Eric Brehault", From b159bf16d28f30f5c4a1b61dd194c8cd32caad21 Mon Sep 17 00:00:00 2001 From: Eric BREHAULT Date: Tue, 28 Jan 2020 14:00:04 +0100 Subject: [PATCH 5/5] use constant for action --- README.md | 25 ++++++++++++------- projects/ngx-state-traverser/package.json | 2 +- .../ngx-state-traverser/src/lib/actions.ts | 1 + .../ngx-state-traverser/src/lib/effect.ts | 4 +-- projects/nst-test/src/app/app.component.ts | 4 +-- 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index c05b5b8..2f2d57b 100644 --- a/README.md +++ b/README.md @@ -22,12 +22,17 @@ It also allows to map several views for a given type (like the `@@edit` view for We declare some views for our data type (`view` is the default view name): -``` +```typescript traverser.addView('view', 'post', PostComponent); traverser.addView('edit', 'post', EditPostComponent); traverser.addView('view', 'user', UserProfileComponent); ``` +And we connect traversing to our state: +```typescript +this.store.dispatch({ type: TraverserActions.Types.Watch}); +``` + Then the app is able to expose the following pathes: - http://localhost:4200/introduction @@ -43,7 +48,7 @@ The `` will load the current context accord Any template might contain some links like: -``` +```html @@ -53,7 +58,7 @@ Note: here and later on, the provided link can be either a full path (`/2019/07/ In code, we can navigate by dispatching an action: -``` +```typescript this.store.dispatch(new TraverserActions.Traverse('../eric')) ``` @@ -63,13 +68,13 @@ The component gets the `context` from the state. We can be the raw context (`any`) using the `getContext` selector: -``` +```typescript context = this.store.pipe(select(TraverserSelectors.getContext)); ``` But the `TraverserContext` function allows to get a typed context: -``` +```typescript context = TraverserSelectors.TraverserContext(this.store); ``` @@ -81,7 +86,7 @@ Let's say we need the list of all the posts from the current month when displayi We can get the folder content from the state: -``` +```typescript folder = TraverserSelectors.TraverseTo(this.store, '..'); ``` @@ -91,13 +96,13 @@ All the traversed resources are stored in the state, but if the requested resour As the state acts as a cache system, it can be cleaned on demand: -``` +```typescript this.store.dispatch(new TraverserActions.CleanTraverserResources(['../eric', '/2019/*'])) ``` And it can be updated: -``` +```typescript this.store.dispatch(new TraverserActions.UpdateTraverserResource({ path: '/2019/07/03', changes: { @@ -108,7 +113,9 @@ this.store.dispatch(new TraverserActions.UpdateTraverserResource({ ## Tiles -With `angular-traversal`, we manage the main page view, but it also allows to define small blocks within the current page (named tiles). +`angular-traversal` allows to manage the main page view. + +Since version 1.3.0, it also allows to define small blocks within the current page (named "tiles"). See the [angular-traversal documentation](https://github.com/guillotinaweb/angular-traversal#tiles) for more details. diff --git a/projects/ngx-state-traverser/package.json b/projects/ngx-state-traverser/package.json index 9aafc30..0c28316 100644 --- a/projects/ngx-state-traverser/package.json +++ b/projects/ngx-state-traverser/package.json @@ -32,7 +32,7 @@ "@ngrx/core": "^1.2.0", "@ngrx/effects": "^7.4.0", "@ngrx/store": "^7.4.0", - "angular-traversal": "latest" + "angular-traversal": "^1.3.0" }, "private": false } diff --git a/projects/ngx-state-traverser/src/lib/actions.ts b/projects/ngx-state-traverser/src/lib/actions.ts index 777fe0d..cf64dc4 100644 --- a/projects/ngx-state-traverser/src/lib/actions.ts +++ b/projects/ngx-state-traverser/src/lib/actions.ts @@ -3,6 +3,7 @@ import { Target } from 'angular-traversal'; export namespace TraverserActions { export enum Types { + Watch = '[Traversing] Watch', Traverse = '[Traversal] Traverse', ResolveContext = '[Traversal] Resolve context', Resolve = '[Traversal] Resolve', diff --git a/projects/ngx-state-traverser/src/lib/effect.ts b/projects/ngx-state-traverser/src/lib/effect.ts index b315008..7549d59 100644 --- a/projects/ngx-state-traverser/src/lib/effect.ts +++ b/projects/ngx-state-traverser/src/lib/effect.ts @@ -10,7 +10,7 @@ export class StateTraverserEffect { @Effect() watchTraversing = this.actions .pipe( - ofType('[Traversing] Watch'), + ofType(TraverserActions.Types.Watch), mergeMap(() => this.traverser.target .pipe( map(target => new TraverserActions.ResolveContext(target)), @@ -22,7 +22,7 @@ export class StateTraverserEffect { @Effect() watchTiles = this.actions .pipe( - ofType('[Traversing] Watch'), + ofType(TraverserActions.Types.Watch), mergeMap(() => this.traverser.tileUpdates .pipe( map(({tile, target}) => new TraverserActions.UpdateTile({tile, target})), diff --git a/projects/nst-test/src/app/app.component.ts b/projects/nst-test/src/app/app.component.ts index a4dd347..cc730af 100644 --- a/projects/nst-test/src/app/app.component.ts +++ b/projects/nst-test/src/app/app.component.ts @@ -4,7 +4,7 @@ import { FileComponent } from './file/file.component'; import { FileInfoComponent } from './file-info/file-info.component'; import { FolderComponent } from './folder/folder.component'; import { Store } from '@ngrx/store'; -import { TraversingState } from 'ngx-state-traverser'; +import { TraversingState, TraverserActions } from 'ngx-state-traverser'; import { FolderDetailsComponent } from './folder/folder-details.component'; import { NoDetailsComponent } from './no-details.component'; @@ -21,7 +21,7 @@ export class AppComponent { private readonly store: Store, traverser: Traverser, ) { - this.store.dispatch({ type: '[Traversing] Watch'}); + this.store.dispatch({ type: TraverserActions.Types.Watch}); traverser.addView('view', 'file', FileComponent); traverser.addView('info', 'file', FileInfoComponent); traverser.addView('view', 'dir', FolderComponent);