diff options
Diffstat (limited to 'client/src/app/admin/friends')
14 files changed, 300 insertions, 0 deletions
diff --git a/client/src/app/admin/friends/friend-add/friend-add.component.html b/client/src/app/admin/friends/friend-add/friend-add.component.html new file mode 100644 index 000000000..788f3b44d --- /dev/null +++ b/client/src/app/admin/friends/friend-add/friend-add.component.html | |||
@@ -0,0 +1,26 @@ | |||
1 | <h3>Make friends</h3> | ||
2 | |||
3 | <div *ngIf="error" class="alert alert-danger">{{ error }}</div> | ||
4 | |||
5 | <form (ngSubmit)="makeFriends()" [formGroup]="form"> | ||
6 | <div class="form-group" *ngFor="let url of urls; let id = index; trackBy:customTrackBy"> | ||
7 | <label for="username">Url</label> | ||
8 | |||
9 | <div class="input-group"> | ||
10 | <input | ||
11 | type="text" class="form-control" placeholder="http://domain.com" | ||
12 | [id]="'url-' + id" [formControlName]="'url-' + id" | ||
13 | /> | ||
14 | <span class="input-group-btn"> | ||
15 | <button *ngIf="displayAddField(id)" (click)="addField()" class="btn btn-default" type="button">+</button> | ||
16 | <button *ngIf="displayRemoveField(id)" (click)="removeField(id)" class="btn btn-default" type="button">-</button> | ||
17 | </span> | ||
18 | </div> | ||
19 | |||
20 | <div [hidden]="form.controls['url-' + id].valid || form.controls['url-' + id].pristine" class="alert alert-warning"> | ||
21 | It should be a valid url. | ||
22 | </div> | ||
23 | </div> | ||
24 | |||
25 | <input type="submit" value="Make friends" class="btn btn-default" [disabled]="!isFormValid()"> | ||
26 | </form> | ||
diff --git a/client/src/app/admin/friends/friend-add/friend-add.component.scss b/client/src/app/admin/friends/friend-add/friend-add.component.scss new file mode 100644 index 000000000..5fde51636 --- /dev/null +++ b/client/src/app/admin/friends/friend-add/friend-add.component.scss | |||
@@ -0,0 +1,7 @@ | |||
1 | table { | ||
2 | margin-bottom: 40px; | ||
3 | } | ||
4 | |||
5 | .input-group-btn button { | ||
6 | width: 35px; | ||
7 | } | ||
diff --git a/client/src/app/admin/friends/friend-add/friend-add.component.ts b/client/src/app/admin/friends/friend-add/friend-add.component.ts new file mode 100644 index 000000000..64165a9a5 --- /dev/null +++ b/client/src/app/admin/friends/friend-add/friend-add.component.ts | |||
@@ -0,0 +1,108 @@ | |||
1 | import { Component, OnInit } from '@angular/core'; | ||
2 | import { FormControl, FormGroup } from '@angular/forms'; | ||
3 | import { Router } from '@angular/router'; | ||
4 | |||
5 | import { validateUrl } from '../../../shared'; | ||
6 | import { FriendService } from '../shared'; | ||
7 | |||
8 | @Component({ | ||
9 | selector: 'my-friend-add', | ||
10 | templateUrl: './friend-add.component.html', | ||
11 | styleUrls: [ './friend-add.component.scss' ] | ||
12 | }) | ||
13 | export class FriendAddComponent implements OnInit { | ||
14 | form: FormGroup; | ||
15 | urls = [ ]; | ||
16 | error: string = null; | ||
17 | |||
18 | constructor(private router: Router, private friendService: FriendService) {} | ||
19 | |||
20 | ngOnInit() { | ||
21 | this.form = new FormGroup({}); | ||
22 | this.addField(); | ||
23 | } | ||
24 | |||
25 | addField() { | ||
26 | this.form.addControl(`url-${this.urls.length}`, new FormControl('', [ validateUrl ])); | ||
27 | this.urls.push(''); | ||
28 | } | ||
29 | |||
30 | customTrackBy(index: number, obj: any): any { | ||
31 | return index; | ||
32 | } | ||
33 | |||
34 | displayAddField(index: number) { | ||
35 | return index === (this.urls.length - 1); | ||
36 | } | ||
37 | |||
38 | displayRemoveField(index: number) { | ||
39 | return (index !== 0 || this.urls.length > 1) && index !== (this.urls.length - 1); | ||
40 | } | ||
41 | |||
42 | isFormValid() { | ||
43 | // Do not check the last input | ||
44 | for (let i = 0; i < this.urls.length - 1; i++) { | ||
45 | if (!this.form.controls[`url-${i}`].valid) return false; | ||
46 | } | ||
47 | |||
48 | const lastIndex = this.urls.length - 1; | ||
49 | // If the last input (which is not the first) is empty, it's ok | ||
50 | if (this.urls[lastIndex] === '' && lastIndex !== 0) { | ||
51 | return true; | ||
52 | } else { | ||
53 | return this.form.controls[`url-${lastIndex}`].valid; | ||
54 | } | ||
55 | } | ||
56 | |||
57 | removeField(index: number) { | ||
58 | // Remove the last control | ||
59 | this.form.removeControl(`url-${this.urls.length - 1}`); | ||
60 | this.urls.splice(index, 1); | ||
61 | } | ||
62 | |||
63 | makeFriends() { | ||
64 | this.error = ''; | ||
65 | |||
66 | const notEmptyUrls = this.getNotEmptyUrls(); | ||
67 | if (notEmptyUrls.length === 0) { | ||
68 | this.error = 'You need to specify at less 1 url.'; | ||
69 | return; | ||
70 | } | ||
71 | |||
72 | if (!this.isUrlsUnique(notEmptyUrls)) { | ||
73 | this.error = 'Urls need to be unique.'; | ||
74 | return; | ||
75 | } | ||
76 | |||
77 | const confirmMessage = 'Are you sure to make friends with:\n - ' + notEmptyUrls.join('\n - '); | ||
78 | if (!confirm(confirmMessage)) return; | ||
79 | |||
80 | this.friendService.makeFriends(notEmptyUrls).subscribe( | ||
81 | status => { | ||
82 | // TODO: extractdatastatus | ||
83 | // if (status === 409) { | ||
84 | // alert('Already made friends!'); | ||
85 | // } else { | ||
86 | alert('Make friends request sent!'); | ||
87 | this.router.navigate([ '/admin/friends/list' ]); | ||
88 | // } | ||
89 | }, | ||
90 | error => alert(error.text) | ||
91 | ); | ||
92 | } | ||
93 | |||
94 | private getNotEmptyUrls() { | ||
95 | const notEmptyUrls = []; | ||
96 | |||
97 | Object.keys(this.form.value).forEach((urlKey) => { | ||
98 | const url = this.form.value[urlKey]; | ||
99 | if (url !== '') notEmptyUrls.push(url); | ||
100 | }); | ||
101 | |||
102 | return notEmptyUrls; | ||
103 | } | ||
104 | |||
105 | private isUrlsUnique(urls: string[]) { | ||
106 | return urls.every(url => urls.indexOf(url) === urls.lastIndexOf(url)); | ||
107 | } | ||
108 | } | ||
diff --git a/client/src/app/admin/friends/friend-add/index.ts b/client/src/app/admin/friends/friend-add/index.ts new file mode 100644 index 000000000..a101b3be5 --- /dev/null +++ b/client/src/app/admin/friends/friend-add/index.ts | |||
@@ -0,0 +1 @@ | |||
export * from './friend-add.component'; | |||
diff --git a/client/src/app/admin/friends/friend-list/friend-list.component.html b/client/src/app/admin/friends/friend-list/friend-list.component.html new file mode 100644 index 000000000..d786a7846 --- /dev/null +++ b/client/src/app/admin/friends/friend-list/friend-list.component.html | |||
@@ -0,0 +1,29 @@ | |||
1 | <h3>Friends list</h3> | ||
2 | |||
3 | <table class="table table-hover"> | ||
4 | <thead> | ||
5 | <tr> | ||
6 | <th class="table-column-id">ID</th> | ||
7 | <th>Url</th> | ||
8 | <th>Score</th> | ||
9 | <th>Created Date</th> | ||
10 | </tr> | ||
11 | </thead> | ||
12 | |||
13 | <tbody> | ||
14 | <tr *ngFor="let friend of friends"> | ||
15 | <td>{{ friend.id }}</td> | ||
16 | <td>{{ friend.url }}</td> | ||
17 | <td>{{ friend.score }}</td> | ||
18 | <td>{{ friend.createdDate | date: 'medium' }}</td> | ||
19 | </tr> | ||
20 | </tbody> | ||
21 | </table> | ||
22 | |||
23 | <a *ngIf="friends?.length !== 0" class="add-user btn btn-danger pull-left" (click)="quitFriends()"> | ||
24 | Quit friends | ||
25 | </a> | ||
26 | |||
27 | <a *ngIf="friends?.length === 0" class="add-user btn btn-success pull-right" [routerLink]="['/admin/friends/add']"> | ||
28 | Make friends | ||
29 | </a> | ||
diff --git a/client/src/app/admin/friends/friend-list/friend-list.component.scss b/client/src/app/admin/friends/friend-list/friend-list.component.scss new file mode 100644 index 000000000..cb597e12b --- /dev/null +++ b/client/src/app/admin/friends/friend-list/friend-list.component.scss | |||
@@ -0,0 +1,3 @@ | |||
1 | table { | ||
2 | margin-bottom: 40px; | ||
3 | } | ||
diff --git a/client/src/app/admin/friends/friend-list/friend-list.component.ts b/client/src/app/admin/friends/friend-list/friend-list.component.ts new file mode 100644 index 000000000..88c4800ee --- /dev/null +++ b/client/src/app/admin/friends/friend-list/friend-list.component.ts | |||
@@ -0,0 +1,38 @@ | |||
1 | import { Component, OnInit } from '@angular/core'; | ||
2 | |||
3 | import { Friend, FriendService } from '../shared'; | ||
4 | |||
5 | @Component({ | ||
6 | selector: 'my-friend-list', | ||
7 | templateUrl: './friend-list.component.html', | ||
8 | styleUrls: [ './friend-list.component.scss' ] | ||
9 | }) | ||
10 | export class FriendListComponent implements OnInit { | ||
11 | friends: Friend[]; | ||
12 | |||
13 | constructor(private friendService: FriendService) { } | ||
14 | |||
15 | ngOnInit() { | ||
16 | this.getFriends(); | ||
17 | } | ||
18 | |||
19 | quitFriends() { | ||
20 | if (!confirm('Are you sure?')) return; | ||
21 | |||
22 | this.friendService.quitFriends().subscribe( | ||
23 | status => { | ||
24 | alert('Quit friends!'); | ||
25 | this.getFriends(); | ||
26 | }, | ||
27 | error => alert(error.text) | ||
28 | ); | ||
29 | } | ||
30 | |||
31 | private getFriends() { | ||
32 | this.friendService.getFriends().subscribe( | ||
33 | friends => this.friends = friends, | ||
34 | |||
35 | err => alert(err.text) | ||
36 | ); | ||
37 | } | ||
38 | } | ||
diff --git a/client/src/app/admin/friends/friend-list/index.ts b/client/src/app/admin/friends/friend-list/index.ts new file mode 100644 index 000000000..354c978a4 --- /dev/null +++ b/client/src/app/admin/friends/friend-list/index.ts | |||
@@ -0,0 +1 @@ | |||
export * from './friend-list.component'; | |||
diff --git a/client/src/app/admin/friends/friends.component.ts b/client/src/app/admin/friends/friends.component.ts new file mode 100644 index 000000000..bc3f54158 --- /dev/null +++ b/client/src/app/admin/friends/friends.component.ts | |||
@@ -0,0 +1,8 @@ | |||
1 | import { Component } from '@angular/core'; | ||
2 | |||
3 | @Component({ | ||
4 | template: '<router-outlet></router-outlet>' | ||
5 | }) | ||
6 | |||
7 | export class FriendsComponent { | ||
8 | } | ||
diff --git a/client/src/app/admin/friends/friends.routes.ts b/client/src/app/admin/friends/friends.routes.ts new file mode 100644 index 000000000..7fdef68f9 --- /dev/null +++ b/client/src/app/admin/friends/friends.routes.ts | |||
@@ -0,0 +1,27 @@ | |||
1 | import { Routes } from '@angular/router'; | ||
2 | |||
3 | import { FriendsComponent } from './friends.component'; | ||
4 | import { FriendAddComponent } from './friend-add'; | ||
5 | import { FriendListComponent } from './friend-list'; | ||
6 | |||
7 | export const FriendsRoutes: Routes = [ | ||
8 | { | ||
9 | path: 'friends', | ||
10 | component: FriendsComponent, | ||
11 | children: [ | ||
12 | { | ||
13 | path: '', | ||
14 | redirectTo: 'list', | ||
15 | pathMatch: 'full' | ||
16 | }, | ||
17 | { | ||
18 | path: 'list', | ||
19 | component: FriendListComponent | ||
20 | }, | ||
21 | { | ||
22 | path: 'add', | ||
23 | component: FriendAddComponent | ||
24 | } | ||
25 | ] | ||
26 | } | ||
27 | ]; | ||
diff --git a/client/src/app/admin/friends/index.ts b/client/src/app/admin/friends/index.ts new file mode 100644 index 000000000..dd4df2538 --- /dev/null +++ b/client/src/app/admin/friends/index.ts | |||
@@ -0,0 +1,5 @@ | |||
1 | export * from './friend-add'; | ||
2 | export * from './friend-list'; | ||
3 | export * from './shared'; | ||
4 | export * from './friends.component'; | ||
5 | export * from './friends.routes'; | ||
diff --git a/client/src/app/admin/friends/shared/friend.model.ts b/client/src/app/admin/friends/shared/friend.model.ts new file mode 100644 index 000000000..7cb28f440 --- /dev/null +++ b/client/src/app/admin/friends/shared/friend.model.ts | |||
@@ -0,0 +1,6 @@ | |||
1 | export interface Friend { | ||
2 | id: string; | ||
3 | url: string; | ||
4 | score: number; | ||
5 | createdDate: Date; | ||
6 | } | ||
diff --git a/client/src/app/admin/friends/shared/friend.service.ts b/client/src/app/admin/friends/shared/friend.service.ts new file mode 100644 index 000000000..75826fc17 --- /dev/null +++ b/client/src/app/admin/friends/shared/friend.service.ts | |||
@@ -0,0 +1,39 @@ | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { Observable } from 'rxjs/Observable'; | ||
3 | |||
4 | import { Friend } from './friend.model'; | ||
5 | import { AuthHttp, RestExtractor } from '../../../shared'; | ||
6 | |||
7 | @Injectable() | ||
8 | export class FriendService { | ||
9 | private static BASE_FRIEND_URL: string = '/api/v1/pods/'; | ||
10 | |||
11 | constructor ( | ||
12 | private authHttp: AuthHttp, | ||
13 | private restExtractor: RestExtractor | ||
14 | ) {} | ||
15 | |||
16 | getFriends(): Observable<Friend[]> { | ||
17 | return this.authHttp.get(FriendService.BASE_FRIEND_URL) | ||
18 | // Not implemented as a data list by the server yet | ||
19 | // .map(this.restExtractor.extractDataList) | ||
20 | .map((res) => res.json()) | ||
21 | .catch((res) => this.restExtractor.handleError(res)); | ||
22 | } | ||
23 | |||
24 | makeFriends(notEmptyUrls) { | ||
25 | const body = { | ||
26 | urls: notEmptyUrls | ||
27 | }; | ||
28 | |||
29 | return this.authHttp.post(FriendService.BASE_FRIEND_URL + 'makefriends', body) | ||
30 | .map(this.restExtractor.extractDataBool) | ||
31 | .catch((res) => this.restExtractor.handleError(res)); | ||
32 | } | ||
33 | |||
34 | quitFriends() { | ||
35 | return this.authHttp.get(FriendService.BASE_FRIEND_URL + 'quitfriends') | ||
36 | .map(res => res.status) | ||
37 | .catch((res) => this.restExtractor.handleError(res)); | ||
38 | } | ||
39 | } | ||
diff --git a/client/src/app/admin/friends/shared/index.ts b/client/src/app/admin/friends/shared/index.ts new file mode 100644 index 000000000..0d671637d --- /dev/null +++ b/client/src/app/admin/friends/shared/index.ts | |||
@@ -0,0 +1,2 @@ | |||
1 | export * from './friend.model'; | ||
2 | export * from './friend.service'; | ||