Merge branch 'master' into julius-dev

master
trivernis 5 years ago
commit 2126ea1652

@ -28,3 +28,20 @@ $scrollbar-thumb-color-dark: #aaa
background: $scrollbar-thumb-color background: $scrollbar-thumb-color
.dark-theme .dark-theme
background: $scrollbar-thumb-color-dark 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

@ -6,12 +6,23 @@
<div [hidden]="!loggedIn"> <div [hidden]="!loggedIn">
<mat-card> <mat-card>
<mat-card-content> <mat-card-content>
<div id="inputPreviewWrapper">
<h2 *ngIf="localFileUrl">Preview:</h2>
<img *ngIf="fileType == 'image'" id="inputPreview" [src]="localFileUrl"/>
<video *ngIf="fileType == 'video'" [src]="localFileUrl" controls="" class="html5-video-player">
Your browser does not support playing HTML5 video.
You can <a href="https://files.catbox.moe/m6gsbb.mp4" download="">download the file</a> instead.
</video>
</div>
<mat-form-field id="input"> <mat-form-field id="input">
<textarea matInput #content type="text" (input)="onTextInputChange()" [(ngModel)]="textInputValue" <textarea matInput #content type="text" (input)="onTextInputChange()" [(ngModel)]="textInputValue"
mat-autosize="true" matAutosizeMaxRows="3" placeholder="post something"></textarea> mat-autosize="true" matAutosizeMaxRows="3" placeholder="post something"></textarea>
<button mat-button matSuffix mat-icon-button> <button mat-button matSuffix mat-icon-button (click)="name.click()"
<mat-icon>add</mat-icon> matTooltip="upload a picture or video (up to 10MB)"
matTooltipShowDelay="200">
<mat-icon>attach_file</mat-icon>
</button> </button>
<input style="display: none" id="input-file" type="file" accept="video/*,image/*" (change)="onFileInputChange($event)" #name>
</mat-form-field> </mat-form-field>
<p id="check"> <p id="check">
<mat-checkbox color="primary" [(ngModel)]="checked" checked="checked">I protected the environment. <mat-checkbox color="primary" [(ngModel)]="checked" checked="checked">I protected the environment.

@ -16,6 +16,10 @@
width: 100% width: 100%
padding: 0.5em padding: 0.5em
::ng-deep .mat-option
touch-action: auto !important
#info #info
::ng-deep .mat-card-header-text ::ng-deep .mat-card-header-text
margin: 0px margin: 0px
@ -27,6 +31,26 @@
width: 100% width: 100%
padding-left: 0.5em padding-left: 0.5em
padding-right: 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 #action-chooser
width: 100% width: 100%

@ -6,6 +6,7 @@ import {DatasharingService} from '../../services/datasharing.service';
import {ActivityService} from 'src/app/services/activity/activity.service'; import {ActivityService} from 'src/app/services/activity/activity.service';
import {User} from 'src/app/models/user'; import {User} from 'src/app/models/user';
import {IErrorResponse} from '../../models/interfaces/IErrorResponse'; import {IErrorResponse} from '../../models/interfaces/IErrorResponse';
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
@Component({ @Component({
selector: 'home-feed', selector: 'home-feed',
@ -15,6 +16,12 @@ import {IErrorResponse} from '../../models/interfaces/IErrorResponse';
export class FeedComponent implements OnInit { export class FeedComponent implements OnInit {
loadingNew = true; loadingNew = true;
loadingMostLiked = true; loadingMostLiked = true;
// file upload variables
public uploading = false;
public profilePictureUrl: BehaviorSubject<string | null>;
private file;
fileType;
public localFileUrl;
checked = false; // if the "I protected the environment."-box is checked checked = false; // if the "I protected the environment."-box is checked
view = 'new'; view = 'new';
@ -27,7 +34,7 @@ export class FeedComponent implements OnInit {
loggedIn = false; loggedIn = false;
user: User; user: User;
errorOccurred: boolean; errorOccurred = false;
private errorMessage: string; 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 * Fetches the next posts when scrolled
*/ */

@ -7,19 +7,25 @@
<img class="profile-picture" [src]="groupProfile.picture"/> <img class="profile-picture" [src]="groupProfile.picture"/>
<mat-icon id="icon">camera_alt</mat-icon> <mat-icon id="icon">camera_alt</mat-icon>
</div> </div>
<div *ngIf="!isAdmin"> <div *ngIf="!isAdmin" (click)="openPfpLightbox()">
<img class="profile-picture" [src]="groupProfile.picture"/> <img class="profile-picture" [src]="groupProfile.picture"/>
</div> </div>
<span id="username">{{groupProfile.name}}</span> <span id="username">{{groupProfile.name}}</span>
<div class="button-box"> <div class="button-box">
<button mat-icon-button <button mat-icon-button *ngIf="!groupProfile.joined"
class="request-button" class="request-button"
matTooltip="join group" matTooltipShowDelay="500" matTooltip="join group" matTooltipShowDelay="500"
(click)="joinGroup(groupProfile)" (click)="joinGroup(groupProfile)"
[disabled]="!groupProfile.allowedToJoinGroup"> [disabled]="!groupProfile.allowedToJoinGroup">
<mat-icon>group_add</mat-icon> <mat-icon>group_add</mat-icon>
</button> </button>
<button mat-icon-button *ngIf="groupProfile.joined"
class="request-button"
matTooltip="leave group" matTooltipShowDelay="500"
(click)="leaveGroup(groupProfile)">
<mat-icon>directions_run</mat-icon>
</button>
<button mat-icon-button <button mat-icon-button
class="request-button" class="request-button"
matTooltip="create event" matTooltipShowDelay="500" matTooltip="create event" matTooltipShowDelay="500"
@ -27,6 +33,14 @@
[disabled]="!isAdmin"> [disabled]="!isAdmin">
<mat-icon>event</mat-icon> <mat-icon>event</mat-icon>
</button> </button>
<div style="display: contents;" *ngIf="groupProfile.deletable">
<button mat-icon-button
class="request-button"
matTooltip="delete this group" matTooltipShowDelay="0"
(click)="deleteGroup()">
<mat-icon>delete</mat-icon>
</button>
</div>
</div> </div>
</mat-toolbar-row> </mat-toolbar-row>
<mat-toolbar-row> <mat-toolbar-row>
@ -49,7 +63,7 @@
<img class="profile-picture" [src]="groupProfile.picture"/> <img class="profile-picture" [src]="groupProfile.picture"/>
<mat-icon id="icon">camera_alt</mat-icon> <mat-icon id="icon">camera_alt</mat-icon>
</div> </div>
<div *ngIf="!isAdmin"> <div *ngIf="!isAdmin" (click)="openPfpLightbox()">
<img class="profile-picture" [src]="groupProfile.picture"/> <img class="profile-picture" [src]="groupProfile.picture"/>
</div> </div>
<span id="username">{{groupProfile.name}}</span> <span id="username">{{groupProfile.name}}</span>
@ -57,13 +71,19 @@
(click)="showUserProfile(groupProfile.creator)">created by {{groupProfile.creator.username}} (click)="showUserProfile(groupProfile.creator)">created by {{groupProfile.creator.username}}
@{{groupProfile.creator.handle}}</span> @{{groupProfile.creator.handle}}</span>
<div class="button-box"> <div class="button-box">
<button mat-icon-button <button mat-icon-button *ngIf="!groupProfile.joined"
class="request-button" class="request-button"
matTooltip="join group" matTooltipShowDelay="500" matTooltip="join group" matTooltipShowDelay="500"
(click)="joinGroup(groupProfile)" (click)="joinGroup(groupProfile)"
[disabled]="!groupProfile.allowedToJoinGroup"> [disabled]="!groupProfile.allowedToJoinGroup">
<mat-icon>group_add</mat-icon> <mat-icon>group_add</mat-icon>
</button> </button>
<button mat-icon-button *ngIf="groupProfile.joined"
class="request-button"
matTooltip="leave group" matTooltipShowDelay="500"
(click)="leaveGroup(groupProfile)">
<mat-icon>directions_run</mat-icon>
</button>
<button mat-icon-button <button mat-icon-button
class="request-button" class="request-button"
matTooltip="create event" matTooltipShowDelay="500" matTooltip="create event" matTooltipShowDelay="500"
@ -71,6 +91,14 @@
[disabled]="!isAdmin"> [disabled]="!isAdmin">
<mat-icon>event</mat-icon> <mat-icon>event</mat-icon>
</button> </button>
<div style="display: contents;" *ngIf="groupProfile.deletable">
<button mat-icon-button
class="request-button"
matTooltip="delete this group" matTooltipShowDelay="0"
(click)="deleteGroup()">
<mat-icon>delete</mat-icon>
</button>
</div>
</div> </div>
</mat-toolbar-row> </mat-toolbar-row>
<mat-toolbar-row> <mat-toolbar-row>
@ -80,7 +108,7 @@
</mat-toolbar-row> </mat-toolbar-row>
</mat-toolbar> </mat-toolbar>
<div id="accordion"> <div id="accordion">
<mat-accordion> <mat-accordion multi="true">
<mat-expansion-panel *ngIf="groupProfile.events.length > 0" expanded> <mat-expansion-panel *ngIf="groupProfile.events.length > 0" expanded>
<mat-expansion-panel-header> <mat-expansion-panel-header>
<mat-panel-title> <mat-panel-title>
@ -95,14 +123,12 @@
<mat-card-title>{{event.name}}</mat-card-title> <mat-card-title>{{event.name}}</mat-card-title>
<mat-card-subtitle>{{event.date}}</mat-card-subtitle> <mat-card-subtitle>{{event.date}}</mat-card-subtitle>
<div class="button-box"> <div class="button-box">
<button mat-icon-button class="request-button" <button *ngIf="!event.joined" mat-icon-button class="request-button"
matTooltip="join event" matTooltipShowDelay="500" matTooltip="join event" matTooltipShowDelay="500"
(click)="joinEvent(event)" (click)="joinEvent(event)">
[disabled]="event.joined"> <mat-icon>event_available</mat-icon>
<mat-icon *ngIf="event.joined" color="primary">event_available</mat-icon>
<mat-icon *ngIf="!event.joined">event_available</mat-icon>
</button> </button>
<button mat-icon-button class="request-button" <button *ngIf="event.joined" mat-icon-button class="request-button"
matTooltip="leave event" matTooltipShowDelay="500" matTooltip="leave event" matTooltipShowDelay="500"
(click)="leaveEvent(event)" (click)="leaveEvent(event)"
[disabled]="!event.joined"> [disabled]="!event.joined">
@ -113,7 +139,7 @@
</mat-card> </mat-card>
</div> </div>
</mat-expansion-panel> </mat-expansion-panel>
<mat-expansion-panel [expanded]="groupProfile.events.length < 1"> <mat-expansion-panel expanded>
<mat-expansion-panel-header> <mat-expansion-panel-header>
<mat-panel-title> <mat-panel-title>
Members Members

@ -35,7 +35,8 @@ $mat-card-header-size: 100px !default
.mat-toolbar-row .mat-toolbar-row
max-height: 40px max-height: 40px
.ng-star-inserted
z-index: 99
.info-box .info-box
font-size: 14px font-size: 14px
margin-left: calc(100px + 0.5em) 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. // in IE, but we're using it as a progressive enhancement.
.profile-picture .profile-picture
cursor: pointer
height: $mat-card-header-size height: $mat-card-header-size
width: $mat-card-header-size width: $mat-card-header-size
border-radius: 50% border-radius: 50%
flex-shrink: 0 flex-shrink: 0
background-size: cover background-size: cover
transition-duration: 0.5s transition-duration: 0.5s
z-index: 10 z-index: 99
object-fit: cover object-fit: cover
.card .card

@ -9,6 +9,7 @@ import {Group} from 'src/app/models/group';
import {Event} from 'src/app/models/event'; import {Event} from 'src/app/models/event';
import {MatDialog, MatDialogRef} from '@angular/material/dialog'; import {MatDialog, MatDialogRef} from '@angular/material/dialog';
import {DialogGroupFileUploadComponent} from './fileUpload/fileUpload.component'; import {DialogGroupFileUploadComponent} from './fileUpload/fileUpload.component';
import {Lightbox} from 'ngx-lightbox';
// DIALOG COMPONENT to create events // DIALOG COMPONENT to create events
@Component({ @Component({
@ -85,6 +86,7 @@ export class GroupComponent implements OnInit {
private requestService: RequestService, private requestService: RequestService,
private data: DatasharingService, private data: DatasharingService,
private groupService: GroupService, private groupService: GroupService,
private lightbox: Lightbox,
private datasharingService: DatasharingService) { private datasharingService: DatasharingService) {
router.events.forEach((event) => { router.events.forEach((event) => {
// check if url changes // check if url changes
@ -151,9 +153,10 @@ export class GroupComponent implements OnInit {
public joinGroup(group: Group) { public joinGroup(group: Group) {
group.allowedToJoinGroup = false; group.allowedToJoinGroup = false;
this.requestService.joinGroup(group) this.requestService.joinGroup(group.id)
.subscribe(() => { .subscribe(() => {
this.datasharingService.addGroupToUser(group); this.datasharingService.addGroupToUser(group);
this.groupProfile.joined = true;
}); });
} }
@ -179,4 +182,27 @@ export class GroupComponent implements OnInit {
user.allowedToSendRequest = false; user.allowedToSendRequest = false;
this.requestService.sendFriendRequest(user); 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});
}
} }

@ -12,12 +12,18 @@
</div> </div>
<span id="username">{{userProfile.username}}</span> <span id="username">{{userProfile.username}}</span>
<button mat-icon-button <button mat-icon-button *ngIf="userProfile.allowedToSendRequest"
matTooltip="send friend request" matTooltipShowDelay="200"
class="request-button" class="request-button"
(click)="sendFriendRequest(userProfile)" (click)="sendFriendRequest(userProfile)">
[disabled]="!userProfile.allowedToSendRequest">
<mat-icon>person_add</mat-icon> <mat-icon>person_add</mat-icon>
</button> </button>
<button mat-icon-button *ngIf="isFriendOfSelf"
matTooltip="remove friend" matTooltipShowDelay="200"
class="request-button"
(click)="removeFriend(userProfile)">
<mat-icon>person_add_disabled</mat-icon>
</button>
</mat-toolbar-row> </mat-toolbar-row>
<mat-toolbar-row> <mat-toolbar-row>
<div class="info-box"> <div class="info-box">
@ -53,12 +59,18 @@
</div> </div>
<span id="username">{{userProfile.username}}</span> <span id="username">{{userProfile.username}}</span>
<span id="handle">@{{userProfile.handle}}</span> <span id="handle">@{{userProfile.handle}}</span>
<button mat-icon-button <button mat-icon-button *ngIf="userProfile.allowedToSendRequest"
matTooltip="send friend request" matTooltipShowDelay="200"
class="request-button" class="request-button"
(click)="sendFriendRequest(userProfile)" (click)="sendFriendRequest(userProfile)">
[disabled]="!userProfile.allowedToSendRequest">
<mat-icon>person_add</mat-icon> <mat-icon>person_add</mat-icon>
</button> </button>
<button mat-icon-button *ngIf="isFriendOfSelf"
matTooltip="remove friend" matTooltipShowDelay="200"
class="request-button"
(click)="removeFriend(userProfile)">
<mat-icon>person_add_disabled</mat-icon>
</button>
</mat-toolbar-row> </mat-toolbar-row>
<mat-toolbar-row> <mat-toolbar-row>
<div class="info-box"> <div class="info-box">

@ -6,6 +6,7 @@ import {RequestService} from 'src/app/services/request/request.service';
import {DatasharingService} from '../../services/datasharing.service'; import {DatasharingService} from '../../services/datasharing.service';
import {ProfileService} from 'src/app/services/profile/profile.service'; import {ProfileService} from 'src/app/services/profile/profile.service';
import {HttpClient} from '@angular/common/http'; import {HttpClient} from '@angular/common/http';
import {SocialService} from 'src/app/services/social/social.service';
import {SelfService} from '../../services/selfservice/self.service'; import {SelfService} from '../../services/selfservice/self.service';
import {MatDialog} from '@angular/material'; import {MatDialog} from '@angular/material';
import {DialogFileUploadComponent} from './fileUpload/fileUpload.component'; import {DialogFileUploadComponent} from './fileUpload/fileUpload.component';
@ -24,7 +25,7 @@ export class ProfileComponent implements OnInit {
id: string; id: string;
rankname: string; rankname: string;
profileNotFound = false; profileNotFound = false;
isFriendOfSelf = false;
loading = false; loading = false;
constructor( constructor(
@ -33,6 +34,7 @@ export class ProfileComponent implements OnInit {
private requestService: RequestService, private requestService: RequestService,
private data: DatasharingService, private data: DatasharingService,
private profileService: ProfileService, private profileService: ProfileService,
private socialService: SocialService,
private lightbox: Lightbox, private lightbox: Lightbox,
public dialog: MatDialog) { public dialog: MatDialog) {
router.events.forEach((event) => { 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.id = this.router.url.substr(this.router.url.lastIndexOf('/') + 1);
this.data.currentUser.subscribe(user => { this.data.currentUser.subscribe(user => {
this.self = user; this.self = user;
this.checkIfUserIsFriend();
}); });
this.profileService.getUserData(this.id); this.profileService.getUserData(this.id);
this.profileService.proflile.subscribe(response => { 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) { public sendFriendRequest(user: User) {
user.allowedToSendRequest = false; user.allowedToSendRequest = false;
this.requestService.sendFriendRequest(user); 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 * Opens the file upload dialog
*/ */

@ -78,7 +78,10 @@ export class SearchComponent implements OnInit {
public joinGroup(group: GroupInfo) { public joinGroup(group: GroupInfo) {
group.allowedToJoinGroup = false; group.allowedToJoinGroup = false;
this.requestService.joinGroup(group); this.requestService.joinGroup(group.id)
.subscribe(() => {
this.data.addGroupToUser(group);
});
} }
} }

@ -4,15 +4,24 @@
<div id="friendlist"> <div id="friendlist">
<mat-card class="friend-card" *ngFor="let friend of user.friends" <mat-card class="friend-card" *ngFor="let friend of user.friends"
[class.selected]="friend === selectedFriend" (click)="showFriendProfile(friend)" [class.selected]="friend === selectedFriend"
tabindex="0" tabindex="0">
matRipple>
<mat-card-header> <mat-card-header>
<div mat-card-avatar> <div id="button-box">
<button mat-icon-button [matMenuTriggerFor]="menu" id="menu-button">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="removeFriend(friend)">
<span>remove friend</span>
</button>
</mat-menu>
</div>
<div mat-card-avatar (click)="showGroupProfile(group)">
<img class="profile-picture" [src]="friend.profilePicture"/> <img class="profile-picture" [src]="friend.profilePicture"/>
</div> </div>
<mat-card-title>{{friend.name}}</mat-card-title> <mat-card-title (click)="showFriendProfile(friend)">{{friend.name}}</mat-card-title>
<mat-card-subtitle>{{friend.rankname}}</mat-card-subtitle> <mat-card-subtitle (click)="showFriendProfile(friend)">{{friend.rankname}}</mat-card-subtitle>
</mat-card-header> </mat-card-header>
</mat-card> </mat-card>
</div> </div>

@ -9,18 +9,23 @@
box-sizing: border-box box-sizing: border-box
width: 100% width: 100%
margin-top: 0.5em margin-top: 0.5em
cursor: pointer
outline: none outline: none
user-select: none user-select: none
#button-box
text-align: right
margin-left: auto
width: auto
::ng-deep .mat-card-header-text ::ng-deep .mat-card-header-text
margin: 0 24px margin: 0 24px
cursor: pointer
.mat-card-subtitle .mat-card-subtitle
margin: 0 margin: 0
$mat-card-header-size: 52px !default $mat-card-header-size: 52px !default
.profile-picture .profile-picture
cursor: pointer
height: $mat-card-header-size height: $mat-card-header-size
width: $mat-card-header-size width: $mat-card-header-size
border-radius: 50% border-radius: 50%

@ -1,5 +1,6 @@
import {Component, OnInit} from '@angular/core'; import {Component, OnInit} from '@angular/core';
import {DatasharingService} from 'src/app/services/datasharing.service'; 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 {FriendInfo} from 'src/app/models/friendinfo';
import {Router} from '@angular/router'; import {Router} from '@angular/router';
import {User} from 'src/app/models/user'; import {User} from 'src/app/models/user';
@ -12,7 +13,7 @@ import {User} from 'src/app/models/user';
export class FriendsComponent implements OnInit { export class FriendsComponent implements OnInit {
user: User; user: User;
constructor(private data: DatasharingService, private router: Router) { constructor(private data: DatasharingService, private router: Router, private socialService: SocialService) {
} }
ngOnInit() { ngOnInit() {
@ -25,4 +26,8 @@ export class FriendsComponent implements OnInit {
this.router.navigate(['profile/' + pFriend.id]); this.router.navigate(['profile/' + pFriend.id]);
} }
removeFriend(friend: FriendInfo) {
this.socialService.removeFriend(friend.id).subscribe();
}
} }

@ -10,13 +10,27 @@
<div id="grouplist"> <div id="grouplist">
<mat-card class="group-card" *ngFor="let group of user.groups" <mat-card class="group-card" *ngFor="let group of user.groups"
matRipple [class.selected]="group === selectedGroup">
[class.selected]="group === selectedGroup" (click)="showGroupProfile(group)">
<mat-card-header> <mat-card-header>
<div mat-card-avatar> <div id="button-box">
<button mat-icon-button [matMenuTriggerFor]="menu" id="menu-button">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu="matMenu">
<div *ngIf="group.deletable">
<button mat-menu-item (click)="deleteGroup(group)">
<span>delete group</span>
</button>
</div>
<button mat-menu-item (click)="leaveGroup(group)">
<span>leave group</span>
</button>
</mat-menu>
</div>
<div mat-card-avatar (click)="showGroupProfile(group)">
<img class="group-picture" [src]="group.picture"/> <img class="group-picture" [src]="group.picture"/>
</div> </div>
<mat-card-title>{{group.name}}</mat-card-title> <mat-card-title (click)="showGroupProfile(group)">{{group.name}}</mat-card-title>
</mat-card-header> </mat-card-header>
</mat-card> </mat-card>
</div> </div>

@ -11,18 +11,23 @@
margin-top: 0.5em margin-top: 0.5em
outline: none outline: none
user-select: none user-select: none
cursor: pointer #button-box
text-align: right
margin-left: auto
::ng-deep .mat-card-header-text ::ng-deep .mat-card-header-text
width: 1000% width: 1000%
margin: auto 0 auto 24px margin: auto 0 auto 24px
.mat-card-subtitle .mat-card-subtitle
cursor: pointer
margin: 0 margin: 0
word-break: break-all word-break: break-all
.mat-card-title .mat-card-title
cursor: pointer
margin: 0 margin: 0
word-break: break-all word-break: break-all
$mat-card-header-size: 52px !default $mat-card-header-size: 52px !default
.group-picture .group-picture
cursor: pointer
height: $mat-card-header-size height: $mat-card-header-size
width: $mat-card-header-size width: $mat-card-header-size
border-radius: 50% border-radius: 50%

@ -4,6 +4,7 @@ import {MatDialog, MatDialogRef} from '@angular/material/dialog';
import {SocialService} from 'src/app/services/social/social.service'; import {SocialService} from 'src/app/services/social/social.service';
import {User} from 'src/app/models/user'; import {User} from 'src/app/models/user';
import {DatasharingService} from 'src/app/services/datasharing.service'; import {DatasharingService} from 'src/app/services/datasharing.service';
import {GroupService} from 'src/app/services/group/group.service';
import {Router} from '@angular/router'; import {Router} from '@angular/router';
import {IErrorResponse} from '../../../models/interfaces/IErrorResponse'; import {IErrorResponse} from '../../../models/interfaces/IErrorResponse';
@ -50,7 +51,9 @@ export class DialogCreateGroupComponent {
export class GroupsComponent implements OnInit { export class GroupsComponent implements OnInit {
user: User; 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() { ngOnInit() {
@ -68,5 +71,13 @@ export class GroupsComponent implements OnInit {
width: '250px' width: '250px'
}); });
} }
deleteGroup(group: GroupInfo) {
this.groupService.deleteGroup(group.id).subscribe();
}
leaveGroup(group: GroupInfo) {
this.groupService.leaveGroup(group.id).subscribe();
}
} }

@ -13,6 +13,7 @@ export class Group {
events: Event[] = []; events: Event[] = [];
joined: boolean; joined: boolean;
allowedToJoinGroup = false; allowedToJoinGroup = false;
deletable: boolean;
public assignFromResponse(groupDataResponse: IGroup) { public assignFromResponse(groupDataResponse: IGroup) {
if (!groupDataResponse) { if (!groupDataResponse) {
@ -23,6 +24,7 @@ export class Group {
this.picture = this.buildPictureUrl(groupDataResponse.picture); this.picture = this.buildPictureUrl(groupDataResponse.picture);
let user = new User(); let user = new User();
this.creator = user.assignFromResponse(groupDataResponse.creator); this.creator = user.assignFromResponse(groupDataResponse.creator);
this.deletable = groupDataResponse.deletable;
if (groupDataResponse.members) { if (groupDataResponse.members) {
for (const member of groupDataResponse.members) { for (const member of groupDataResponse.members) {
user = new User(); user = new User();

@ -4,12 +4,14 @@ export class GroupInfo {
id: number; id: number;
name: string; name: string;
picture: string; picture: string;
deletable: boolean;
allowedToJoinGroup = false; allowedToJoinGroup = false;
constructor(pId: number, pName: string, picture: string) { constructor(pId: number, pName: string, picture: string, deletable: boolean) {
this.id = pId; this.id = pId;
this.name = pName; this.name = pName;
this.picture = this.buildPictureUrl(picture); this.picture = this.buildPictureUrl(picture);
this.deletable = deletable;
} }
buildPictureUrl(path: string): string { buildPictureUrl(path: string): string {

@ -19,4 +19,6 @@ export interface IGroup {
events: any; events: any;
joined: boolean; joined: boolean;
deletable: boolean;
} }

@ -62,7 +62,7 @@ export class User {
this.groups.push(group_.assignFromResponse(group)); this.groups.push(group_.assignFromResponse(group));
} doesnt work because of circular injection*/ } doesnt work because of circular injection*/
this.groups = userDataResponse.groups 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) { if (userDataResponse.chats) {
this.chatIDs = userDataResponse.chats.map(chat => chat.id); this.chatIDs = userDataResponse.chats.map(chat => chat.id);

@ -21,6 +21,17 @@ export class DatasharingService {
this.currentUser.next(user); 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) { addGroupToUser(group: GroupInfo) {
const user = this.currentUser.getValue(); const user = this.currentUser.getValue();
user.groups.push(group); user.groups.push(group);
@ -33,7 +44,18 @@ export class DatasharingService {
user.friends.push(friend); user.friends.push(friend);
user.friendCount++; user.friendCount++;
this.currentUser.next(user); 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) { setDarkMode(active: boolean) {
const user: User = this.currentUser.getValue(); const user: User = this.currentUser.getValue();

@ -8,6 +8,7 @@ import {Group} from 'src/app/models/group';
import {tap} from 'rxjs/operators'; import {tap} from 'rxjs/operators';
import {BaseService} from '../base.service'; import {BaseService} from '../base.service';
import {IFileUploadResult} from '../../models/interfaces/IFileUploadResult'; import {IFileUploadResult} from '../../models/interfaces/IFileUploadResult';
import {DatasharingService} from 'src/app/services/datasharing.service';
const getGroupGraphqlQuery = `query($groupId: ID!) { const getGroupGraphqlQuery = `query($groupId: ID!) {
getGroup(groupId:$groupId){ getGroup(groupId:$groupId){
@ -15,6 +16,7 @@ const getGroupGraphqlQuery = `query($groupId: ID!) {
name name
joined joined
picture picture
deletable
creator{id name handle} creator{id name handle}
admins{id name handle} admins{id name handle}
members{id name handle profilePicture} members{id name handle profilePicture}
@ -29,7 +31,7 @@ export class GroupService extends BaseService {
public group: BehaviorSubject<Group> = new BehaviorSubject(new Group()); public group: BehaviorSubject<Group> = new BehaviorSubject(new Group());
constructor(http: HttpClient) { constructor(http: HttpClient, private data: DatasharingService) {
super(http); super(http);
} }
@ -115,4 +117,32 @@ export class GroupService extends BaseService {
formData.append('groupId', id); formData.append('groupId', id);
return this.post<IFileUploadResult>(environment.greenvironmentUrl + '/upload', formData); return this.post<IFileUploadResult>(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);
}));
}
} }

@ -34,7 +34,8 @@ const graphqlQuery = `mutation($email: String!, $pwHash: String!) {
groups { groups {
id, id,
name, name,
picture picture,
deletable
}, },
chats{ chats{
id id

@ -51,7 +51,7 @@ export class RequestService extends BaseService {
private static buildJoinGroupBody(id: number): any { private static buildJoinGroupBody(id: number): any {
return { return {
query: `mutation($id: ID!) { query: `mutation($id: ID!) {
joinGroup(id: $id) { joinGroup(groupId: $id) {
id id
} }
}` }`
@ -126,8 +126,8 @@ export class RequestService extends BaseService {
* Joins a group * Joins a group
* @param group * @param group
*/ */
public joinGroup(group: GroupInfo) { public joinGroup(groupId: number) {
return this.postGraphql(RequestService.buildJoinGroupBody(group.id)); return this.postGraphql(RequestService.buildJoinGroupBody(groupId));
} }
/** /**

@ -32,6 +32,7 @@ const graphqlQuery = `query($query: String!, $first: Int, $offset: Int) {
id id
name name
picture picture
deletable
creator{id name handle} creator{id name handle}
members{id name handle} members{id name handle}
} }
@ -91,7 +92,7 @@ export class SearchService extends BaseService {
public getGroupsForResponse(response: ISearchRequestResult): Array<GroupInfo> { public getGroupsForResponse(response: ISearchRequestResult): Array<GroupInfo> {
const groups = new Array<GroupInfo>(); const groups = new Array<GroupInfo>();
for (const group of response.data.search.groups) { 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; return groups;
} }

@ -27,7 +27,8 @@ const getSelfGraphqlQuery = `{
groups { groups {
id, id,
name, name,
picture picture,
deletable
}, },
chats{ chats{
id id

@ -2,6 +2,8 @@ import {Injectable} from '@angular/core';
import {environment} from 'src/environments/environment'; import {environment} from 'src/environments/environment';
import {HttpClient} from '@angular/common/http'; import {HttpClient} from '@angular/common/http';
import {BaseService} from '../base.service'; 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!) { const graphqlCreateGroupQuery = `mutation($name: String!) {
createGroup(name: $name) { createGroup(name: $name) {
@ -14,11 +16,12 @@ const graphqlCreateGroupQuery = `mutation($name: String!) {
}) })
export class SocialService extends BaseService { export class SocialService extends BaseService {
constructor(http: HttpClient) { constructor(http: HttpClient,
private data: DatasharingService) {
super(http); super(http);
} }
/** /**
* Builds the body for a group creation request * Builds the body for a group creation request
* @param name * @param name
*/ */
@ -38,4 +41,18 @@ export class SocialService extends BaseService {
const body = SocialService.buildGroupCreateBody(name); const body = SocialService.buildGroupCreateBody(name);
return this.postGraphql(body, null, 0); 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);
}));
}
} }

Loading…
Cancel
Save