Skip to content

Commit

Permalink
feat(context): add a favorite context for each user
Browse files Browse the repository at this point in the history
  • Loading branch information
mbarbeau committed Nov 13, 2017
1 parent 2f96d69 commit fcf0386
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 7 deletions.
7 changes: 7 additions & 0 deletions src/lib/auth/shared/auth.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,10 @@ export interface AuthOptions {
facebook?: AuthFacebookOptions;
google?: AuthGoogleOptions;
}

export interface User {
source?: string;
sourceId?: string;
email?: string;
defaultContextId?: string;
}
27 changes: 25 additions & 2 deletions src/lib/auth/shared/auth.service.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { Injectable, Optional } from '@angular/core';
import { Http, Headers } from '@angular/http';
import { Router } from '@angular/router';
import { AuthHttp } from 'angular2-jwt';

import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Rx';
import { JwtHelper } from 'angular2-jwt';

import { ConfigService } from '../../core';
import { ConfigService, RequestService } from '../../core';
import { Base64 } from '../../utils';

import { AuthOptions } from '../shared';
import { AuthOptions, User } from './auth.interface';

@Injectable()
export class AuthService {
Expand All @@ -20,6 +21,8 @@ export class AuthService {
private anonymous: boolean = false;

constructor(private http: Http,
private authHttp: AuthHttp,
private requestService: RequestService,
private config: ConfigService,
@Optional() private router: Router) {

Expand Down Expand Up @@ -115,6 +118,26 @@ export class AuthService {
}
}

getUserInfo(): Observable<User> {
const url = this.options.url + '/info';
const request = this.authHttp.get(url);
return this.requestService.register(request, 'Get user info error')
.map((res) => {
const user: User = res.json();
return user;
});
}

updateUser(user: User): Observable<User> {
const url = this.options.url;
const request = this.authHttp.patch(url, JSON.stringify(user));
return this.requestService.register(request, 'Update user error')
.map((res) => {
const userUpdated: User = res.json();
return userUpdated;
});
}

private encodePassword(password: string) {
return Base64.encode(password);
}
Expand Down
2 changes: 2 additions & 0 deletions src/lib/auth/shared/poi/poi.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export class PoiService {
}

get(): Observable<Poi[]> {
if (!this.baseUrl) { return Observable.empty(); }

const url = this.baseUrl + '/pois';
const request = this.authHttp.get(url);
return this.requestService.register(request, 'Get POIs error')
Expand Down
11 changes: 10 additions & 1 deletion src/lib/context/context-item/context-item.component.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
<md-list-item>
<md-icon md-list-avatar>{{context.icon ? context.icon : 'star'}}</md-icon>
<button md-list-avatar
md-icon-button
igoStopPropagation
[md-tooltip]="'igo.context.favorite' | translate"
[color]="default ? 'primary' : 'default'"
(click)="favorite.emit(context)">
<md-icon>
{{context.icon ? context.icon : 'star'}}
</md-icon>
</button>
<h4 mdLine>{{context.title}}</h4>

<div *ngIf="auth.authenticated && context.permission === typePermission[typePermission.read]"
Expand Down
8 changes: 8 additions & 0 deletions src/lib/context/context-item/context-item.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,18 @@ export class ContextItemComponent {
}
private _context: DetailedContext;

@Input()
get default(): boolean { return this._default; }
set default(value: boolean) {
this._default = value;
}
private _default: boolean = false;

@Output() edit = new EventEmitter<DetailedContext>();
@Output() delete = new EventEmitter<DetailedContext>();
@Output() save = new EventEmitter<DetailedContext>();
@Output() clone = new EventEmitter<DetailedContext>();
@Output() favorite = new EventEmitter<DetailedContext>();
@Output() managePermissions = new EventEmitter<DetailedContext>();
@Output() manageTools = new EventEmitter<DetailedContext>();

Expand Down
23 changes: 23 additions & 0 deletions src/lib/context/context-list/context-list-binding.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Subscription } from 'rxjs/Subscription';
import { MessageService, LanguageService } from '../../core';
import { ConfirmDialogService } from '../../shared';
import { MapService } from '../../map';
import { AuthService } from '../../auth';
import { Context, DetailedContext, ContextsList, ContextService } from '../shared';
import { ContextListComponent } from './context-list.component';

Expand All @@ -17,6 +18,7 @@ export class ContextListBindingDirective implements OnInit, OnDestroy {
private component: ContextListComponent;
private contexts$$: Subscription;
private selectedContext$$: Subscription;
private defaultContextId$$: Subscription;

@HostListener('select', ['$event']) onSelect(context: Context) {
this.contextService.loadContext(context.uri);
Expand Down Expand Up @@ -72,6 +74,20 @@ export class ContextListBindingDirective implements OnInit, OnDestroy {

}

@HostListener('favorite', ['$event']) onFavorite(context: Context) {
this.authService.updateUser({
defaultContextId: String(context.id)
}).subscribe(() => {
this.contextService.defaultContextId$.next(context.id);
const translate = this.languageService.translate;
const message = translate.instant('igo.context.dialog.favoriteMsg', {
value: context.title
});
const title = translate.instant('igo.context.dialog.favoriteTitle');
this.messageService.info(message, title);
});
}

@HostListener('manageTools', ['$event']) onManageTools(context: Context) {
this.contextService.loadEditedContext(context.uri);
}
Expand Down Expand Up @@ -114,6 +130,7 @@ export class ContextListBindingDirective implements OnInit, OnDestroy {

constructor(@Self() component: ContextListComponent,
private contextService: ContextService,
private authService: AuthService,
private mapService: MapService,
private languageService: LanguageService,
private confirmDialogService: ConfirmDialogService,
Expand All @@ -128,6 +145,11 @@ export class ContextListBindingDirective implements OnInit, OnDestroy {
this.contexts$$ = this.contextService.contexts$
.subscribe(contexts => this.handleContextsChange(contexts));

this.defaultContextId$$ = this.contextService.defaultContextId$
.subscribe(id => {
this.component.defaultContextId = id
});

// See feature-list.component for an explanation about the debounce time
this.selectedContext$$ = this.contextService.context$
.debounceTime(100)
Expand All @@ -139,6 +161,7 @@ export class ContextListBindingDirective implements OnInit, OnDestroy {
ngOnDestroy() {
this.contexts$$.unsubscribe();
this.selectedContext$$.unsubscribe();
this.defaultContextId$$.unsubscribe();
}

private handleContextsChange(contexts: ContextsList) {
Expand Down
2 changes: 2 additions & 0 deletions src/lib/context/context-list/context-list.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
color="accent"
[selected]="selectedContext && selectedContext.uri === context.uri"
[context]="context"
[default]="this.defaultContextId === context.id"
(edit)="edit.emit(context)"
(delete)="delete.emit(context)"
(clone)="clone.emit(context)"
(save)="save.emit(context)"
(favorite)="favorite.emit(context)"
(manageTools)="manageTools.emit(context)"
(managePermissions)="managePermissions.emit(context)"
(select)="select.emit(context)"
Expand Down
8 changes: 8 additions & 0 deletions src/lib/context/context-list/context-list.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,20 @@ export class ContextListComponent {
}
private _selectedContext: DetailedContext;

@Input()
get defaultContextId(): string { return this._defaultContextId; }
set defaultContextId(value: string) {
this._defaultContextId = value;
}
private _defaultContextId: string;

@Output() select = new EventEmitter<DetailedContext>();
@Output() unselect = new EventEmitter<DetailedContext>();
@Output() edit = new EventEmitter<DetailedContext>();
@Output() delete = new EventEmitter<DetailedContext>();
@Output() save = new EventEmitter<DetailedContext>();
@Output() clone = new EventEmitter<DetailedContext>();
@Output() favorite = new EventEmitter<DetailedContext>();
@Output() managePermissions = new EventEmitter<DetailedContext>();
@Output() manageTools = new EventEmitter<DetailedContext>();

Expand Down
43 changes: 39 additions & 4 deletions src/lib/context/shared/context.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export class ContextService {

public context$ = new BehaviorSubject<DetailedContext>(undefined);
public contexts$ = new BehaviorSubject<ContextsList>({ours: []});
public defaultContextId$ = new BehaviorSubject<string>(undefined);
public editedContext$ = new BehaviorSubject<DetailedContext>(undefined);
private mapViewFromRoute: ContextMapView = {};
private options: ContextServiceOptions;
Expand Down Expand Up @@ -46,6 +47,7 @@ export class ContextService {
this.authService.authenticate$
.subscribe((authenticated) => {
if (authenticated === null) {
this.loadDefaultContext();
return;
}
const contexts$$ = this.contexts$.subscribe((contexts) => {
Expand Down Expand Up @@ -89,6 +91,17 @@ export class ContextService {
.catch(res => this.handleError(res, id));
}

getDefault(): Observable<DetailedContext> {
const url = this.baseUrl + '/contexts/default';
const request = this.authHttp.get(url);
return this.requestService.register(request, 'Get context default error')
.map((res) => {
const context: DetailedContext = res.json();
this.defaultContextId$.next(context.id);
return context;
});
}

delete(id: string): Observable<void> {
const url = this.baseUrl + '/contexts/' + id;
const request = this.authHttp.delete(url);
Expand Down Expand Up @@ -219,16 +232,30 @@ deletePermissionAssociation(contextId: string, permissionId: string): Observable
}

loadDefaultContext() {
const loadFct = () => {
if (this.baseUrl && this.authService.authenticated) {
this.getDefault().subscribe(
(_context: DetailedContext) => this.setContext(_context),
() => {
this.defaultContextId$.next(undefined);
this.loadContext(this.options.defaultContextUri);
}
);
} else {
this.loadContext(this.options.defaultContextUri);
}
}

if (this.route && this.route.options.contextKey) {
this.route.queryParams.subscribe(params => {
const contextParam = params[this.route.options.contextKey as string];
if (contextParam) {
this.options.defaultContextUri = contextParam;
}
this.loadContext(this.options.defaultContextUri);
loadFct();
});
} else {
this.loadContext(this.options.defaultContextUri);
loadFct();
}
}

Expand All @@ -242,6 +269,13 @@ deletePermissionAssociation(contextId: string, permissionId: string): Observable
}

setContext(context: DetailedContext) {
const currentContext = this.context$.value;
if (currentContext && context && context.id === currentContext.id) {
context.map.view.keepCurrentView = true;
this.context$.next(context);
return;
}

// Update the tools options with those found in the context
if (context.tools !== undefined) {
this.toolService.setTools(context.tools);
Expand Down Expand Up @@ -331,16 +365,17 @@ deletePermissionAssociation(contextId: string, permissionId: string): Observable
throw [{title: titleError, text: textError}];
}

private handleContextsChange(contexts: ContextsList) {
private handleContextsChange(contexts: ContextsList, keepCurrentContext = false) {

const context = this.context$.value;
const editedContext = this.editedContext$.value;

if (!this.findContext(context)) {
if (!keepCurrentContext || !this.findContext(context)) {
this.loadDefaultContext();
} else {
context.map.view.keepCurrentView = true;
this.context$.next(context);
this.getDefault().subscribe(() => {});
}
const editedFound = this.findContext(editedContext);
if (!editedFound || editedFound.permission !== 'write') {
Expand Down

0 comments on commit fcf0386

Please sign in to comment.