import { Injectable } from '@angular/core';
-import { AuthHttp, AuthService } from '../shared';
+import { AuthHttp, AuthService, RestExtractor } from '../shared';
@Injectable()
export class AccountService {
private static BASE_USERS_URL = '/api/v1/users/';
- constructor(private authHttp: AuthHttp, private authService: AuthService) { }
+ constructor(
+ private authHttp: AuthHttp,
+ private authService: AuthService,
+ private restExtractor: RestExtractor
+ ) {}
changePassword(newPassword: string) {
const url = AccountService.BASE_USERS_URL + this.authService.getUser().id;
password: newPassword
};
- return this.authHttp.put(url, body);
+ return this.authHttp.put(url, body)
+ .map(this.restExtractor.extractDataBool)
+ .catch((res) => this.restExtractor.handleError(res));
}
}
import { Injectable } from '@angular/core';
-import { Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Friend } from './friend.model';
-import { AuthHttp, AuthService } from '../../../shared';
+import { AuthHttp, RestExtractor } from '../../../shared';
@Injectable()
export class FriendService {
constructor (
private authHttp: AuthHttp,
- private authService: AuthService
+ private restExtractor: RestExtractor
) {}
getFriends(): Observable<Friend[]> {
return this.authHttp.get(FriendService.BASE_FRIEND_URL)
- .map(res => <Friend[]>res.json())
- .catch(this.handleError);
+ // Not implemented as a data list by the server yet
+ // .map(this.restExtractor.extractDataList)
+ .map((res) => res.json())
+ .catch((res) => this.restExtractor.handleError(res));
}
makeFriends(notEmptyUrls) {
};
return this.authHttp.post(FriendService.BASE_FRIEND_URL + 'makefriends', body)
- .map(res => res.status)
- .catch(this.handleError);
+ .map(this.restExtractor.extractDataBool)
+ .catch((res) => this.restExtractor.handleError(res));
}
quitFriends() {
return this.authHttp.get(FriendService.BASE_FRIEND_URL + 'quitfriends')
.map(res => res.status)
- .catch(this.handleError);
- }
-
- private handleError (error: Response) {
- console.error(error);
- return Observable.throw(error.json().error || 'Server error');
+ .catch((res) => this.restExtractor.handleError(res));
}
}
import { Injectable } from '@angular/core';
-import { Response } from '@angular/http';
-import { Observable } from 'rxjs/Observable';
-import { AuthHttp, User } from '../../../shared';
+import { AuthHttp, RestExtractor, ResultList, User } from '../../../shared';
@Injectable()
export class UserService {
// TODO: merge this constant with account
private static BASE_USERS_URL = '/api/v1/users/';
- constructor(private authHttp: AuthHttp) {}
+ constructor(
+ private authHttp: AuthHttp,
+ private restExtractor: RestExtractor
+ ) {}
addUser(username: string, password: string) {
const body = {
password
};
- return this.authHttp.post(UserService.BASE_USERS_URL, body);
+ return this.authHttp.post(UserService.BASE_USERS_URL, body)
+ .map(this.restExtractor.extractDataBool)
+ .catch((res) => this.restExtractor.handleError(res));
}
getUsers() {
return this.authHttp.get(UserService.BASE_USERS_URL)
- .map(res => res.json())
+ .map(this.restExtractor.extractDataList)
.map(this.extractUsers)
- .catch(this.handleError);
+ .catch((res) => this.restExtractor.handleError(res));
}
removeUser(user: User) {
return this.authHttp.delete(UserService.BASE_USERS_URL + user.id);
}
- private extractUsers(body: any) {
- const usersJson = body.data;
- const totalUsers = body.total;
+ private extractUsers(result: ResultList) {
+ const usersJson = result.data;
+ const totalUsers = result.total;
const users = [];
for (const userJson of usersJson) {
users.push(new User(userJson));
return { users, totalUsers };
}
-
- private handleError(error: Response) {
- console.error(error);
- return Observable.throw(error.json().error || 'Server error');
- }
}
import { MenuAdminComponent } from './admin';
import { MenuComponent } from './menu.component';
-import { SearchComponent, SearchService } from './shared';
+import { RestExtractor, RestService, SearchComponent, SearchService } from './shared';
import { VideoService } from './videos';
@Component({
template: require('./app.component.html'),
styles: [ require('./app.component.scss') ],
directives: [ MenuAdminComponent, MenuComponent, ROUTER_DIRECTIVES, SearchComponent ],
- providers: [ VideoService, SearchService ]
+ providers: [ RestExtractor, RestService, VideoService, SearchService ]
})
export class AppComponent {
this.router.navigate(['/videos/list']);
},
error => {
- console.error(error);
+ console.error(error.json);
- if (error.error === 'invalid_grant') {
+ if (error.json.error === 'invalid_grant') {
this.error = 'Credentials are invalid.';
} else {
- this.error = `${error.error}: ${error.error_description}`;
+ this.error = `${error.json.error}: ${error.json.error_description}`;
}
}
);
import { Injectable } from '@angular/core';
-import { Headers, Http, Response, URLSearchParams } from '@angular/http';
+import { Headers, Http, URLSearchParams } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { AuthStatus } from './auth-status.model';
import { AuthUser } from './auth-user.model';
+import { RestExtractor } from '../rest';
@Injectable()
export class AuthService {
private loginChanged: Subject<AuthStatus>;
private user: AuthUser = null;
- constructor(private http: Http) {
+ constructor(private http: Http, private restExtractor: RestExtractor) {
this.loginChanged = new Subject<AuthStatus>();
this.loginChangedSource = this.loginChanged.asObservable();
// Fetch the client_id/client_secret
// FIXME: save in local storage?
this.http.get(AuthService.BASE_CLIENT_URL)
- .map(res => res.json())
- .catch(this.handleError)
+ .map(this.restExtractor.extractDataGet)
+ .catch((res) => this.restExtractor.handleError(res))
.subscribe(
result => {
this.clientId = result.client_id;
};
return this.http.post(AuthService.BASE_TOKEN_URL, body.toString(), options)
- .map(res => res.json())
+ .map(this.restExtractor.extractDataGet)
.map(res => {
res.username = username;
return res;
})
.flatMap(res => this.fetchUserInformations(res))
.map(res => this.handleLogin(res))
- .catch(this.handleError);
+ .catch((res) => this.restExtractor.handleError(res));
}
logout() {
};
return this.http.post(AuthService.BASE_TOKEN_URL, body.toString(), options)
- .map(res => res.json())
+ .map(this.restExtractor.extractDataGet)
.map(res => this.handleRefreshToken(res))
- .catch(this.handleError);
+ .catch((res) => this.restExtractor.handleError(res));
}
private fetchUserInformations (obj: any) {
);
}
- private handleError (error: Response) {
- console.error(error);
- return Observable.throw(error.json() || { error: 'Server error' });
- }
-
private handleLogin (obj: any) {
const id = obj.id;
const username = obj.username;
export * from './auth';
export * from './form-validators';
+export * from './rest';
export * from './search';
export * from './users';
--- /dev/null
+export * from './rest-extractor.service';
+export * from './rest-pagination';
+export * from './rest.service';
--- /dev/null
+import { Injectable } from '@angular/core';
+import { Response } from '@angular/http';
+import { Observable } from 'rxjs/Observable';
+
+export interface ResultList {
+ data: any[];
+ total: number;
+}
+
+@Injectable()
+export class RestExtractor {
+
+ constructor () { ; }
+
+ extractDataBool(res: Response) {
+ return true;
+ }
+
+ extractDataList(res: Response) {
+ const body = res.json();
+
+ const ret: ResultList = {
+ data: body.data,
+ total: body.total
+ };
+
+ return ret;
+ }
+
+ extractDataGet(res: Response) {
+ return res.json();
+ }
+
+ handleError(res: Response) {
+ let text = 'Server error: ';
+ text += res.text();
+ let json = res.json();
+
+ const error = {
+ json,
+ text
+ };
+
+ return Observable.throw(error);
+ }
+}
--- /dev/null
+export interface RestPagination {
+ currentPage: number;
+ itemsPerPage: number;
+ totalItems: number;
+};
--- /dev/null
+import { Injectable } from '@angular/core';
+import { URLSearchParams } from '@angular/http';
+
+import { RestPagination } from './rest-pagination';
+
+@Injectable()
+export class RestService {
+
+ buildRestGetParams(pagination?: RestPagination, sort?: string) {
+ const params = new URLSearchParams();
+
+ if (pagination) {
+ const start: number = (pagination.currentPage - 1) * pagination.itemsPerPage;
+ const count: number = pagination.itemsPerPage;
+
+ params.set('start', start.toString());
+ params.set('count', count.toString());
+ }
+
+ if (sort) {
+ params.set('sort', sort);
+ }
+
+ return params;
+ }
+
+}
export * from './loader';
-export * from './pagination.model';
export * from './sort-field.type';
export * from './video.model';
export * from './video.service';
+++ /dev/null
-export interface Pagination {
- currentPage: number;
- itemsPerPage: number;
- totalItems: number;
-}
import { Injectable } from '@angular/core';
-import { Http, Response, URLSearchParams } from '@angular/http';
+import { Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
-import { Pagination } from './pagination.model';
import { Search } from '../../shared';
import { SortField } from './sort-field.type';
-import { AuthHttp, AuthService } from '../../shared';
+import { AuthHttp, AuthService, RestExtractor, RestPagination, RestService, ResultList } from '../../shared';
import { Video } from './video.model';
@Injectable()
constructor(
private authService: AuthService,
private authHttp: AuthHttp,
- private http: Http
+ private http: Http,
+ private restExtractor: RestExtractor,
+ private restService: RestService
) {}
- getVideo(id: string) {
+ getVideo(id: string): Observable<Video> {
return this.http.get(VideoService.BASE_VIDEO_URL + id)
- .map(res => <Video> res.json())
- .catch(this.handleError);
+ .map(this.restExtractor.extractDataGet)
+ .catch((res) => this.restExtractor.handleError(res));
}
- getVideos(pagination: Pagination, sort: SortField) {
- const params = this.createPaginationParams(pagination);
-
- if (sort) params.set('sort', sort);
+ getVideos(pagination: RestPagination, sort: SortField) {
+ const params = this.restService.buildRestGetParams(pagination, sort);
return this.http.get(VideoService.BASE_VIDEO_URL, { search: params })
.map(res => res.json())
.map(this.extractVideos)
- .catch(this.handleError);
+ .catch((res) => this.restExtractor.handleError(res));
}
removeVideo(id: string) {
return this.authHttp.delete(VideoService.BASE_VIDEO_URL + id)
- .map(res => <number> res.status)
- .catch(this.handleError);
+ .map(this.restExtractor.extractDataBool)
+ .catch((res) => this.restExtractor.handleError(res));
}
- searchVideos(search: Search, pagination: Pagination, sort: SortField) {
- const params = this.createPaginationParams(pagination);
+ searchVideos(search: Search, pagination: RestPagination, sort: SortField) {
+ const params = this.restService.buildRestGetParams(pagination, sort);
if (search.field) params.set('field', search.field);
- if (sort) params.set('sort', sort);
return this.http.get(VideoService.BASE_VIDEO_URL + 'search/' + encodeURIComponent(search.value), { search: params })
- .map(res => res.json())
+ .map(this.restExtractor.extractDataList)
.map(this.extractVideos)
- .catch(this.handleError);
- }
-
- private createPaginationParams(pagination: Pagination) {
- const params = new URLSearchParams();
- const start: number = (pagination.currentPage - 1) * pagination.itemsPerPage;
- const count: number = pagination.itemsPerPage;
-
- params.set('start', start.toString());
- params.set('count', count.toString());
-
- return params;
+ .catch((res) => this.restExtractor.handleError(res));
}
- private extractVideos(body: any) {
- const videos_json = body.data;
- const totalVideos = body.total;
+ private extractVideos(result: ResultList) {
+ const videosJson = result.data;
+ const totalVideos = result.total;
const videos = [];
- for (const video_json of videos_json) {
- videos.push(new Video(video_json));
+ for (const videoJson of videosJson) {
+ videos.push(new Video(videoJson));
}
return { videos, totalVideos };
}
-
- private handleError(error: Response) {
- console.error(error);
- return Observable.throw(error.json().error || 'Server error');
- }
}
import {
LoaderComponent,
- Pagination,
SortField,
Video,
VideoService
} from '../shared';
-import { AuthService, AuthUser, Search, SearchField } from '../../shared';
+import { AuthService, AuthUser, RestPagination, Search, SearchField } from '../../shared';
import { VideoMiniatureComponent } from './video-miniature.component';
import { VideoSortComponent } from './video-sort.component';
import { SearchService } from '../../shared';
export class VideoListComponent implements OnInit, OnDestroy {
loading: BehaviorSubject<boolean> = new BehaviorSubject(false);
- pagination: Pagination = {
+ pagination: RestPagination = {
currentPage: 1,
itemsPerPage: 9,
totalItems: null
import { provideRouter } from '@angular/router';
import { routes } from './app/app.routes';
-import { AuthHttp, AuthService } from './app/shared';
+import { AuthHttp, AuthService, RestExtractor } from './app/shared';
import { AppComponent } from './app/app.component';
if (process.env.ENV === 'production') {
}),
AuthService,
+ RestExtractor,
provideRouter(routes),
"src/app/shared/form-validators/index.ts",
"src/app/shared/form-validators/url.validator.ts",
"src/app/shared/index.ts",
+ "src/app/shared/rest/index.ts",
+ "src/app/shared/rest/mock-rest-table.ts",
+ "src/app/shared/rest/rest-extractor.service.ts",
+ "src/app/shared/rest/rest-filter.model.ts",
+ "src/app/shared/rest/rest-pagination.ts",
+ "src/app/shared/rest/rest-sort.ts",
+ "src/app/shared/rest/rest-table-page.ts",
+ "src/app/shared/rest/rest-table.spec.ts",
+ "src/app/shared/rest/rest-table.ts",
+ "src/app/shared/rest/rest.service.ts",
"src/app/shared/search/index.ts",
"src/app/shared/search/search-field.type.ts",
"src/app/shared/search/search.component.ts",