diff --git a/src/app/app.component.sass b/src/app/app.component.sass index e977ea0..eb5a516 100644 --- a/src/app/app.component.sass +++ b/src/app/app.component.sass @@ -28,3 +28,20 @@ $scrollbar-thumb-color-dark: #aaa background: $scrollbar-thumb-color .dark-theme background: $scrollbar-thumb-color-dark + + + +::ng-deep .lb-dataContainer + display: none + +::ng-deep .lightbox .lb-image + border: none + +::ng-deep .lb-outerContainer + background-color: transparent + +::ng-deep .lb-outerContainer + // height: 100vh !important + display: flex + justify-content: center + align-items: center diff --git a/src/app/components/feed/feed.component.html b/src/app/components/feed/feed.component.html index 3f7bb97..47b1ed2 100644 --- a/src/app/components/feed/feed.component.html +++ b/src/app/components/feed/feed.component.html @@ -6,12 +6,23 @@
+
+

Preview:

+ + +
- +

I protected the environment. diff --git a/src/app/components/feed/feed.component.sass b/src/app/components/feed/feed.component.sass index 40e1094..5f16e08 100644 --- a/src/app/components/feed/feed.component.sass +++ b/src/app/components/feed/feed.component.sass @@ -16,6 +16,10 @@ width: 100% padding: 0.5em + +::ng-deep .mat-option + touch-action: auto !important + #info ::ng-deep .mat-card-header-text margin: 0px @@ -27,6 +31,26 @@ width: 100% padding-left: 0.5em padding-right: 0.5em + .mat-icon + transform: scale(1.5) +#inputPreview + max-width: 75% + max-height: 100% + width: auto + border-radius: 4px + mask-mode: luminance + outline: none + user-select: none +::ng-deep video + width: 100% + max-height: 40vh + outline: none + user-select: none +#inputPreviewWrapper + margin: auto + text-align: center + max-height: 512px + margin-bottom: 1em #action-chooser width: 100% diff --git a/src/app/components/feed/feed.component.ts b/src/app/components/feed/feed.component.ts index d7d85b8..a99eea9 100644 --- a/src/app/components/feed/feed.component.ts +++ b/src/app/components/feed/feed.component.ts @@ -6,6 +6,7 @@ import {DatasharingService} from '../../services/datasharing.service'; import {ActivityService} from 'src/app/services/activity/activity.service'; import {User} from 'src/app/models/user'; import {IErrorResponse} from '../../models/interfaces/IErrorResponse'; +import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; @Component({ selector: 'home-feed', @@ -15,6 +16,12 @@ import {IErrorResponse} from '../../models/interfaces/IErrorResponse'; export class FeedComponent implements OnInit { loadingNew = true; loadingMostLiked = true; + // file upload variables + public uploading = false; + public profilePictureUrl: BehaviorSubject; + private file; + fileType; + public localFileUrl; checked = false; // if the "I protected the environment."-box is checked view = 'new'; @@ -27,7 +34,7 @@ export class FeedComponent implements OnInit { loggedIn = false; user: User; - errorOccurred: boolean; + errorOccurred = false; private errorMessage: string; @@ -89,6 +96,22 @@ export class FeedComponent implements OnInit { } } + onFileInputChange(event) { + this.errorOccurred = false; + this.errorMessage = ''; + this.file = event.target.files[0]; + if (this.file.type.includes('video')) { + this.fileType = 'video'; + } else if (this.file.type.includes('image')) { + this.fileType = 'image'; + } + const reader = new FileReader(); + reader.onload = (e: any) => { + this.localFileUrl = e.target.result; + }; + reader.readAsDataURL(this.file); + } + /** * Fetches the next posts when scrolled */ diff --git a/src/app/components/group/group.component.html b/src/app/components/group/group.component.html index 70f9ff0..652f47b 100644 --- a/src/app/components/group/group.component.html +++ b/src/app/components/group/group.component.html @@ -7,19 +7,25 @@ camera_alt

-
+
{{groupProfile.name}}
- + +
+ +
@@ -49,7 +63,7 @@ camera_alt
-
+
{{groupProfile.name}} @@ -57,13 +71,19 @@ (click)="showUserProfile(groupProfile.creator)">created by {{groupProfile.creator.username}} @{{groupProfile.creator.handle}}
- + +
+ +
@@ -80,7 +108,7 @@
- + @@ -95,14 +123,12 @@ {{event.name}} {{event.date}}
- -
- + Members diff --git a/src/app/components/group/group.component.sass b/src/app/components/group/group.component.sass index 65d8b8e..6312e7b 100644 --- a/src/app/components/group/group.component.sass +++ b/src/app/components/group/group.component.sass @@ -35,7 +35,8 @@ $mat-card-header-size: 100px !default .mat-toolbar-row max-height: 40px - + .ng-star-inserted + z-index: 99 .info-box font-size: 14px margin-left: calc(100px + 0.5em) @@ -73,13 +74,14 @@ $mat-card-header-size: 100px !default // in IE, but we're using it as a progressive enhancement. .profile-picture + cursor: pointer height: $mat-card-header-size width: $mat-card-header-size border-radius: 50% flex-shrink: 0 background-size: cover transition-duration: 0.5s - z-index: 10 + z-index: 99 object-fit: cover .card diff --git a/src/app/components/group/group.component.ts b/src/app/components/group/group.component.ts index a8cc934..014483b 100644 --- a/src/app/components/group/group.component.ts +++ b/src/app/components/group/group.component.ts @@ -9,6 +9,7 @@ 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({ @@ -85,6 +86,7 @@ export class GroupComponent implements OnInit { private requestService: RequestService, private data: DatasharingService, private groupService: GroupService, + private lightbox: Lightbox, private datasharingService: DatasharingService) { router.events.forEach((event) => { // check if url changes @@ -151,9 +153,10 @@ export class GroupComponent implements OnInit { public joinGroup(group: Group) { group.allowedToJoinGroup = false; - this.requestService.joinGroup(group) + this.requestService.joinGroup(group.id) .subscribe(() => { this.datasharingService.addGroupToUser(group); + this.groupProfile.joined = true; }); } @@ -179,4 +182,27 @@ export class GroupComponent implements OnInit { user.allowedToSendRequest = false; this.requestService.sendFriendRequest(user); } + + private deleteGroup() { + this.groupService.deleteGroup(this.groupProfile.id) + .subscribe(response => { + this.router.navigateByUrl(''); + }); + } + + leaveGroup() { + this.groupService.leaveGroup(this.groupProfile.id).subscribe(response => { + this.groupProfile.joined = false; + // tslint:disable-next-line:max-line-length + this.groupProfile.allowedToJoinGroup = this.requestService.isAllowedToJoinGroup(this.groupProfile.id, this.self); + }); + } + + openPfpLightbox() { + this.lightbox.open([{ + src: this.groupProfile.picture, + thumb: this.groupProfile.picture, + }], 0, {disableScrolling: true}); + } + } diff --git a/src/app/components/profile/profile.component.html b/src/app/components/profile/profile.component.html index e427abc..a65585b 100644 --- a/src/app/components/profile/profile.component.html +++ b/src/app/components/profile/profile.component.html @@ -12,12 +12,18 @@
{{userProfile.username}} - +
@@ -53,12 +59,18 @@
{{userProfile.username}} @{{userProfile.handle}} - +
diff --git a/src/app/components/profile/profile.component.ts b/src/app/components/profile/profile.component.ts index 815ba80..81bb20b 100644 --- a/src/app/components/profile/profile.component.ts +++ b/src/app/components/profile/profile.component.ts @@ -6,6 +6,7 @@ import {RequestService} from 'src/app/services/request/request.service'; import {DatasharingService} from '../../services/datasharing.service'; import {ProfileService} from 'src/app/services/profile/profile.service'; import {HttpClient} from '@angular/common/http'; +import {SocialService} from 'src/app/services/social/social.service'; import {SelfService} from '../../services/selfservice/self.service'; import {MatDialog} from '@angular/material'; import {DialogFileUploadComponent} from './fileUpload/fileUpload.component'; @@ -24,7 +25,7 @@ export class ProfileComponent implements OnInit { id: string; rankname: string; profileNotFound = false; - + isFriendOfSelf = false; loading = false; constructor( @@ -33,6 +34,7 @@ export class ProfileComponent implements OnInit { private requestService: RequestService, private data: DatasharingService, private profileService: ProfileService, + private socialService: SocialService, private lightbox: Lightbox, public dialog: MatDialog) { router.events.forEach((event) => { @@ -52,6 +54,7 @@ export class ProfileComponent implements OnInit { this.id = this.router.url.substr(this.router.url.lastIndexOf('/') + 1); this.data.currentUser.subscribe(user => { this.self = user; + this.checkIfUserIsFriend(); }); this.profileService.getUserData(this.id); this.profileService.proflile.subscribe(response => { @@ -68,11 +71,29 @@ export class ProfileComponent implements OnInit { }); } + checkIfUserIsFriend() { + this.isFriendOfSelf = false; + for (const friend of this.self.friends) { + if (friend.id.toString() === this.id) { + this.isFriendOfSelf = true; + break; + } + } + } + public sendFriendRequest(user: User) { user.allowedToSendRequest = false; this.requestService.sendFriendRequest(user); } + removeFriend(user: User) { + this.socialService.removeFriend(user.userID).subscribe(response => { + this.checkIfUserIsFriend(); + // tslint:disable-next-line:max-line-length + this.userProfile.allowedToSendRequest = this.requestService.isAllowedToSendRequest(this.userProfile.userID, this.self); + }); + } + /** * Opens the file upload dialog */ diff --git a/src/app/components/search/search.component.ts b/src/app/components/search/search.component.ts index 9dd92f8..461126b 100644 --- a/src/app/components/search/search.component.ts +++ b/src/app/components/search/search.component.ts @@ -78,7 +78,10 @@ export class SearchComponent implements OnInit { public joinGroup(group: GroupInfo) { group.allowedToJoinGroup = false; - this.requestService.joinGroup(group); + this.requestService.joinGroup(group.id) + .subscribe(() => { + this.data.addGroupToUser(group); + }); } } diff --git a/src/app/components/social/friends/friends.component.html b/src/app/components/social/friends/friends.component.html index 6347cc4..c036f75 100644 --- a/src/app/components/social/friends/friends.component.html +++ b/src/app/components/social/friends/friends.component.html @@ -4,15 +4,24 @@
+ [class.selected]="friend === selectedFriend" + tabindex="0"> -
+
+ + + + +
+
- {{friend.name}} - {{friend.rankname}} + {{friend.name}} + {{friend.rankname}}
diff --git a/src/app/components/social/friends/friends.component.sass b/src/app/components/social/friends/friends.component.sass index 253ee4a..db4f286 100644 --- a/src/app/components/social/friends/friends.component.sass +++ b/src/app/components/social/friends/friends.component.sass @@ -9,18 +9,23 @@ box-sizing: border-box width: 100% margin-top: 0.5em - cursor: pointer outline: none user-select: none + #button-box + text-align: right + margin-left: auto + width: auto ::ng-deep .mat-card-header-text margin: 0 24px + cursor: pointer .mat-card-subtitle margin: 0 $mat-card-header-size: 52px !default .profile-picture + cursor: pointer height: $mat-card-header-size width: $mat-card-header-size border-radius: 50% diff --git a/src/app/components/social/friends/friends.component.ts b/src/app/components/social/friends/friends.component.ts index 4cd3840..0420c82 100644 --- a/src/app/components/social/friends/friends.component.ts +++ b/src/app/components/social/friends/friends.component.ts @@ -1,5 +1,6 @@ import {Component, OnInit} from '@angular/core'; import {DatasharingService} from 'src/app/services/datasharing.service'; +import {SocialService} from 'src/app/services/social/social.service'; import {FriendInfo} from 'src/app/models/friendinfo'; import {Router} from '@angular/router'; import {User} from 'src/app/models/user'; @@ -12,7 +13,7 @@ import {User} from 'src/app/models/user'; export class FriendsComponent implements OnInit { user: User; - constructor(private data: DatasharingService, private router: Router) { + constructor(private data: DatasharingService, private router: Router, private socialService: SocialService) { } ngOnInit() { @@ -25,4 +26,8 @@ export class FriendsComponent implements OnInit { this.router.navigate(['profile/' + pFriend.id]); } + removeFriend(friend: FriendInfo) { + this.socialService.removeFriend(friend.id).subscribe(); + } + } diff --git a/src/app/components/social/groups/groups.component.html b/src/app/components/social/groups/groups.component.html index aa85510..7781231 100644 --- a/src/app/components/social/groups/groups.component.html +++ b/src/app/components/social/groups/groups.component.html @@ -10,13 +10,27 @@
+ [class.selected]="group === selectedGroup"> -
+
+ + +
+ +
+ +
+
+
- {{group.name}} + {{group.name}}
diff --git a/src/app/components/social/groups/groups.component.sass b/src/app/components/social/groups/groups.component.sass index 3e12dce..a868fe5 100644 --- a/src/app/components/social/groups/groups.component.sass +++ b/src/app/components/social/groups/groups.component.sass @@ -11,18 +11,23 @@ margin-top: 0.5em outline: none user-select: none - cursor: pointer + #button-box + text-align: right + margin-left: auto ::ng-deep .mat-card-header-text width: 1000% margin: auto 0 auto 24px .mat-card-subtitle + cursor: pointer margin: 0 word-break: break-all .mat-card-title + cursor: pointer margin: 0 word-break: break-all $mat-card-header-size: 52px !default .group-picture + cursor: pointer height: $mat-card-header-size width: $mat-card-header-size border-radius: 50% diff --git a/src/app/components/social/groups/groups.component.ts b/src/app/components/social/groups/groups.component.ts index 6097462..bcb87cf 100644 --- a/src/app/components/social/groups/groups.component.ts +++ b/src/app/components/social/groups/groups.component.ts @@ -4,6 +4,7 @@ import {MatDialog, MatDialogRef} from '@angular/material/dialog'; import {SocialService} from 'src/app/services/social/social.service'; import {User} from 'src/app/models/user'; import {DatasharingService} from 'src/app/services/datasharing.service'; +import {GroupService} from 'src/app/services/group/group.service'; import {Router} from '@angular/router'; import {IErrorResponse} from '../../../models/interfaces/IErrorResponse'; @@ -50,7 +51,9 @@ export class DialogCreateGroupComponent { export class GroupsComponent implements OnInit { user: User; - constructor(public dialog: MatDialog, private data: DatasharingService, private router: Router) { + constructor(public dialog: MatDialog, private data: DatasharingService, + private router: Router, + private groupService: GroupService) { } ngOnInit() { @@ -68,5 +71,13 @@ export class GroupsComponent implements OnInit { width: '250px' }); } + + deleteGroup(group: GroupInfo) { + this.groupService.deleteGroup(group.id).subscribe(); + } + + leaveGroup(group: GroupInfo) { + this.groupService.leaveGroup(group.id).subscribe(); + } } diff --git a/src/app/models/group.ts b/src/app/models/group.ts index eb0da3d..51be07f 100644 --- a/src/app/models/group.ts +++ b/src/app/models/group.ts @@ -13,6 +13,7 @@ export class Group { events: Event[] = []; joined: boolean; allowedToJoinGroup = false; + deletable: boolean; public assignFromResponse(groupDataResponse: IGroup) { if (!groupDataResponse) { @@ -23,6 +24,7 @@ export class Group { this.picture = this.buildPictureUrl(groupDataResponse.picture); let user = new User(); this.creator = user.assignFromResponse(groupDataResponse.creator); + this.deletable = groupDataResponse.deletable; if (groupDataResponse.members) { for (const member of groupDataResponse.members) { user = new User(); diff --git a/src/app/models/groupinfo.ts b/src/app/models/groupinfo.ts index e9399eb..9db5965 100644 --- a/src/app/models/groupinfo.ts +++ b/src/app/models/groupinfo.ts @@ -4,12 +4,14 @@ export class GroupInfo { id: number; name: string; picture: string; + deletable: boolean; allowedToJoinGroup = false; - constructor(pId: number, pName: string, picture: string) { + constructor(pId: number, pName: string, picture: string, deletable: boolean) { this.id = pId; this.name = pName; this.picture = this.buildPictureUrl(picture); + this.deletable = deletable; } buildPictureUrl(path: string): string { diff --git a/src/app/models/interfaces/IGroup.ts b/src/app/models/interfaces/IGroup.ts index 357a5d6..f6b82e0 100644 --- a/src/app/models/interfaces/IGroup.ts +++ b/src/app/models/interfaces/IGroup.ts @@ -19,4 +19,6 @@ export interface IGroup { events: any; joined: boolean; + + deletable: boolean; } diff --git a/src/app/models/user.ts b/src/app/models/user.ts index 05cf220..528e7ce 100644 --- a/src/app/models/user.ts +++ b/src/app/models/user.ts @@ -62,7 +62,7 @@ export class User { this.groups.push(group_.assignFromResponse(group)); } doesnt work because of circular injection*/ this.groups = userDataResponse.groups - .map(group => new GroupInfo(group.id, group.name, group.picture)); + .map(group => new GroupInfo(group.id, group.name, group.picture, group.deletable)); } if (userDataResponse.chats) { this.chatIDs = userDataResponse.chats.map(chat => chat.id); diff --git a/src/app/services/datasharing.service.ts b/src/app/services/datasharing.service.ts index 9f21f30..67241db 100644 --- a/src/app/services/datasharing.service.ts +++ b/src/app/services/datasharing.service.ts @@ -21,6 +21,17 @@ export class DatasharingService { this.currentUser.next(user); } + deleteGroup(id: number) { + const user: User = this.currentUser.getValue(); + for (let i = 0; i < user.groups.length; i++) { + if (user.groups[i].id === id) { + user.groups.splice(i, 1); + return; + } + } + this.currentUser.next(user); + } + addGroupToUser(group: GroupInfo) { const user = this.currentUser.getValue(); user.groups.push(group); @@ -33,7 +44,18 @@ export class DatasharingService { user.friends.push(friend); user.friendCount++; this.currentUser.next(user); -} + } + + removeFriendFromUser(id: number) { + const user: User = this.currentUser.getValue(); + for (let i = 0; i < user.friends.length; i++) { + if (user.friends[i].id === id) { + user.friends.splice(i, 1); + return; + } + } + this.currentUser.next(user); + } setDarkMode(active: boolean) { const user: User = this.currentUser.getValue(); diff --git a/src/app/services/group/group.service.ts b/src/app/services/group/group.service.ts index 2af61ac..48beabd 100644 --- a/src/app/services/group/group.service.ts +++ b/src/app/services/group/group.service.ts @@ -8,6 +8,7 @@ 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){ @@ -15,6 +16,7 @@ const getGroupGraphqlQuery = `query($groupId: ID!) { name joined picture + deletable creator{id name handle} admins{id name handle} members{id name handle profilePicture} @@ -29,7 +31,7 @@ export class GroupService extends BaseService { public group: BehaviorSubject = new BehaviorSubject(new Group()); - constructor(http: HttpClient) { + constructor(http: HttpClient, private data: DatasharingService) { super(http); } @@ -115,4 +117,32 @@ export class GroupService extends BaseService { formData.append('groupId', id); return this.post(environment.greenvironmentUrl + '/upload', formData); } + + public deleteGroup(groupId: number) { + const body = { + query: `mutation($groupId: ID!) { + deleteGroup(groupId: $groupId) + }`, variables: { + groupId + } + }; + return this.postGraphql(body) + .pipe(tap(response => { + this.data.deleteGroup(groupId); + })); + } + + public leaveGroup(groupId: number) { + const body = { + query: `mutation($groupId: ID!) { + leaveGroup(groupId: $groupId){ id } + }`, variables: { + groupId + } + }; + return this.postGraphql(body) + .pipe(tap(response => { + this.data.deleteGroup(groupId); + })); + } } diff --git a/src/app/services/login/login.service.ts b/src/app/services/login/login.service.ts index 5cfc9c8..ed1884e 100644 --- a/src/app/services/login/login.service.ts +++ b/src/app/services/login/login.service.ts @@ -34,7 +34,8 @@ const graphqlQuery = `mutation($email: String!, $pwHash: String!) { groups { id, name, - picture + picture, + deletable }, chats{ id diff --git a/src/app/services/request/request.service.ts b/src/app/services/request/request.service.ts index bb949da..b1a0d67 100644 --- a/src/app/services/request/request.service.ts +++ b/src/app/services/request/request.service.ts @@ -51,7 +51,7 @@ export class RequestService extends BaseService { private static buildJoinGroupBody(id: number): any { return { query: `mutation($id: ID!) { - joinGroup(id: $id) { + joinGroup(groupId: $id) { id } }` @@ -126,8 +126,8 @@ export class RequestService extends BaseService { * Joins a group * @param group */ - public joinGroup(group: GroupInfo) { - return this.postGraphql(RequestService.buildJoinGroupBody(group.id)); + public joinGroup(groupId: number) { + return this.postGraphql(RequestService.buildJoinGroupBody(groupId)); } /** diff --git a/src/app/services/search/search.service.ts b/src/app/services/search/search.service.ts index 417cf9a..690dadb 100644 --- a/src/app/services/search/search.service.ts +++ b/src/app/services/search/search.service.ts @@ -32,6 +32,7 @@ const graphqlQuery = `query($query: String!, $first: Int, $offset: Int) { id name picture + deletable creator{id name handle} members{id name handle} } @@ -91,7 +92,7 @@ export class SearchService extends BaseService { public getGroupsForResponse(response: ISearchRequestResult): Array { const groups = new Array(); for (const group of response.data.search.groups) { - groups.push(new GroupInfo(group.id, group.name, group.picture)); + groups.push(new GroupInfo(group.id, group.name, group.picture, group.deletable)); } return groups; } diff --git a/src/app/services/selfservice/self.service.ts b/src/app/services/selfservice/self.service.ts index f89c25b..7c22071 100644 --- a/src/app/services/selfservice/self.service.ts +++ b/src/app/services/selfservice/self.service.ts @@ -27,7 +27,8 @@ const getSelfGraphqlQuery = `{ groups { id, name, - picture + picture, + deletable }, chats{ id diff --git a/src/app/services/social/social.service.ts b/src/app/services/social/social.service.ts index 77fe81f..7fda50a 100644 --- a/src/app/services/social/social.service.ts +++ b/src/app/services/social/social.service.ts @@ -2,6 +2,8 @@ import {Injectable} from '@angular/core'; import {environment} from 'src/environments/environment'; import {HttpClient} from '@angular/common/http'; import {BaseService} from '../base.service'; +import { tap } from 'rxjs/internal/operators/tap'; +import {DatasharingService} from 'src/app/services/datasharing.service'; const graphqlCreateGroupQuery = `mutation($name: String!) { createGroup(name: $name) { @@ -14,11 +16,12 @@ const graphqlCreateGroupQuery = `mutation($name: String!) { }) export class SocialService extends BaseService { - constructor(http: HttpClient) { + constructor(http: HttpClient, + private data: DatasharingService) { super(http); } - /** + /** * Builds the body for a group creation request * @param name */ @@ -38,4 +41,18 @@ export class SocialService extends BaseService { const body = SocialService.buildGroupCreateBody(name); return this.postGraphql(body, null, 0); } + + public removeFriend(id: number) { + const body = { + query: `mutation($id: ID!) { + removeFriend(friendId: $id) + }`, variables: { + id + } + }; + return this.postGraphql(body) + .pipe(tap(response => { + this.data.removeFriendFromUser(id); + })); + } }