Skip to content

Commit

Permalink
Merge pull request #13 from guillotinaweb/tiles
Browse files Browse the repository at this point in the history
Tiles
  • Loading branch information
ebrehault authored Jan 28, 2020
2 parents 6291610 + b159bf1 commit 5085fe0
Show file tree
Hide file tree
Showing 20 changed files with 163 additions and 27 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
35 changes: 27 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -43,7 +48,7 @@ The `<traverser-outlet></traverser-outlet>` will load the current context accord

Any template might contain some links like:

```
```html
<a traverseTo="/2019/07/new-post">
<a [traverseTo]="relatedPost">
<a traverseTo="..">
Expand All @@ -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'))
```

Expand All @@ -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<UserProfile>(this.store);
```

Expand All @@ -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<Folder>(this.store, '..');
```

Expand All @@ -91,17 +96,31 @@ 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: {
title: "New title"
}
}));
```

## 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.

We can load a context in a tile by doing:

```typescript
this.store.dispatch(new TraverserActions.LoadTile({tile: 'details', path}));
```
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
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": "@guillotinaweb/ngx-state-traverser",
"version": "1.0.6",
"version": "1.1.0",
"license": "MIT",
"author": {
"name": "Eric Brehault",
Expand Down Expand Up @@ -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
}
17 changes: 16 additions & 1 deletion projects/ngx-state-traverser/src/lib/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ import { Target } from 'angular-traversal';

export namespace TraverserActions {
export enum Types {
Watch = '[Traversing] Watch',
Traverse = '[Traversal] Traverse',
ResolveContext = '[Traversal] Resolve context',
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 {
Expand Down Expand Up @@ -35,10 +38,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;
}
24 changes: 22 additions & 2 deletions projects/ngx-state-traverser/src/lib/effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ 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 {
@Effect()
watchTraversing = this.actions
.pipe(
ofType('[Traversing] Watch'),
ofType(TraverserActions.Types.Watch),
mergeMap(() => this.traverser.target
.pipe(
map(target => new TraverserActions.ResolveContext(target)),
Expand All @@ -19,6 +19,18 @@ export class StateTraverserEffect {
)
);

@Effect()
watchTiles = this.actions
.pipe(
ofType(TraverserActions.Types.Watch),
mergeMap(() => this.traverser.tileUpdates
.pipe(
map(({tile, target}) => new TraverserActions.UpdateTile({tile, target})),
catchError(() => EMPTY)
)
)
);

@Effect()
request = this.actions
.pipe(
Expand All @@ -30,6 +42,14 @@ export class StateTraverserEffect {
)
)
);

@Effect({dispatch: false})
loadTile = this.actions
.pipe(
ofType<TraverserActions.LoadTile>(TraverserActions.Types.LoadTile),
tap(action => this.traverser.loadTile(action.payload.tile, action.payload.path))
);

constructor(
private readonly actions: Actions,
private traverser: Traverser,
Expand Down
10 changes: 10 additions & 0 deletions projects/ngx-state-traverser/src/lib/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
}
Expand Down
11 changes: 11 additions & 0 deletions projects/ngx-state-traverser/src/lib/selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
);
}
}
2 changes: 2 additions & 0 deletions projects/ngx-state-traverser/src/lib/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export enum TraversingStateFeatures {
export interface TraversingState {
target: Target;
collection: {[path: string]: any};
tiles: {[name: string]: Target};
}

export const initialState: TraversingState = {
Expand All @@ -20,4 +21,5 @@ export const initialState: TraversingState = {
view: 'view',
},
collection: {},
tiles: {},
};
7 changes: 6 additions & 1 deletion projects/nst-test/src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,10 @@
<button [traverseTo]="'/' + repository +'/contents/'">Go</button>
</header>
<section>
<traverser-outlet></traverser-outlet>
<article>
<traverser-outlet></traverser-outlet>
</article>
<aside>
<traverser-tile name="details"></traverser-tile>
</aside>
</section>
9 changes: 9 additions & 0 deletions projects/nst-test/src/app/app.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
section {
display: flex;
article {
width: 80%;
}
aside {
width: 20%;
}
}
8 changes: 6 additions & 2 deletions projects/nst-test/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ 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';

@Component({
selector: 'app-root',
Expand All @@ -19,9 +21,11 @@ export class AppComponent {
private readonly store: Store<TraversingState>,
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);
traverser.addTile('details', '*', NoDetailsComponent);
traverser.addTile('details', 'dir', FolderDetailsComponent);
}
}
10 changes: 8 additions & 2 deletions projects/nst-test/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,18 @@ 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: [
AppComponent,
FileComponent,
FolderComponent,
FileInfoComponent,
NavigationComponent
NavigationComponent,
FolderDetailsComponent,
NoDetailsComponent,
],
imports: [
StoreModule.forRoot({}),
Expand All @@ -45,7 +49,9 @@ import { EffectsModule } from '@ngrx/effects';
entryComponents: [
FileComponent,
FolderComponent,
FileInfoComponent
FileInfoComponent,
FolderDetailsComponent,
NoDetailsComponent,
],
providers: [
{ provide: Resolver, useClass: BasicHttpResolver },
Expand Down
4 changes: 2 additions & 2 deletions projects/nst-test/src/app/file-info/file-info.component.html
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
<p>Size: {{ (context | async).size }}</p>
<p>SHA: {{ (context | async).sha }}</p>
<p>Size: {{ (context | async)?.size }}</p>
<p>SHA: {{ (context | async)?.sha }}</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div>This folder contains {{ (tileContext | async).length }} elements</div>
16 changes: 16 additions & 0 deletions projects/nst-test/src/app/folder/folder-details.component.ts
Original file line number Diff line number Diff line change
@@ -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<TraversingState>) { }


}
2 changes: 1 addition & 1 deletion projects/nst-test/src/app/folder/folder.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
<li *ngFor="let entry of (context | async)">
<a [traverseTo]="entry.url">
{{ entry.name }}
</a>
</a> <button (click)="showDetails(entry.url)">Details</button>
</li>
</ul>
Loading

0 comments on commit 5085fe0

Please sign in to comment.