From 8845d591e9f93dfca805128b336b104642e78313 Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 26 Jan 2020 13:21:53 +0100 Subject: [PATCH 01/16] Change feedservice to delete post when media upload fails --- src/app/services/feed/feed.service.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/app/services/feed/feed.service.ts b/src/app/services/feed/feed.service.ts index 9f0a8fd..cfd1623 100644 --- a/src/app/services/feed/feed.service.ts +++ b/src/app/services/feed/feed.service.ts @@ -194,17 +194,23 @@ export class FeedService extends BaseService { const updatedPosts = this.posts.getValue(); const post = this.constructPost(response); this.uploadPostImage(post.id, file).subscribe((result) => { - if (this.activePostList === Sort.NEW) { - post.mediaUrl = result.fileName; - post.mediaType = result.fileName.endsWith('.png') ? 'IMAGE' : 'VIDEO'; - updatedPosts.unshift(post); - this.posts.next(updatedPosts); + if (result.success) { + if (this.activePostList === Sort.NEW) { + post.mediaUrl = result.fileName; + post.mediaType = result.fileName.endsWith('.png') ? 'IMAGE' : 'VIDEO'; + updatedPosts.unshift(post); + this.posts.next(updatedPosts); + this.posting.next(false); + } + } else { + console.error(result.error); this.posting.next(false); + this.deletePost(post.id).subscribe(); } }, error => { console.error(error); this.posting.next(false); - this.deletePost(post.id); + this.deletePost(post.id).subscribe(); }); } )); From 0bb2fcf8d7da536c22e5d879ea8a92316dc3e27b Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 26 Jan 2020 14:04:46 +0100 Subject: [PATCH 02/16] Add levels are loaded from the backend now --- src/app/components/about/about.component.html | 2 +- src/app/components/about/about.component.ts | 12 +++- .../main-navigation.component.ts | 2 - .../components/profile/profile.component.ts | 4 +- src/app/models/friendinfo.ts | 2 - src/app/models/levellist.ts | 32 ++++++---- src/app/services/activity/activity.service.ts | 64 +++++++++++++++---- 7 files changed, 80 insertions(+), 38 deletions(-) diff --git a/src/app/components/about/about.component.html b/src/app/components/about/about.component.html index 5bf352e..6f2cb3e 100644 --- a/src/app/components/about/about.component.html +++ b/src/app/components/about/about.component.html @@ -20,7 +20,7 @@ - + diff --git a/src/app/components/about/about.component.ts b/src/app/components/about/about.component.ts index 3983dc3..2fdf072 100644 --- a/src/app/components/about/about.component.ts +++ b/src/app/components/about/about.component.ts @@ -1,6 +1,6 @@ import {Component, OnInit, ViewChild} from '@angular/core'; import {Activitylist} from 'src/app/models/activity'; -import {Levellist} from 'src/app/models/levellist'; +import {LevelList} from 'src/app/models/levellist'; import {MatSort} from '@angular/material/sort'; import {MatTableDataSource} from '@angular/material/table'; import {ActivityService} from 'src/app/services/activity/activity.service'; @@ -12,12 +12,12 @@ import {ActivityService} from 'src/app/services/activity/activity.service'; }) export class AboutComponent implements OnInit { actionlist: Activitylist = new Activitylist(); - levellist: Levellist = new Levellist(); + levellist: LevelList = new LevelList(); displayedColumns = ['points', 'name', 'description']; dataSource = new MatTableDataSource(this.actionlist.Actions); displayedLevelColumns = ['level', 'name']; - levelSource = this.levellist.levels; + levelSource = new MatTableDataSource(this.levellist.levels); constructor(private activityService: ActivityService) { } @@ -31,6 +31,12 @@ export class AboutComponent implements OnInit { this.dataSource = new MatTableDataSource(this.actionlist.Actions); this.dataSource.sort = this.sort; }); + this.activityService.getLevels(); + this.activityService.levelList.subscribe(response => { + this.levellist = response; + this.levelSource = new MatTableDataSource(this.levellist.levels); + this.levelSource.sort = this.sort; + }); } } diff --git a/src/app/components/main-navigation/main-navigation.component.ts b/src/app/components/main-navigation/main-navigation.component.ts index a9bcdc2..3898ce2 100644 --- a/src/app/components/main-navigation/main-navigation.component.ts +++ b/src/app/components/main-navigation/main-navigation.component.ts @@ -4,7 +4,6 @@ import {DatasharingService} from '../../services/datasharing.service'; import {RequestService} from '../../services/request/request.service'; import {SettingsService} from '../../services/settings/settings.service'; import {environment} from 'src/environments/environment'; -import {Levellist} from 'src/app/models/levellist'; import {Router} from '@angular/router'; import {User} from 'src/app/models/user'; import {OverlayContainer} from '@angular/cdk/overlay'; @@ -33,7 +32,6 @@ export class MainNavigationComponent implements OnInit { userId: number; username: string; user: User; - levellist: Levellist = new Levellist(); level: string; points: number; profileUrl = '/profile/1'; diff --git a/src/app/components/profile/profile.component.ts b/src/app/components/profile/profile.component.ts index 200f2d9..22232a7 100644 --- a/src/app/components/profile/profile.component.ts +++ b/src/app/components/profile/profile.component.ts @@ -1,7 +1,7 @@ import {Component, OnInit} from '@angular/core'; import {NavigationEnd, Router} from '@angular/router'; import {User} from 'src/app/models/user'; -import {Levellist} from 'src/app/models/levellist'; +import {LevelList} from 'src/app/models/levellist'; import {RequestService} from 'src/app/services/request/request.service'; import {DatasharingService} from '../../services/datasharing.service'; import {ProfileService} from 'src/app/services/profile/profile.service'; @@ -18,7 +18,7 @@ import {Lightbox} from 'ngx-lightbox'; styleUrls: ['./profile.component.sass'] }) export class ProfileComponent implements OnInit { - levellist: Levellist = new Levellist(); + levellist: LevelList = new LevelList(); ownProfile = false; userProfile: User = new User(); self: User; diff --git a/src/app/models/friendinfo.ts b/src/app/models/friendinfo.ts index 887737b..637d000 100644 --- a/src/app/models/friendinfo.ts +++ b/src/app/models/friendinfo.ts @@ -1,5 +1,3 @@ -import {Levellist} from 'src/app/models/levellist'; - export class FriendInfo { id: number; name: string; diff --git a/src/app/models/levellist.ts b/src/app/models/levellist.ts index 09be30c..b510103 100644 --- a/src/app/models/levellist.ts +++ b/src/app/models/levellist.ts @@ -1,23 +1,27 @@ -export class Levellist { - levels: { level: number, name: string, points: number }[] = [ - {level: 0, name: 'Green Horn', points: 0}, - {level: 1, name: 'Good Willed', points: 100}, - {level: 2, name: 'Helper', points: 200}, - {level: 3, name: 'World Saver', points: 300}, - {level: 4, name: 'Hero of the Green Country', points: 400}, - {level: 5, name: 'Champion of the Earth', points: 500}, - {level: 6, name: 'Intergallactic Superhero', points: 600}, - ]; +export class Level { + id: number; + name: string; + levelNumber: number; + points: number; - getLevelName(level: number): any { - let name = 'not defined'; + constructor(id: number, name: string, levelNumber: number, points: number) { + this.id = id; + this.name = name; + this.levelNumber = levelNumber; + this.points = points; + } +} +export class LevelList { + levels: Level[] = []; + + getLevelName(level: number): string { + let name = 'not defined'; for (const rank of this.levels) { - if (level === rank.level) { + if (level === rank.levelNumber) { name = rank.name; } } return name; } - } diff --git a/src/app/services/activity/activity.service.ts b/src/app/services/activity/activity.service.ts index df2246d..8056a9c 100644 --- a/src/app/services/activity/activity.service.ts +++ b/src/app/services/activity/activity.service.ts @@ -1,18 +1,40 @@ import {Injectable} from '@angular/core'; import {BehaviorSubject} from 'rxjs'; import {Activity, Activitylist} from 'src/app/models/activity'; +import {Level, LevelList} from 'src/app/models/levellist'; import {environment} from 'src/environments/environment'; -import {Http} from '@angular/http'; +import {HttpClient, HttpErrorResponse} from '@angular/common/http'; +import {BaseService} from '../base.service'; @Injectable({ providedIn: 'root' }) -export class ActivityService { +export class ActivityService extends BaseService { public activitylist = new BehaviorSubject(new Activitylist()); + public levelList = new BehaviorSubject(new LevelList()); - constructor(private http: Http) { + constructor(http: HttpClient) { + super(http); + } + + private static buildGetActivityBody(): any { + const body = { + query: `query{getActivities{ + id name description points + }}`, variables: {} + }; + return body; + } + + private static buildGetLevelsBody(): any { + const body = { + query: `query{getLevels{ + id name levelNumber points + }}`, variables: {} + }; + return body; } changeUserInfo(pActivitylist: Activitylist) { @@ -21,22 +43,24 @@ export class ActivityService { public getActivities() { if (this.activitylist.getValue().Actions.length < 1) { - const headers = new Headers(); - headers.set('Content-Type', 'application/json'); - this.http.post(environment.graphQLUrl, this.buildJson()).subscribe(result => { + this.http.post(environment.graphQLUrl, ActivityService.buildGetActivityBody(), {headers: this.headers}) + .pipe(this.retryRated()) + .subscribe(result => { // push onto subject - this.activitylist.next(this.renderActivity(result.json())); + this.activitylist.next(this.renderActivity(result)); }); } } - public buildJson(): any { - const body = { - query: `query{getActivities{ - id name description points - }}`, variables: {} - }; - return body; + public getLevels() { + if (this.activitylist.getValue().Actions.length < 1) { + this.http.post(environment.graphQLUrl, ActivityService.buildGetLevelsBody(), {headers: this.headers}) + .pipe(this.retryRated()) + .subscribe(result => { + // push onto subject + this.levelList.next(this.renderLevels(result)); + }); + } } public renderActivity(response: any): Activitylist { @@ -50,5 +74,17 @@ export class ActivityService { } return activitylist; } + + public renderLevels(response: any): LevelList { + const levelList = new LevelList(); + for (const level of response.data.getLevels) { + levelList.levels.push(new Level( + level.id, + level.name, + level.levelNumber, + level.points)); + } + return levelList; + } } From 0713b7f4398e65253e7ced80020655dacb77d07b Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 26 Jan 2020 18:07:06 +0100 Subject: [PATCH 03/16] Add groupService functions to add and remove group admins --- src/app/services/group/group.service.ts | 51 ++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/src/app/services/group/group.service.ts b/src/app/services/group/group.service.ts index 48beabd..5d12fb8 100644 --- a/src/app/services/group/group.service.ts +++ b/src/app/services/group/group.service.ts @@ -18,7 +18,7 @@ const getGroupGraphqlQuery = `query($groupId: ID!) { picture deletable creator{id name handle} - admins{id name handle} + admins{id name handle profilePicture} members{id name handle profilePicture} events{id name dueDate joined} } @@ -82,6 +82,55 @@ export class GroupService extends BaseService { })); } + + public addGroupAdmin(userId: string, groupId: string) { + const body = { + query: `mutation($groupId: ID!, $userId: ID!) { + addGroupAdmin(groupId: $groupId, userId: $userId) { + admins{id name handle profilePicture} + } + }`, variables: { + userId, + groupId + } + }; + + return this.postGraphql(body, null, 0) + .pipe(tap(response => { + const admins: User[] = []; + for (const admin of response.data.addGroupAdmin) { + admins.push(admin.assignFromResponse(admin)); + } + const group = this.group.getValue(); + group.admins = admins; + this.group.next(group); + })); + } + + public removeGroupAdmin(userId: string, groupId: string) { + const body = { + query: `mutation($groupId: ID!, $userId: ID!) { + removeGroupAdmin(groupId: $groupId, userId: $userId) { + admins{id name handle profilePicture} + } + }`, variables: { + userId, + groupId + } + }; + + return this.postGraphql(body, null, 0) + .pipe(tap(response => { + const admins: User[] = []; + for (const admin of response.data.addGroupAdmin) { + admins.push(admin.assignFromResponse(admin)); + } + const group = this.group.getValue(); + group.admins = admins; + this.group.next(group); + })); + } + public joinEvent(eventId: string) { const body = { query: `mutation($eventId: ID!) { From f8e533e9ca38164e6ce5c8ac04b3f2267f62b39e Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 26 Jan 2020 18:17:33 +0100 Subject: [PATCH 04/16] Add limitation of post length --- src/app/components/feed/feed.component.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/components/feed/feed.component.html b/src/app/components/feed/feed.component.html index 00f4bbb..3d31915 100644 --- a/src/app/components/feed/feed.component.html +++ b/src/app/components/feed/feed.component.html @@ -22,8 +22,9 @@ - + {{content.value.length}} / 2048
From 079456aecce8ca5227724398b4d0582f2ea49c8a Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 26 Jan 2020 19:56:01 +0100 Subject: [PATCH 05/16] WIP: add remove groupAdmin --- src/app/components/feed/feed.component.html | 2 +- src/app/components/group/group.component.html | 30 +++++++++++++++++++ src/app/components/group/group.component.sass | 16 +++++++--- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/app/components/feed/feed.component.html b/src/app/components/feed/feed.component.html index 3d31915..b3c31e9 100644 --- a/src/app/components/feed/feed.component.html +++ b/src/app/components/feed/feed.component.html @@ -24,7 +24,7 @@ - {{content.value.length}} / 2048 + {{content.value.length}} / 2048
diff --git a/src/app/components/group/group.component.html b/src/app/components/group/group.component.html index 652f47b..1196c44 100644 --- a/src/app/components/group/group.component.html +++ b/src/app/components/group/group.component.html @@ -149,6 +149,36 @@
+ + + + Admins + + +
+ + +
+ + + + +
+
+ +
+ {{admin.username}} + {{admin.handle}} +
+
+
+
diff --git a/src/app/components/group/group.component.sass b/src/app/components/group/group.component.sass index 6046785..6b9947d 100644 --- a/src/app/components/group/group.component.sass +++ b/src/app/components/group/group.component.sass @@ -107,13 +107,21 @@ $mat-card-header-size: 100px !default margin-top: 0.5em margin-bottom: 0.5em - .profile-picture - background-image: url(https://material.angular.io/assets/img/examples/shiba1.jpg) - background-size: cover - .profile-picture:hover cursor: pointer +$mat-card-header-size-small: 54px !default +.profile-picture-small + height: $mat-card-header-size-small + width: $mat-card-header-size-small + border-radius: 50% + flex-shrink: 0 + background-size: cover + transition-duration: 0.5s + z-index: 10 + object-fit: cover + + .pointer cursor: pointer From fae9e79f24489d3deedda353d7c3139d4dafa78d Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 26 Jan 2020 20:56:22 +0100 Subject: [PATCH 06/16] Add add/remove group admin functionallity --- src/app/components/group/group.component.html | 125 +++++++----------- src/app/components/group/group.component.sass | 42 ++++++ src/app/components/group/group.component.ts | 42 +++--- src/app/models/group.ts | 15 ++- src/app/models/user.ts | 13 +- src/app/services/group/group.service.ts | 92 ++++++------- 6 files changed, 178 insertions(+), 151 deletions(-) diff --git a/src/app/components/group/group.component.html b/src/app/components/group/group.component.html index 1196c44..64677ef 100644 --- a/src/app/components/group/group.component.html +++ b/src/app/components/group/group.component.html @@ -4,40 +4,30 @@
- + camera_alt
- +
{{groupProfile.name}}
- - -
-
@@ -45,8 +35,8 @@
- created by {{groupProfile.creator.username}} + created by + {{groupProfile.creator.username}} @{{groupProfile.creator.handle}}
@@ -60,42 +50,32 @@
- + camera_alt
- +
{{groupProfile.name}} - created by {{groupProfile.creator.username}} + created by + {{groupProfile.creator.username}} @{{groupProfile.creator.handle}}
- - -
-
@@ -116,22 +96,18 @@
- + {{event.name}} {{event.date}}
- -
@@ -145,36 +121,30 @@ Members -
- -
- - - - - Admins - -
- + -
- - +
-
- -
- {{admin.username}} - {{admin.handle}}
@@ -186,5 +156,4 @@

Group not found :(

-
- +
\ No newline at end of file diff --git a/src/app/components/group/group.component.sass b/src/app/components/group/group.component.sass index 6b9947d..8125bfb 100644 --- a/src/app/components/group/group.component.sass +++ b/src/app/components/group/group.component.sass @@ -121,6 +121,48 @@ $mat-card-header-size-small: 54px !default z-index: 10 object-fit: cover +.member-card + box-sizing: border-box + width: 100% + margin-top: 0.5em + outline: none + user-select: none + + ::ng-deep .mat-card-header-text + width: 1000% + margin: auto 0 auto 24px + + .mat-card-subtitle + margin: 0 + word-break: break-all + + .mat-card-title + margin: 0 + word-break: break-all + + .request-button + margin-top: 0.5em + margin-bottom: 0.5em + + .pointer:hover + cursor: pointer + + .icon-box + text-align: right + width: 100% + + $pic-size: 40px !default + .card-picture + cursor: pointer + height: $pic-size + width: $pic-size + border-radius: 50% + flex-shrink: 0 + background-size: cover + transition-duration: 0.5s + z-index: 10 + object-fit: cover + .pointer cursor: pointer diff --git a/src/app/components/group/group.component.ts b/src/app/components/group/group.component.ts index 014483b..2d7cb5f 100644 --- a/src/app/components/group/group.component.ts +++ b/src/app/components/group/group.component.ts @@ -1,15 +1,15 @@ -import {Component, OnInit, ViewChild} from '@angular/core'; -import {Data, NavigationEnd, Router} from '@angular/router'; -import {User} from 'src/app/models/user'; -import {MatSort} from '@angular/material/sort'; -import {RequestService} from 'src/app/services/request/request.service'; -import {DatasharingService} from '../../services/datasharing.service'; -import {GroupService} from 'src/app/services/group/group.service'; -import {Group} from 'src/app/models/group'; -import {Event} from 'src/app/models/event'; -import {MatDialog, MatDialogRef} from '@angular/material/dialog'; -import {DialogGroupFileUploadComponent} from './fileUpload/fileUpload.component'; -import {Lightbox} from 'ngx-lightbox'; +import { Component, OnInit, ViewChild } from '@angular/core'; +import { Data, NavigationEnd, Router } from '@angular/router'; +import { User } from 'src/app/models/user'; +import { MatSort } from '@angular/material/sort'; +import { RequestService } from 'src/app/services/request/request.service'; +import { DatasharingService } from '../../services/datasharing.service'; +import { GroupService } from 'src/app/services/group/group.service'; +import { Group } from 'src/app/models/group'; +import { Event } from 'src/app/models/event'; +import { MatDialog, MatDialogRef } from '@angular/material/dialog'; +import { DialogGroupFileUploadComponent } from './fileUpload/fileUpload.component'; +import { Lightbox } from 'ngx-lightbox'; // DIALOG COMPONENT to create events @Component({ @@ -100,7 +100,7 @@ export class GroupComponent implements OnInit { }); } - @ViewChild(MatSort, {static: true}) sort: MatSort; + @ViewChild(MatSort, { static: true }) sort: MatSort; ngOnInit() { this.loading = true; @@ -185,9 +185,9 @@ export class GroupComponent implements OnInit { private deleteGroup() { this.groupService.deleteGroup(this.groupProfile.id) - .subscribe(response => { - this.router.navigateByUrl(''); - }); + .subscribe(response => { + this.router.navigateByUrl(''); + }); } leaveGroup() { @@ -198,11 +198,19 @@ export class GroupComponent implements OnInit { }); } + addGroupAdmin(user: User) { + this.groupService.addGroupAdmin(user.userID.toString(), this.id).subscribe(); + } + + removeGroupAdmin(user: User) { + this.groupService.removeGroupAdmin(user.userID.toString(), this.id).subscribe(); + } + openPfpLightbox() { this.lightbox.open([{ src: this.groupProfile.picture, thumb: this.groupProfile.picture, - }], 0, {disableScrolling: true}); + }], 0, { disableScrolling: true }); } } diff --git a/src/app/models/group.ts b/src/app/models/group.ts index 51be07f..908613e 100644 --- a/src/app/models/group.ts +++ b/src/app/models/group.ts @@ -1,7 +1,7 @@ -import {User} from 'src/app/models/user'; -import {Event} from 'src/app/models/event'; -import {IGroup} from './interfaces/IGroup'; -import {environment} from 'src/environments/environment'; +import { User } from 'src/app/models/user'; +import { Event } from 'src/app/models/event'; +import { IGroup } from './interfaces/IGroup'; +import { environment } from 'src/environments/environment'; export class Group { id: number; @@ -36,6 +36,13 @@ export class Group { user = new User(); this.admins.push(user.assignFromResponse(admin)); } + for (const admin of this.admins) { + for (const member of this.members) { + if (member.userID === admin.userID) { + member.isGroupAdmin = true; + } + } + } } if (groupDataResponse.events) { for (const event of groupDataResponse.events) { diff --git a/src/app/models/user.ts b/src/app/models/user.ts index 6836d10..7e435eb 100644 --- a/src/app/models/user.ts +++ b/src/app/models/user.ts @@ -1,9 +1,9 @@ -import {FriendRequest} from 'src/app/models/friendRequest'; -import {FriendInfo} from 'src/app/models/friendinfo'; -import {GroupInfo} from 'src/app/models/groupinfo'; -import {Post} from 'src/app/models/post'; -import {IUser} from './interfaces/IUser'; -import {environment} from 'src/environments/environment'; +import { FriendRequest } from 'src/app/models/friendRequest'; +import { FriendInfo } from 'src/app/models/friendinfo'; +import { GroupInfo } from 'src/app/models/groupinfo'; +import { Post } from 'src/app/models/post'; +import { IUser } from './interfaces/IUser'; +import { environment } from 'src/environments/environment'; export class User { loggedIn = false; @@ -18,6 +18,7 @@ export class User { joinedAt: string; friendCount: number; groupCount: number; + isGroupAdmin: boolean; darkmode = false; diff --git a/src/app/services/group/group.service.ts b/src/app/services/group/group.service.ts index 5d12fb8..7527fe6 100644 --- a/src/app/services/group/group.service.ts +++ b/src/app/services/group/group.service.ts @@ -1,14 +1,14 @@ -import {Injectable} from '@angular/core'; -import {HttpClient} from '@angular/common/http'; -import {environment} from 'src/environments/environment'; -import {User} from 'src/app/models/user'; -import {Event} from 'src/app/models/event'; -import {BehaviorSubject} from 'rxjs'; -import {Group} from 'src/app/models/group'; -import {tap} from 'rxjs/operators'; -import {BaseService} from '../base.service'; -import {IFileUploadResult} from '../../models/interfaces/IFileUploadResult'; -import {DatasharingService} from 'src/app/services/datasharing.service'; +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { environment } from 'src/environments/environment'; +import { User } from 'src/app/models/user'; +import { Event } from 'src/app/models/event'; +import { BehaviorSubject } from 'rxjs'; +import { Group } from 'src/app/models/group'; +import { tap } from 'rxjs/operators'; +import { BaseService } from '../base.service'; +import { IFileUploadResult } from '../../models/interfaces/IFileUploadResult'; +import { DatasharingService } from 'src/app/services/datasharing.service'; const getGroupGraphqlQuery = `query($groupId: ID!) { getGroup(groupId:$groupId){ @@ -18,7 +18,7 @@ const getGroupGraphqlQuery = `query($groupId: ID!) { picture deletable creator{id name handle} - admins{id name handle profilePicture} + admins{id name handle} members{id name handle profilePicture} events{id name dueDate joined} } @@ -40,14 +40,14 @@ export class GroupService extends BaseService { */ private static buildGetGroupBody(id: string): any { return { - query: getGroupGraphqlQuery, variables: {groupId: id} + query: getGroupGraphqlQuery, variables: { groupId: id } }; } public getGroupData(groupId: string) { const url = environment.graphQLUrl; - return this.http.post(url, GroupService.buildGetGroupBody(groupId), {headers: this.headers}) + return this.http.post(url, GroupService.buildGetGroupBody(groupId), { headers: this.headers }) .pipe(this.retryRated()) .pipe(tap(response => { const group_ = new Group(); @@ -73,16 +73,16 @@ export class GroupService extends BaseService { }; return this.postGraphql(body, null, 0) - .pipe(tap(response => { - const event = new Event(); - event.assignFromResponse(response.data.createEvent); - const group = this.group.getValue(); - group.events.push(event); - this.group.next(group); - })); + .pipe(tap(response => { + const event = new Event(); + event.assignFromResponse(response.data.createEvent); + const group = this.group.getValue(); + group.events.push(event); + this.group.next(group); + })); } - + public addGroupAdmin(userId: string, groupId: string) { const body = { query: `mutation($groupId: ID!, $userId: ID!) { @@ -96,15 +96,15 @@ export class GroupService extends BaseService { }; return this.postGraphql(body, null, 0) - .pipe(tap(response => { - const admins: User[] = []; - for (const admin of response.data.addGroupAdmin) { - admins.push(admin.assignFromResponse(admin)); - } - const group = this.group.getValue(); - group.admins = admins; - this.group.next(group); - })); + .pipe(tap(response => { + const admins: User[] = []; + for (const admin of response.data.addGroupAdmin) { + admins.push(admin.assignFromResponse(admin)); + } + const group = this.group.getValue(); + group.admins = admins; + this.group.next(group); + })); } public removeGroupAdmin(userId: string, groupId: string) { @@ -120,15 +120,15 @@ export class GroupService extends BaseService { }; return this.postGraphql(body, null, 0) - .pipe(tap(response => { - const admins: User[] = []; - for (const admin of response.data.addGroupAdmin) { - admins.push(admin.assignFromResponse(admin)); - } - const group = this.group.getValue(); - group.admins = admins; - this.group.next(group); - })); + .pipe(tap(response => { + const admins: User[] = []; + for (const admin of response.data.addGroupAdmin) { + admins.push(admin.assignFromResponse(admin)); + } + const group = this.group.getValue(); + group.admins = admins; + this.group.next(group); + })); } public joinEvent(eventId: string) { @@ -176,9 +176,9 @@ export class GroupService extends BaseService { } }; return this.postGraphql(body) - .pipe(tap(response => { - this.data.deleteGroup(groupId); - })); + .pipe(tap(response => { + this.data.deleteGroup(groupId); + })); } public leaveGroup(groupId: number) { @@ -190,8 +190,8 @@ export class GroupService extends BaseService { } }; return this.postGraphql(body) - .pipe(tap(response => { - this.data.deleteGroup(groupId); - })); + .pipe(tap(response => { + this.data.deleteGroup(groupId); + })); } } From f5328cd57ab806e425825b7aa17ddb6973aab990 Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 26 Jan 2020 21:18:04 +0100 Subject: [PATCH 07/16] Add delete event functionallity --- src/app/components/group/group.component.html | 4 +++ src/app/components/group/group.component.ts | 4 +++ src/app/models/event.ts | 4 ++- src/app/models/interfaces/IEvent.ts | 2 ++ src/app/services/group/group.service.ts | 30 ++++++++++++++++--- 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/app/components/group/group.component.html b/src/app/components/group/group.component.html index 64677ef..bb4c11a 100644 --- a/src/app/components/group/group.component.html +++ b/src/app/components/group/group.component.html @@ -110,6 +110,10 @@ matTooltipShowDelay="500" (click)="leaveEvent(event)" [disabled]="!event.joined"> event_busy + diff --git a/src/app/components/group/group.component.ts b/src/app/components/group/group.component.ts index 2d7cb5f..fa81f61 100644 --- a/src/app/components/group/group.component.ts +++ b/src/app/components/group/group.component.ts @@ -174,6 +174,10 @@ export class GroupComponent implements OnInit { }); } + public deleteEvent(event: Event) { + this.groupService.deleteEvent(event.id).subscribe(); + } + public showUserProfile(user: User) { this.router.navigate(['profile/' + user.userID]); } diff --git a/src/app/models/event.ts b/src/app/models/event.ts index a01d2f7..e65111e 100644 --- a/src/app/models/event.ts +++ b/src/app/models/event.ts @@ -1,10 +1,11 @@ -import {IEvent} from './interfaces/IEvent'; +import { IEvent } from './interfaces/IEvent'; export class Event { id: string; name: string; date: string; joined: boolean; + deletable: boolean; public assignFromResponse(eventDataResponse: IEvent) { this.id = eventDataResponse.id; @@ -12,6 +13,7 @@ export class Event { const temp = new Date(Number(eventDataResponse.dueDate)); this.date = temp.toLocaleString('en-GB'); this.joined = eventDataResponse.joined; + this.deletable = eventDataResponse.deletable; return this; } diff --git a/src/app/models/interfaces/IEvent.ts b/src/app/models/interfaces/IEvent.ts index cdf7fa0..49f1c2a 100644 --- a/src/app/models/interfaces/IEvent.ts +++ b/src/app/models/interfaces/IEvent.ts @@ -7,4 +7,6 @@ export interface IEvent { dueDate: string; joined: boolean; + + deletable: boolean; } diff --git a/src/app/services/group/group.service.ts b/src/app/services/group/group.service.ts index 7527fe6..3f1c935 100644 --- a/src/app/services/group/group.service.ts +++ b/src/app/services/group/group.service.ts @@ -20,7 +20,7 @@ const getGroupGraphqlQuery = `query($groupId: ID!) { creator{id name handle} admins{id name handle} members{id name handle profilePicture} - events{id name dueDate joined} + events{id name dueDate joined deletable} } }`; @@ -146,8 +146,6 @@ export class GroupService extends BaseService { } public leaveEvent(eventId: string) { - const headers = new Headers(); - headers.set('Content-Type', 'application/json'); const body = { query: `mutation($eventId: ID!) { leaveEvent(eventId: $eventId) { @@ -157,7 +155,31 @@ export class GroupService extends BaseService { eventId: eventId } }; - return this.postGraphql(body); + return this.postGraphql(body) + .pipe(this.retryRated()); + } + + public deleteEvent(eventId: string) { + const body = { + query: `mutation($eventId: ID!) { + deleteEvent(eventId: $eventId) { + joined + } + }`, variables: { + eventId + } + }; + return this.postGraphql(body) + .pipe(this.retryRated()) + .pipe(tap(response => { + const group = this.group.getValue(); + for (let i = 0; i < group.events.length; i++) { + if (group.events[i].id === eventId) { + group.events.splice(i, 1); + } + } + this.group.next(group); + })); } public changeProfilePicture(file: any, id: number) { From becbb0a73f48621062457f344c52e990512aa73f Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 26 Jan 2020 22:04:56 +0100 Subject: [PATCH 08/16] Add instant group admin update --- src/app/models/group.ts | 28 +++++++++++++++---------- src/app/services/group/group.service.ts | 22 +++++-------------- 2 files changed, 22 insertions(+), 28 deletions(-) diff --git a/src/app/models/group.ts b/src/app/models/group.ts index 908613e..6314ee5 100644 --- a/src/app/models/group.ts +++ b/src/app/models/group.ts @@ -2,6 +2,7 @@ import { User } from 'src/app/models/user'; import { Event } from 'src/app/models/event'; import { IGroup } from './interfaces/IGroup'; import { environment } from 'src/environments/environment'; +import { IUser } from './interfaces/IUser'; export class Group { id: number; @@ -32,17 +33,7 @@ export class Group { } } if (groupDataResponse.admins) { - for (const admin of groupDataResponse.admins) { - user = new User(); - this.admins.push(user.assignFromResponse(admin)); - } - for (const admin of this.admins) { - for (const member of this.members) { - if (member.userID === admin.userID) { - member.isGroupAdmin = true; - } - } - } + this.updateAdmins(groupDataResponse.admins); } if (groupDataResponse.events) { for (const event of groupDataResponse.events) { @@ -55,6 +46,21 @@ export class Group { return this; } + public updateAdmins(admins: IUser[]) { + // this.admins = []; + for (const admin of admins) { + const user = new User(); + this.admins.push(user.assignFromResponse(admin)); + } + for (const admin of this.admins) { + for (const member of this.members) { + if (member.userID === admin.userID) { + member.isGroupAdmin = true; + } + } + } + } + buildPictureUrl(path: string): string { if (path) { return environment.greenvironmentUrl + path; diff --git a/src/app/services/group/group.service.ts b/src/app/services/group/group.service.ts index 3f1c935..eba4b1f 100644 --- a/src/app/services/group/group.service.ts +++ b/src/app/services/group/group.service.ts @@ -87,22 +87,17 @@ export class GroupService extends BaseService { const body = { query: `mutation($groupId: ID!, $userId: ID!) { addGroupAdmin(groupId: $groupId, userId: $userId) { - admins{id name handle profilePicture} + admins{id name handle} } }`, variables: { userId, groupId } }; - return this.postGraphql(body, null, 0) .pipe(tap(response => { - const admins: User[] = []; - for (const admin of response.data.addGroupAdmin) { - admins.push(admin.assignFromResponse(admin)); - } const group = this.group.getValue(); - group.admins = admins; + group.updateAdmins(response.data.addGroupAdmin); this.group.next(group); })); } @@ -111,22 +106,17 @@ export class GroupService extends BaseService { const body = { query: `mutation($groupId: ID!, $userId: ID!) { removeGroupAdmin(groupId: $groupId, userId: $userId) { - admins{id name handle profilePicture} + admins{id name handle} } }`, variables: { userId, groupId } }; - return this.postGraphql(body, null, 0) .pipe(tap(response => { - const admins: User[] = []; - for (const admin of response.data.addGroupAdmin) { - admins.push(admin.assignFromResponse(admin)); - } const group = this.group.getValue(); - group.admins = admins; + group.updateAdmins(response.data.removeGroupAdmin); this.group.next(group); })); } @@ -162,9 +152,7 @@ export class GroupService extends BaseService { public deleteEvent(eventId: string) { const body = { query: `mutation($eventId: ID!) { - deleteEvent(eventId: $eventId) { - joined - } + deleteEvent(eventId: $eventId) }`, variables: { eventId } From 787008ebfb1367fd7b9bc32d592b7cfcb6b866e4 Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 26 Jan 2020 22:15:34 +0100 Subject: [PATCH 09/16] Fix only creator can remove/add admins --- src/app/components/group/group.component.html | 2 +- src/app/components/group/group.component.ts | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/app/components/group/group.component.html b/src/app/components/group/group.component.html index bb4c11a..132e5b1 100644 --- a/src/app/components/group/group.component.html +++ b/src/app/components/group/group.component.html @@ -136,7 +136,7 @@ {{user.handle}} [admin] -
+
diff --git a/src/app/components/group/group.component.ts b/src/app/components/group/group.component.ts index fa81f61..d9ef4d7 100644 --- a/src/app/components/group/group.component.ts +++ b/src/app/components/group/group.component.ts @@ -76,6 +76,7 @@ export class GroupComponent implements OnInit { self: User; id: string; isAdmin = false; + isCreator = false; groupNotFound = false; loading = false; @@ -120,6 +121,11 @@ export class GroupComponent implements OnInit { this.isAdmin = true; } } + if (this.groupProfile.creator.userID === this.self.userID) { + this.isCreator = true; + } else { + this.isCreator = false; + } for (const member of this.groupProfile.members) { member.allowedToSendRequest = this.requestService.isAllowedToSendRequest(member.userID, this.self); } From 085d90114c371c4c42d0e3e78955e0dc461c5259 Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 26 Jan 2020 22:38:37 +0100 Subject: [PATCH 10/16] Fix add/remove admins --- src/app/models/group.ts | 2 +- src/app/services/group/group.service.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/models/group.ts b/src/app/models/group.ts index 6314ee5..4d67937 100644 --- a/src/app/models/group.ts +++ b/src/app/models/group.ts @@ -47,7 +47,7 @@ export class Group { } public updateAdmins(admins: IUser[]) { - // this.admins = []; + this.admins = []; for (const admin of admins) { const user = new User(); this.admins.push(user.assignFromResponse(admin)); diff --git a/src/app/services/group/group.service.ts b/src/app/services/group/group.service.ts index eba4b1f..9e57aaf 100644 --- a/src/app/services/group/group.service.ts +++ b/src/app/services/group/group.service.ts @@ -64,6 +64,7 @@ export class GroupService extends BaseService { name dueDate joined + deletable } }`, variables: { name: name, From cb35d79fe299506538523d094083de64796935e6 Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 27 Jan 2020 09:08:31 +0100 Subject: [PATCH 11/16] Fix add/delete admins --- src/app/components/group/group.component.ts | 8 ++++++-- src/app/services/group/group.service.ts | 7 +++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/app/components/group/group.component.ts b/src/app/components/group/group.component.ts index d9ef4d7..e639a62 100644 --- a/src/app/components/group/group.component.ts +++ b/src/app/components/group/group.component.ts @@ -209,11 +209,15 @@ export class GroupComponent implements OnInit { } addGroupAdmin(user: User) { - this.groupService.addGroupAdmin(user.userID.toString(), this.id).subscribe(); + this.groupService.addGroupAdmin(user.userID.toString(), this.id).subscribe(response => { + user.isGroupAdmin = true; + }); } removeGroupAdmin(user: User) { - this.groupService.removeGroupAdmin(user.userID.toString(), this.id).subscribe(); + this.groupService.removeGroupAdmin(user.userID.toString(), this.id).subscribe(response => { + user.isGroupAdmin = false; + }); } openPfpLightbox() { diff --git a/src/app/services/group/group.service.ts b/src/app/services/group/group.service.ts index 9e57aaf..6b96b6c 100644 --- a/src/app/services/group/group.service.ts +++ b/src/app/services/group/group.service.ts @@ -98,7 +98,7 @@ export class GroupService extends BaseService { return this.postGraphql(body, null, 0) .pipe(tap(response => { const group = this.group.getValue(); - group.updateAdmins(response.data.addGroupAdmin); + group.updateAdmins(response.data.addGroupAdmin.admins); this.group.next(group); })); } @@ -114,10 +114,13 @@ export class GroupService extends BaseService { groupId } }; + const group = this.group.getValue(); + group.admins = []; + this.group.next(group); return this.postGraphql(body, null, 0) .pipe(tap(response => { const group = this.group.getValue(); - group.updateAdmins(response.data.removeGroupAdmin); + group.updateAdmins(response.data.removeGroupAdmin.admins); this.group.next(group); })); } From fead28b01365c20a6914e47ee69361c5f9c5cf3a Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 27 Jan 2020 09:37:33 +0100 Subject: [PATCH 12/16] Fix level list --- src/app/services/activity/activity.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/services/activity/activity.service.ts b/src/app/services/activity/activity.service.ts index 8056a9c..138b411 100644 --- a/src/app/services/activity/activity.service.ts +++ b/src/app/services/activity/activity.service.ts @@ -53,7 +53,7 @@ export class ActivityService extends BaseService { } public getLevels() { - if (this.activitylist.getValue().Actions.length < 1) { + if (this.levelList.getValue().levels.length < 1) { this.http.post(environment.graphQLUrl, ActivityService.buildGetLevelsBody(), {headers: this.headers}) .pipe(this.retryRated()) .subscribe(result => { From 6b5daded4619c98442679ba9f084aaff48ca9c45 Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 27 Jan 2020 10:11:40 +0100 Subject: [PATCH 13/16] Add privacy policy --- .../components/imprint/imprint.component.html | 149 +++++++++++++++++- .../components/imprint/imprint.component.sass | 14 +- 2 files changed, 155 insertions(+), 8 deletions(-) diff --git a/src/app/components/imprint/imprint.component.html b/src/app/components/imprint/imprint.component.html index d53a447..718b468 100644 --- a/src/app/components/imprint/imprint.component.html +++ b/src/app/components/imprint/imprint.component.html @@ -1,6 +1,147 @@ -Imprint +
-

The greenvironment network is being developed by the greenvironment team

-

Contact

-

Email: nick.derkoenig@greenvironment.net

+Imprint +
+

Privacy Policy

+

Last updated: January 22, 2020

+

This Privacy Policy describes Our policies and procedures on the collection, use and disclosure of Your information + when You use the Service and tells You about Your privacy rights and how the law protects You.

+

Interpretation and Definitions

+

Interpretation

+

The words of which the initial letter is capitalized have meanings defined under the following conditions.

+

The following definitions shall have the same meaning regardless of whether they appear in singular or in plural. +

+

Definitions

+

For the purposes of this Privacy Policy:

+
    +
  • +

    You means the individual accessing or using the Service, or We, or other legal entity on + behalf of which such individual is accessing or using the Service, as applicable.

    +
  • +
  • +

    Team Greenvironment (referred to as either "Team Greenvironment", "We", + "Us" or "Our" in this Agreement) refers to the Greenvironment team.

    +
  • +
  • +

    Account means a unique account created for You to access our Service or parts of our Service. +

    +
  • +
  • +

    Website refers to Greenvironment, accessible from https://greenvironment.net/

    +
  • +
  • +

    Service refers to the Website.

    +
  • +
  • +

    Third-party Social Media Service refers to any website or any social network website through + which a User can log in or create an account to use the Service.

    +
  • +
  • +

    Personal Data is any information that relates to an identified or identifiable individual.

    +
  • +
  • +

    Cookies are small files that are placed on Your computer, mobile device or any other device by + a website, containing the details of Your browsing history on that website among its many uses.

    +
  • +
  • +

    Usage Data refers to data collected automatically, either generated by the use of the Service + or from the Service infrastructure itself (for example, the duration of a page visit).

    +
  • +
+

Collecting and Using Your Personal Data

+

Types of Data Collected

+

Account Data

+

While using Our Service, We may ask You to provide Us with certain personally identifiable information that will be + saved to your account:

+

Email Address

+

To identify a unique user as a human and to provide a way to log in.

+

Password

+

To provide a secured access to your account. It will only be saved as a hashed value.

+

Username

+

The display name of the user as a human friendly way of representation.

+

Handle

+

A unique username that can be used for identification.

+

Posts

+

Collected to display them to other users.

+

Votes

+

The Upvote or Downvote performed on a post to display the sum of votes all users performed.

+

Profile Pictures

+

A way to enhance the users profile. Stored public accessible on the server.

+

Invites

+

Only visible to the user who was addressed.

+

Friends

+

Only the User and his friend can see that they are friends.The data will be deleted after the friendship is + canceled.

+

Rang points and rang

+

Collected to show other user how good the user helped to protect the environment. Rang and rang points are visible + to all users.

+

Groups/Events

+

The date is used to assign the user to groups and events. Collected to show them to other group- /Event- members. +

+

Chatroom

+

The member are showed to each others.

+

Chat Messages

+

Stored in plain text in the database. The message is visible to all other group members even if the user left the + group

+

Cookies

+

We use Cookies to save the session of the user. So if the user visits Greenvironment the next time he is already + logged in. You can instruct your browser to refuse all Cookies or to indicate when a Cookie is being saved. However, + if ou do not accept Cookies, You may not be able to use some parts of our Service.

+

Use of Your Personal Data

+

Your Personal Data will be used for the following purposes:

+
    +
  • To manage Your Account: to manage Your registration as a user of the Service. The Personal Data + You provide can give You access to different functionalities of the Service that are available to You as a + registered user.
  • +
  • To contact You: To contact You by email.
  • +
+

Retention of Your Personal Data

+

We will retain Your Personal Data only for as long as is necessary for the purposes set out in this Privacy Policy. + We will retain and use Your Personal Data to the extent necessary to comply with our legal obligations (for example, + if we are required to retain your data to comply with applicable laws), resolve disputes, and enforce our legal + agreements and policies.

+

Transfer of Your Personal Data

+

Your information, including Personal Data, is processed at Our operating offices and in any other places where the + parties involved in the processing are located. It means that this information may be transferred to — and + maintained on — computers located outside of Your state, province, country or other governmental jurisdiction where + the data protection laws may differ than those from Your jurisdiction.

+

Your consent to this Privacy Policy followed by Your submission of such information represents Your agreement to + that transfer.

+

We will take all steps reasonably necessary to ensure that Your data is treated securely and in accordance with + this Privacy Policy and no transfer of Your Personal Data will take place to an organization or a country unless + there are adequate controls in place including the security of Your data and other personal information.

+

Disclosure of Your Personal Data

+ +

We may disclose Your Personal Data in the good faith belief that such action is necessary to:

+
    +
  • Comply with a legal obligation
  • +
  • Protect and defend the rights or property of the Greenvironment Team
  • +
  • Prevent or investigate possible wrongdoing in connection with the Service
  • +
  • Protect the personal safety of Users of the Service or the public
  • +
  • Protect against legal liability
  • +
+

Security of Your Personal Data

+

The security of Your Personal Data is important to Us, but remember that no method of transmission over the + Internet, or method of electronic storage is 100% secure. While We strive to use technical acceptable means to + protect Your Personal Data, We cannot guarantee its absolute security.

+

Links to Other Websites

+

Our Service may contain links to other websites that are not operated by Us. If You click on a third party link, + You will be directed to that third party's site. We strongly advise You to review the Privacy Policy of every site + You visit.

+

We have no control over and assume no responsibility for the content, privacy policies or practices of any third + party sites or services.

+

Changes to this Privacy Policy

+

We may update our Privacy Policy from time to time. We will notify You of any changes by posting the new Privacy + Policy on this page.

+

We will let You know via email and/or a prominent notice on Our Service, prior to the change becoming effective and + update the "Last updated" date at the top of this Privacy Policy.

+

You are advised to review this Privacy Policy periodically for any changes. Changes to this Privacy Policy are + effective when they are posted on this page.

+

Contact Us

+

If you have any questions about this Privacy Policy, You can contact us:

+ +
\ No newline at end of file diff --git a/src/app/components/imprint/imprint.component.sass b/src/app/components/imprint/imprint.component.sass index 571666b..81ba057 100644 --- a/src/app/components/imprint/imprint.component.sass +++ b/src/app/components/imprint/imprint.component.sass @@ -3,12 +3,18 @@ #imprint - padding: 2em - max-width: 35em + position: fixed + width: 100% + height: calc(100% - 56px) + overflow: scroll + +#text-box margin: 0 auto + max-width: 800px + padding: 2em + ::ng-deep a + color: $primary-color -h1.mat-display-1 - margin: 0 From 5eac1567c4ebb35c0a9ffcaa59cf17f22311bebd Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 27 Jan 2020 10:32:40 +0100 Subject: [PATCH 14/16] Add check boxes on register page --- .../register/register.component.html | 8 ++++++++ .../register/register.component.sass | 6 ++++++ .../components/register/register.component.ts | 20 +++++++++++++++++-- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/app/components/register/register.component.html b/src/app/components/register/register.component.html index fb5b370..635da5f 100644 --- a/src/app/components/register/register.component.html +++ b/src/app/components/register/register.component.html @@ -28,6 +28,14 @@
+

+ I am older than 16 years. + +

+

+ I've read the privacy policy. + +

diff --git a/src/app/components/register/register.component.sass b/src/app/components/register/register.component.sass index 96133b0..f80b13a 100644 --- a/src/app/components/register/register.component.sass +++ b/src/app/components/register/register.component.sass @@ -5,6 +5,8 @@ padding: 2em max-width: 35em margin: 0 auto + ::ng-deep a + color: $primary-color .example-container display: flex @@ -26,6 +28,10 @@ input.example-right-align .mat-error margin-bottom: 0.25em +.check-box + float: left + margin-right: 1em + .mat-raised-button margin: 0.25em width: 100% diff --git a/src/app/components/register/register.component.ts b/src/app/components/register/register.component.ts index abd544e..ca5f1b9 100644 --- a/src/app/components/register/register.component.ts +++ b/src/app/components/register/register.component.ts @@ -14,6 +14,8 @@ export class RegisterComponent implements OnInit { errorMessage: string; hide1 = true; hide2 = true; + ageCheck = false; + imprintCheck = false; constructor(private registerService: RegisterService) { this.registration = {username: null, passwordHash: null, email: null}; @@ -28,7 +30,7 @@ export class RegisterComponent implements OnInit { onClickSubmit(pUsername: string, pEmail: string, pPasswordHash: string, pPasswordHashRepeat: string) { this.errorOccurred = false; this.errorMessage = ' '; - if (this.passwordSame(pPasswordHash, pPasswordHashRepeat)) { + if (this.passwordSame(pPasswordHash, pPasswordHashRepeat) && this.boxesChecked()) { this.registration.username = pUsername.trim(); this.registration.email = pEmail.trim().toLowerCase(); this.registration.passwordHash = sha512.sha512(pPasswordHash); @@ -38,7 +40,6 @@ export class RegisterComponent implements OnInit { passwordSame(pwd: string, pwd2: string) { if (pwd === pwd2) { - console.log('password same'); return true; } else { this.errorOccurred = true; @@ -47,6 +48,21 @@ export class RegisterComponent implements OnInit { } } + boxesChecked(): boolean { + if (this.imprintCheck && this.ageCheck) { + console.log('all boxes checked'); + return true; + } else { + this.errorOccurred = true; + if (!this.ageCheck) { + this.errorMessage = 'You have to confirm your age.'; + } else if (!this.imprintCheck) { + this.errorMessage = 'You have to confirm that you read the privacy policy.'; + } + return false; + } + } + ngOnInit() { } From 74a1b7a7eaaad333583dcbe0fe07bde73f7c6751 Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 27 Jan 2020 11:12:49 +0100 Subject: [PATCH 15/16] Add Errormessage --- src/app/components/feed/feed.component.ts | 29 ++++++--------- src/app/services/feed/feed.service.ts | 44 +++++++++++++++++++---- 2 files changed, 48 insertions(+), 25 deletions(-) diff --git a/src/app/components/feed/feed.component.ts b/src/app/components/feed/feed.component.ts index abb2992..97cbdb5 100644 --- a/src/app/components/feed/feed.component.ts +++ b/src/app/components/feed/feed.component.ts @@ -1,6 +1,6 @@ import {Component, OnInit, ViewChild, ElementRef} from '@angular/core'; import {Post} from 'src/app/models/post'; -import {FeedService, Sort} from 'src/app/services/feed/feed.service'; +import {FeedService, Sort, PostingState} from 'src/app/services/feed/feed.service'; import {Activitylist} from 'src/app/models/activity'; import {DatasharingService} from '../../services/datasharing.service'; import {ActivityService} from 'src/app/services/activity/activity.service'; @@ -63,10 +63,14 @@ export class FeedComponent implements OnInit { this.feedService.postsAvailable.subscribe(available => { this.loadingMostLiked = this.loadingNew = available; }); - this.feedService.posting.subscribe(posting => { + this.feedService.postingState.subscribe(postingState => { const temp = this.posting; - this.posting = posting; - if (temp !== this.posting && !this.posting) { + + this.posting = postingState.posting; + this.errorOccurred = postingState.errorOccured; + this.errorMessage = postingState.errorMessage; + + if (!this.posting && this.posting !== temp && !postingState.errorOccured) { this.resetPostInput(); } }); @@ -79,22 +83,9 @@ export class FeedComponent implements OnInit { */ createPost(postElement, activityId: string) { if (postElement && activityId && this.checked) { - this.posting = true; - this.feedService.createPostActivity(postElement.value, activityId, this.file).subscribe(() => { - }, (error: IErrorResponse) => { - this.errorOccurred = true; - this.posting = false; - this.errorMessage = error.error.errors[0].message; - }); + this.feedService.createPostActivity(postElement.value, activityId, this.file).subscribe(); } else if (postElement) { - this.posting = true; - this.feedService.createPost(postElement.value, this.file).subscribe((result) => { - }, (error: IErrorResponse) => { - console.log(error); - this.posting = false; - this.errorOccurred = true; - this.errorMessage = error.error.errors[0].message; - }); + this.feedService.createPost(postElement.value, this.file).subscribe(); } } diff --git a/src/app/services/feed/feed.service.ts b/src/app/services/feed/feed.service.ts index cfd1623..ebdee57 100644 --- a/src/app/services/feed/feed.service.ts +++ b/src/app/services/feed/feed.service.ts @@ -9,6 +9,7 @@ import {tap} from 'rxjs/operators'; import {BaseService} from '../base.service'; import {formatDate} from '@angular/common'; import {IFileUploadResult} from '../../models/interfaces/IFileUploadResult'; +import { IErrorResponse } from 'src/app/models/interfaces/IErrorResponse'; const createPostGqlQuery = `mutation($content: String!, $type: PostType) { createPost(content: $content, type: $type) { @@ -98,6 +99,11 @@ export enum Sort { NEW = 'NEW', TOP = 'TOP', } +export class PostingState { + posting = false; + errorOccured = false; + errorMessage = 'An error occured.'; +} @Injectable({ providedIn: 'root' @@ -109,7 +115,7 @@ export class FeedService extends BaseService { } public postsAvailable = new BehaviorSubject(true); - public posting = new BehaviorSubject(false); + public postingState = new BehaviorSubject(new PostingState()); public posts: BehaviorSubject = new BehaviorSubject([]); private activePostList: Sort = Sort.NEW; private offset = 0; @@ -187,7 +193,7 @@ export class FeedService extends BaseService { * @param file - a file that is being uploaded with the post */ private createPostRequest(body: { variables: any; query: string }, file?: File) { - this.posting.next(true); + this.setPostingState(true); if (file) { return this.postGraphql(body, null, 0) .pipe(tap(response => { @@ -200,34 +206,60 @@ export class FeedService extends BaseService { post.mediaType = result.fileName.endsWith('.png') ? 'IMAGE' : 'VIDEO'; updatedPosts.unshift(post); this.posts.next(updatedPosts); - this.posting.next(false); + this.setPostingState(false); } } else { console.error(result.error); - this.posting.next(false); + this.setPostingError(result.error); this.deletePost(post.id).subscribe(); } }, error => { console.error(error); - this.posting.next(false); + this.setPostingError(error); this.deletePost(post.id).subscribe(); }); + }, (error: IErrorResponse) => { + this.setPostingError(error.error.errors[0].message); } )); } else if (!file) { return this.postGraphql(body, null, 0) .pipe(tap(response => { - this.posting.next(false); + this.setPostingState(false); const updatedPosts = this.posts.getValue(); if (this.activePostList === Sort.NEW) { const post = this.constructPost(response); updatedPosts.unshift(post); this.posts.next(updatedPosts); } + }, (error: IErrorResponse) => { + console.log(error); + this.setPostingError(error.error.errors[0].message); })); } } + setPostingState(b: boolean) { + if (b) { + this.postingState.getValue().posting = true; + this.postingState.getValue().errorOccured = false; + this.postingState.getValue().errorMessage = ''; + this.postingState.next(this.postingState.getValue()); + } else { + this.postingState.getValue().posting = false; + this.postingState.getValue().errorOccured = false; + this.postingState.getValue().errorMessage = ''; + this.postingState.next(this.postingState.getValue()); + } + } + + setPostingError(error: string) { + this.postingState.getValue().posting = false; + this.postingState.getValue().errorOccured = true; + this.postingState.getValue().errorMessage = error; + this.postingState.next(this.postingState.getValue()); + } + /** * Uploads a file for a post * @param postId From e112023dc378a809cd60e7e250661b9410d1b763 Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 27 Jan 2020 15:59:28 +0100 Subject: [PATCH 16/16] Add post reporting function --- .../feed/postlist/postlist.component.html | 32 ++++-- .../feed/postlist/postlist.component.ts | 29 ++++- src/app/components/group/group.component.html | 2 +- src/app/models/reportReason.ts | 11 ++ src/app/services/activity/activity.service.ts | 71 +++++++++--- src/app/services/feed/feed.service.ts | 108 +++++++++++------- src/app/services/group/group.service.ts | 3 + 7 files changed, 178 insertions(+), 78 deletions(-) create mode 100644 src/app/models/reportReason.ts diff --git a/src/app/components/feed/postlist/postlist.component.html b/src/app/components/feed/postlist/postlist.component.html index f07a137..f74d789 100644 --- a/src/app/components/feed/postlist/postlist.component.html +++ b/src/app/components/feed/postlist/postlist.component.html @@ -1,16 +1,23 @@
- +
- - + + + +
@@ -22,10 +29,11 @@
- +
- post image + post image
{{post.upvotes}}
{{post.downvotes}}
@@ -57,4 +69,4 @@
- + \ No newline at end of file diff --git a/src/app/components/feed/postlist/postlist.component.ts b/src/app/components/feed/postlist/postlist.component.ts index 84e2044..fee24fa 100644 --- a/src/app/components/feed/postlist/postlist.component.ts +++ b/src/app/components/feed/postlist/postlist.component.ts @@ -1,7 +1,10 @@ -import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; -import {Post} from 'src/app/models/post'; -import {FeedService} from 'src/app/services/feed/feed.service'; -import {Router} from '@angular/router'; +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { Post } from 'src/app/models/post'; +import { FeedService } from 'src/app/services/feed/feed.service'; +import { Router } from '@angular/router'; +import { DatasharingService } from 'src/app/services/datasharing.service'; +import { ActivityService } from 'src/app/services/activity/activity.service'; +import { ReportReason } from 'src/app/models/reportReason'; @Component({ selector: 'feed-postlist', @@ -13,11 +16,23 @@ export class PostlistComponent implements OnInit { @Input() childPostList: Post[]; @Output() voteEvent = new EventEmitter(); selectedPost: Post; + loggedIn = false; + reportReasons: ReportReason[] = new Array(); - constructor(private feedService: FeedService, private router: Router) { + constructor(private feedService: FeedService, + private data: DatasharingService, + private router: Router, + private activityService: ActivityService) { } ngOnInit() { + this.data.currentUser.subscribe(user => { + this.loggedIn = user.loggedIn; + }); + this.activityService.getReportReasons(); + this.activityService.reportReasonList.subscribe(response => { + this.reportReasons = response; + }); } voteUp(pPost: Post) { @@ -49,6 +64,10 @@ export class PostlistComponent implements OnInit { }); } + reportPost(reason: ReportReason, post: Post) { + this.feedService.reportPost(reason.id, post.id).subscribe(); + } + onLoad(post: Post) { post.mediaLoading = false; } diff --git a/src/app/components/group/group.component.html b/src/app/components/group/group.component.html index 132e5b1..5b80133 100644 --- a/src/app/components/group/group.component.html +++ b/src/app/components/group/group.component.html @@ -134,7 +134,7 @@ {{user.username}} {{user.handle}} - [admin] +
level {{level.level}} {{level.levelNumber}} level name