Merge branch 'master' into julius-dev
commit
dea36c122d
File diff suppressed because it is too large
Load Diff
@ -1,23 +0,0 @@
|
|||||||
<h1>Greenvironment</h1>
|
|
||||||
<button id="tab-home" routerLink="">Home</button>
|
|
||||||
<button id="tab-profile" routerLink={{profileUrl}} *ngIf="loggedIn">Profile</button>
|
|
||||||
<button id="tab-about" routerLink="/about">About</button>
|
|
||||||
<button id="tab-imprint" routerLink="/imprint">Imprint</button>
|
|
||||||
<button id="tab-login" routerLink="/login" *ngIf="loggedIn != true">Login</button>
|
|
||||||
<div id="dropdown" *ngIf="loggedIn">
|
|
||||||
<div>
|
|
||||||
<span id="symbol" (click)="showDropdown()"><i class="fa fa-caret-down" aria-hidden="true"></i></span>
|
|
||||||
<span>{{username}}</span>
|
|
||||||
</div>
|
|
||||||
<div id="dropdown-content" *ngIf="dropdownShown">
|
|
||||||
<div>
|
|
||||||
<span>Rang:</span>
|
|
||||||
<span>{{level}}</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>Punkte:</span>
|
|
||||||
<span>{{points}}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button id="logoutbutton" *ngIf="loggedIn" (click)="logout()"><span><i class="fa fa-sign-out-alt fa-2x" aria-hidden="true"></i></span></button>
|
|
@ -1,63 +0,0 @@
|
|||||||
@import '../../../styles/mixins.sass'
|
|
||||||
@import '../../../styles/vars.sass'
|
|
||||||
|
|
||||||
button
|
|
||||||
border: 2px solid $cHeadPrimaryBackground
|
|
||||||
margin-top: 0.125em
|
|
||||||
padding: 0.125em
|
|
||||||
background-color: $cHeadPrimaryBackground
|
|
||||||
color: $cHeadFontColor
|
|
||||||
font-weight: bold
|
|
||||||
transition-duration: 0.25s
|
|
||||||
|
|
||||||
button:hover
|
|
||||||
background-color: lighten($cHeadPrimaryBackground, 10%)
|
|
||||||
cursor: pointer
|
|
||||||
|
|
||||||
button:active
|
|
||||||
background-color: darken($cHeadPrimaryBackground, 5%)
|
|
||||||
box-shadow: inset 0.25em 0.25em 0.1em rgba(0, 0, 0, 0.25)
|
|
||||||
|
|
||||||
h1
|
|
||||||
@include gridPosition(1, 2, 1, 2)
|
|
||||||
line-height: 100%
|
|
||||||
margin-left: 0.5em
|
|
||||||
margin-top: 0.25em
|
|
||||||
|
|
||||||
#tab-home
|
|
||||||
@include gridPosition(1, 2, 2, 3)
|
|
||||||
|
|
||||||
#tab-profile
|
|
||||||
@include gridPosition(1, 2, 3, 4)
|
|
||||||
|
|
||||||
#tab-about
|
|
||||||
@include gridPosition(1, 2, 4, 5)
|
|
||||||
|
|
||||||
#tab-imprint
|
|
||||||
@include gridPosition(1, 2, 5, 6)
|
|
||||||
|
|
||||||
#tab-login
|
|
||||||
@include gridPosition(1, 2, 6, 7)
|
|
||||||
|
|
||||||
#dropdown
|
|
||||||
@include gridPosition(1, 2, 7, 8)
|
|
||||||
display: flex
|
|
||||||
align-items: center
|
|
||||||
margin-left: 2em
|
|
||||||
span
|
|
||||||
margin-left: 1em
|
|
||||||
#symbol
|
|
||||||
span:hover
|
|
||||||
background-color: lighten($cHeadPrimaryBackground, 10%)
|
|
||||||
cursor: pointer
|
|
||||||
#dropdown-content
|
|
||||||
position: absolute
|
|
||||||
background-color: $cHeadPrimaryBackground
|
|
||||||
min-width: 160px
|
|
||||||
margin-top: 7vh
|
|
||||||
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2)
|
|
||||||
padding: 12px 16px
|
|
||||||
z-index: 1
|
|
||||||
|
|
||||||
#logoutbutton
|
|
||||||
@include gridPosition(1, 2, 8, 9)
|
|
@ -1,74 +0,0 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
|
||||||
import { LoginComponent } from '../login/login.component';
|
|
||||||
import { DatasharingService } from '../../services/datasharing.service';
|
|
||||||
import { SelfService } from '../../services/selfservice/self.service';
|
|
||||||
import { Levellist } from 'src/app/models/levellist';
|
|
||||||
import { Http } from '@angular/http';
|
|
||||||
import { Router } from '@angular/router';
|
|
||||||
import { User } from 'src/app/models/user';
|
|
||||||
import { environment } from 'src/environments/environment';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-scaffold',
|
|
||||||
templateUrl: './app-scaffold.component.html',
|
|
||||||
styleUrls: ['./app-scaffold.component.sass']
|
|
||||||
})
|
|
||||||
|
|
||||||
export class AppScaffoldComponent implements OnInit {
|
|
||||||
loggedIn = false;
|
|
||||||
userId: number;
|
|
||||||
username: string;
|
|
||||||
user: User;
|
|
||||||
levellist: Levellist = new Levellist();
|
|
||||||
level: string;
|
|
||||||
points: number;
|
|
||||||
profileUrl: string;
|
|
||||||
|
|
||||||
dropdownShown = false;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private data: DatasharingService,
|
|
||||||
private selfservice: SelfService,
|
|
||||||
private http: Http,
|
|
||||||
private router: Router) { }
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.data.currentUserInfo.subscribe(user => {
|
|
||||||
this.user = user;
|
|
||||||
this.loggedIn = user.loggedIn;
|
|
||||||
this.userId = user.userID;
|
|
||||||
this.username = user.username;
|
|
||||||
this.level = this.levellist.getLevelName(user.level);
|
|
||||||
this.points = user.points;
|
|
||||||
this.profileUrl = '/profile/' + this.userId;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
showDropdown() {
|
|
||||||
if (!this.dropdownShown) {
|
|
||||||
this.dropdownShown = true;
|
|
||||||
} else {
|
|
||||||
this.dropdownShown = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logout() {
|
|
||||||
const url = environment.graphQLUrl;
|
|
||||||
|
|
||||||
const headers = new Headers();
|
|
||||||
headers.set('Content-Type', 'application/json');
|
|
||||||
|
|
||||||
const body = {query: `mutation {
|
|
||||||
logout
|
|
||||||
}`};
|
|
||||||
|
|
||||||
this.http.post(url, body).subscribe(response => {
|
|
||||||
console.log(response.text()); });
|
|
||||||
this.loggedIn = false;
|
|
||||||
const user = new User();
|
|
||||||
user.loggedIn = false;
|
|
||||||
this.data.changeUserInfo(user);
|
|
||||||
this.router.navigate(['login']);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
@import '../../../styles/mixins.sass'
|
|
||||||
@import '../../../styles/vars.sass'
|
|
||||||
|
|
||||||
#chat
|
|
||||||
display: grid
|
|
||||||
grid-template: 7.5% 82.5% 10%/100%
|
|
||||||
width: 100%
|
|
||||||
height: 100%
|
|
||||||
|
|
||||||
#header
|
|
||||||
@include gridPosition(1, 2, 1, 2)
|
|
||||||
background-color: $cBoxHeaderBackground
|
|
||||||
display: grid
|
|
||||||
grid-template: 100% /20% 80%
|
|
||||||
|
|
||||||
span
|
|
||||||
color: $cFontWhite
|
|
||||||
span.title
|
|
||||||
@include gridPosition(1, 2, 2, 3)
|
|
||||||
margin-top: 0.25em
|
|
||||||
margin-left: 0.25em
|
|
||||||
line-height: 100%
|
|
||||||
font-size: 2em
|
|
||||||
|
|
||||||
button
|
|
||||||
background-color: $cBoxHeaderBackground
|
|
||||||
border: none
|
|
||||||
|
|
||||||
button:hover
|
|
||||||
background-color: lighten($cBoxHeaderBackground, 10%)
|
|
||||||
cursor: pointer
|
|
||||||
|
|
||||||
button:active
|
|
||||||
background-color: darken($cBoxHeaderBackground, 5%)
|
|
||||||
|
|
||||||
#goback
|
|
||||||
@include gridPosition(1, 2, 1, 2)
|
|
||||||
|
|
||||||
#chatheader
|
|
||||||
@include gridPosition(1, 2, 1, 2)
|
|
||||||
display: grid
|
|
||||||
grid-template: 100% /10% 90%
|
|
||||||
#goback
|
|
||||||
@include gridPosition(1, 2, 1, 2)
|
|
||||||
#name
|
|
||||||
@include gridPosition(1, 2, 2, 3)
|
|
||||||
|
|
||||||
#messagecontainer
|
|
||||||
@include gridPosition(2, 3, 1, 2)
|
|
||||||
overflow: auto
|
|
||||||
.chatmessage
|
|
||||||
width: 100%
|
|
||||||
#ownmessage
|
|
||||||
text-align: right
|
|
||||||
margin: 0.5em
|
|
||||||
span
|
|
||||||
background-color: $cMessageOwn
|
|
||||||
border: solid
|
|
||||||
border-color: $cMessageOwn
|
|
||||||
border-radius: 0.25em
|
|
||||||
#foreignmessage
|
|
||||||
text-align: left
|
|
||||||
margin: 0.5em
|
|
||||||
span
|
|
||||||
background-color: $cMessageForeign
|
|
||||||
border: solid
|
|
||||||
border-color: $cMessageForeign
|
|
||||||
border-radius: 0.25em
|
|
||||||
|
|
||||||
|
|
||||||
#newmessage
|
|
||||||
@include gridPosition(3, 4, 1, 2)
|
|
||||||
margin: 0.5em
|
|
||||||
display: grid
|
|
||||||
grid-template: 100% /80% 20%
|
|
||||||
#input
|
|
||||||
@include gridPosition(1, 2, 1, 2)
|
|
||||||
border-radius: 0.25em
|
|
||||||
border: 1px solid $cFeedInputBorder
|
|
||||||
padding: 0.125em
|
|
||||||
resize: none
|
|
||||||
#send
|
|
||||||
@include gridPosition(1, 2, 2, 3)
|
|
||||||
button
|
|
||||||
background-color: $cFeedChooserBackground
|
|
||||||
color: $cFontWhite
|
|
||||||
border: none
|
|
||||||
border-radius: 0.5em
|
|
||||||
button:hover
|
|
||||||
background-color: lighten($cFeedChooserBackground, 10%)
|
|
||||||
cursor: pointer
|
|
@ -1,71 +0,0 @@
|
|||||||
@import '../../../styles/mixins.sass'
|
|
||||||
@import '../../../styles/vars.sass'
|
|
||||||
|
|
||||||
#chatlist
|
|
||||||
display: grid
|
|
||||||
grid-template: 7.5% 92.5%/100%
|
|
||||||
width: 100%
|
|
||||||
height: 100%
|
|
||||||
|
|
||||||
#header
|
|
||||||
@include gridPosition(1, 2, 1, 2)
|
|
||||||
background-color: $cBoxHeaderBackground
|
|
||||||
display: grid
|
|
||||||
grid-template: 100% /80% 20%
|
|
||||||
|
|
||||||
span
|
|
||||||
color: $cFontWhite
|
|
||||||
span.title
|
|
||||||
@include gridPosition(1, 2, 1, 2)
|
|
||||||
margin-top: 0.25em
|
|
||||||
margin-left: 0.25em
|
|
||||||
line-height: 100%
|
|
||||||
font-size: 2em
|
|
||||||
|
|
||||||
button
|
|
||||||
background-color: $cBoxHeaderBackground
|
|
||||||
border: none
|
|
||||||
|
|
||||||
button:hover
|
|
||||||
background-color: lighten($cBoxHeaderBackground, 10%)
|
|
||||||
cursor: pointer
|
|
||||||
|
|
||||||
button:active
|
|
||||||
background-color: darken($cBoxHeaderBackground, 5%)
|
|
||||||
|
|
||||||
#newchat
|
|
||||||
@include gridPosition(1, 2, 2, 3)
|
|
||||||
|
|
||||||
#chats
|
|
||||||
overflow: auto
|
|
||||||
@include gridPosition(2, 3, 1, 2)
|
|
||||||
|
|
||||||
div:hover
|
|
||||||
background-color: darken($cPrimaryBackground, 10%)
|
|
||||||
cursor: pointer
|
|
||||||
.chatitem
|
|
||||||
background-color: $cPrimaryBackground
|
|
||||||
height: 3em
|
|
||||||
margin: 0.2em
|
|
||||||
padding: 0.25em
|
|
||||||
border-radius: 0.25em
|
|
||||||
display: grid
|
|
||||||
grid-template: 100% / 20% 60% 20%
|
|
||||||
.picture
|
|
||||||
@include gridPosition(1, 2, 1, 2)
|
|
||||||
border: solid
|
|
||||||
.name, .date
|
|
||||||
margin-top: auto
|
|
||||||
margin-bottom: auto
|
|
||||||
.name
|
|
||||||
@include gridPosition(1, 2, 2, 3)
|
|
||||||
font-weight: bold
|
|
||||||
text-align: left
|
|
||||||
padding-left: 0.5em
|
|
||||||
span
|
|
||||||
font-size: 125%
|
|
||||||
.date
|
|
||||||
@include gridPosition(1, 2, 3, 4)
|
|
||||||
color: $cInactiveText
|
|
||||||
text-align: right
|
|
||||||
padding-right: 0.5em
|
|
@ -0,0 +1,18 @@
|
|||||||
|
<h1 mat-dialog-title>Create a new event!</h1>
|
||||||
|
<div mat-dialog-content>
|
||||||
|
<mat-form-field style="display:contents;">
|
||||||
|
<input matInput placeholder="Enter eventname" #name>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field style="display:contents;">
|
||||||
|
<input matInput [matDatepicker]="picker" placeholder="Choose a date" #date disabled>
|
||||||
|
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
|
||||||
|
<mat-datepicker #picker disabled="false"></mat-datepicker>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field style="display:contents;">
|
||||||
|
<input matInput #time type="time" placeholder="choose a time">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div mat-dialog-actions>
|
||||||
|
<button mat-button (click)="onNoClick()">Cancel</button>
|
||||||
|
<button mat-button cdkFocusInitial (click)="createEvent(name.value, date.value, time.value)">Create Event</button>
|
||||||
|
</div>
|
@ -0,0 +1,129 @@
|
|||||||
|
<div id="profile-page">
|
||||||
|
<div id="profilecontainer" *ngIf="!groupNotFound && !loading">
|
||||||
|
<!--on small screen-->
|
||||||
|
<mat-toolbar color="primary" id="toolbar" fxShow="true" fxHide.gt-sm="true">
|
||||||
|
<mat-toolbar-row>
|
||||||
|
<div class="profile-picture"></div>
|
||||||
|
<span id="username">{{groupProfile.name}}</span>
|
||||||
|
<div class="button-box">
|
||||||
|
<button mat-icon-button
|
||||||
|
class="request-button"
|
||||||
|
matTooltip="join group" matTooltipShowDelay="500"
|
||||||
|
(click)="joinGroup(groupProfile)"
|
||||||
|
[disabled]="!groupProfile.allowedToJoinGroup">
|
||||||
|
<mat-icon>group_add</mat-icon>
|
||||||
|
</button>
|
||||||
|
<button mat-icon-button
|
||||||
|
class="request-button"
|
||||||
|
matTooltip="create event" matTooltipShowDelay="500"
|
||||||
|
(click)="openDialog()"
|
||||||
|
[disabled]="!isAdmin">
|
||||||
|
<mat-icon>event</mat-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</mat-toolbar-row>
|
||||||
|
<mat-toolbar-row>
|
||||||
|
<div class="info-box">
|
||||||
|
<span id="handle" class="pointer" (click)="showUserProfile(groupProfile.creator)">created by {{groupProfile.creator.username}} @{{groupProfile.creator.handle}}</span>
|
||||||
|
</div>
|
||||||
|
</mat-toolbar-row>
|
||||||
|
<mat-toolbar-row>
|
||||||
|
<div class="info-box">
|
||||||
|
<span class="info">{{groupProfile.members.length}} member(s)</span>
|
||||||
|
</div>
|
||||||
|
</mat-toolbar-row>
|
||||||
|
</mat-toolbar>
|
||||||
|
<!--on big screen-->
|
||||||
|
<mat-toolbar color="primary" id="toolbar" fxShow="true" fxHide.lt-md="true">
|
||||||
|
<mat-toolbar-row>
|
||||||
|
<div class="profile-picture"></div>
|
||||||
|
<span id="username">{{groupProfile.name}}</span>
|
||||||
|
<span id="handle" class="pointer" (click)="showUserProfile(groupProfile.creator)">created by {{groupProfile.creator.username}} @{{groupProfile.creator.handle}}</span>
|
||||||
|
<div class="button-box">
|
||||||
|
<button mat-icon-button
|
||||||
|
class="request-button"
|
||||||
|
matTooltip="join group" matTooltipShowDelay="500"
|
||||||
|
(click)="joinGroup(groupProfile)"
|
||||||
|
[disabled]="!groupProfile.allowedToJoinGroup">
|
||||||
|
<mat-icon>group_add</mat-icon>
|
||||||
|
</button>
|
||||||
|
<button mat-icon-button
|
||||||
|
class="request-button"
|
||||||
|
matTooltip="create event" matTooltipShowDelay="500"
|
||||||
|
(click)="openDialog()"
|
||||||
|
[disabled]="!isAdmin">
|
||||||
|
<mat-icon>event</mat-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</mat-toolbar-row>
|
||||||
|
<mat-toolbar-row>
|
||||||
|
<div class="info-box">
|
||||||
|
<span class="info">{{groupProfile.members.length}} member(s)</span>
|
||||||
|
</div>
|
||||||
|
</mat-toolbar-row>
|
||||||
|
</mat-toolbar>
|
||||||
|
<div id="accordion">
|
||||||
|
<mat-accordion>
|
||||||
|
<mat-expansion-panel *ngIf="groupProfile.events.length > 0" expanded>
|
||||||
|
<mat-expansion-panel-header>
|
||||||
|
<mat-panel-title>
|
||||||
|
Events
|
||||||
|
</mat-panel-title>
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
<div class="list">
|
||||||
|
<mat-card class="card" *ngFor="let event of groupProfile.events"
|
||||||
|
[class.selected]="event === selectedEvent"
|
||||||
|
tabindex="0">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>{{event.name}}</mat-card-title>
|
||||||
|
<mat-card-subtitle >{{event.date}}</mat-card-subtitle>
|
||||||
|
<div class="button-box">
|
||||||
|
<button mat-icon-button class="request-button"
|
||||||
|
matTooltip="join event" matTooltipShowDelay="500"
|
||||||
|
(click)="joinEvent(event)"
|
||||||
|
[disabled]="event.joined">
|
||||||
|
<mat-icon *ngIf="event.joined" color="primary">event_available</mat-icon>
|
||||||
|
<mat-icon *ngIf="!event.joined">event_available</mat-icon>
|
||||||
|
</button>
|
||||||
|
<button mat-icon-button class="request-button"
|
||||||
|
matTooltip="leave event" matTooltipShowDelay="500"
|
||||||
|
(click)="leaveEvent(event)"
|
||||||
|
[disabled]="!event.joined">
|
||||||
|
<mat-icon>event_busy</mat-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</mat-card-header>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
</mat-expansion-panel>
|
||||||
|
<mat-expansion-panel [expanded]="groupProfile.events.length < 1">
|
||||||
|
<mat-expansion-panel-header>
|
||||||
|
<mat-panel-title>
|
||||||
|
Members
|
||||||
|
</mat-panel-title>
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
<div class="list">
|
||||||
|
<mat-card class="card" *ngFor="let user of groupProfile.members"
|
||||||
|
[class.selected]="user === selectedUser"
|
||||||
|
tabindex="0">
|
||||||
|
<mat-card-header>
|
||||||
|
<div mat-card-avatar class="profile-picture" (click)="showUserProfile(user)"></div>
|
||||||
|
<mat-card-title class="pointer" (click)="showUserProfile(user)">{{user.username}}</mat-card-title>
|
||||||
|
<mat-card-subtitle class="pointer" (click)="showUserProfile(user)">{{user.handle}}</mat-card-subtitle>
|
||||||
|
<div class="button-box">
|
||||||
|
<button mat-icon-button class="request-button" (click)="sendFriendRequest(user)" [disabled]="!user.allowedToSendRequest"><mat-icon>person_add</mat-icon></button>
|
||||||
|
</div>
|
||||||
|
</mat-card-header>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
</mat-expansion-panel>
|
||||||
|
</mat-accordion>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="profilecontainer" *ngIf="groupNotFound">
|
||||||
|
<h1>Group not found :(</h1>
|
||||||
|
</div>
|
||||||
|
<mat-spinner *ngIf="loading" style="margin:0 auto; margin-top: 10em;" diameter="100"></mat-spinner>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
@ -0,0 +1,85 @@
|
|||||||
|
@import '../../../styles/mixins.sass'
|
||||||
|
@import '../../../styles/vars.sass'
|
||||||
|
|
||||||
|
#profile-page
|
||||||
|
position: fixed
|
||||||
|
width: 100%
|
||||||
|
height: calc(100% - 56px)
|
||||||
|
overflow: scroll
|
||||||
|
overflow-x: hidden
|
||||||
|
|
||||||
|
#profile
|
||||||
|
padding: 2em
|
||||||
|
max-width: 1200px
|
||||||
|
margin: 0 auto
|
||||||
|
|
||||||
|
#accordion
|
||||||
|
max-width: 690px
|
||||||
|
margin: 0 auto
|
||||||
|
|
||||||
|
$mat-card-header-size: 100px !default
|
||||||
|
#profile-card-container
|
||||||
|
margin: 0 auto
|
||||||
|
width: 100%
|
||||||
|
max-width: 690px
|
||||||
|
|
||||||
|
.button-box
|
||||||
|
text-align: right
|
||||||
|
margin-left: auto
|
||||||
|
.request-button
|
||||||
|
margin: auto 0
|
||||||
|
#toolbar
|
||||||
|
margin-top: 32px
|
||||||
|
.mat-toolbar-row
|
||||||
|
max-height: 40px
|
||||||
|
.info-box
|
||||||
|
font-size: 14px
|
||||||
|
margin-left: calc(100px + 0.5em)
|
||||||
|
.info
|
||||||
|
margin-right: 3em
|
||||||
|
#username
|
||||||
|
margin: 0 0.5em
|
||||||
|
overflow: auto
|
||||||
|
#handle
|
||||||
|
font-size: 14px
|
||||||
|
.profile-picture
|
||||||
|
background-image: url(https://material.angular.io/assets/img/examples/shiba1.jpg)
|
||||||
|
height: $mat-card-header-size
|
||||||
|
width: $mat-card-header-size
|
||||||
|
border-radius: 50%
|
||||||
|
flex-shrink: 0
|
||||||
|
background-size: cover
|
||||||
|
// Makes `<img>` tags behave like `background-size: cover`. Not supported
|
||||||
|
// in IE, but we're using it as a progressive enhancement.
|
||||||
|
object-fit: cover
|
||||||
|
|
||||||
|
.card
|
||||||
|
box-sizing: border-box
|
||||||
|
width: 100%
|
||||||
|
margin-top: 0.5em
|
||||||
|
outline: none
|
||||||
|
user-select: none
|
||||||
|
/deep/ .mat-card-header-text
|
||||||
|
margin: 0
|
||||||
|
margin-left: 16px
|
||||||
|
.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
|
||||||
|
.profile-picture
|
||||||
|
background-image: url(https://material.angular.io/assets/img/examples/shiba1.jpg)
|
||||||
|
background-size: cover
|
||||||
|
.profile-picture:hover
|
||||||
|
cursor: pointer
|
||||||
|
.pointer
|
||||||
|
cursor: pointer
|
||||||
|
|
||||||
|
/deep/ .mat-expansion-panel
|
||||||
|
background: #e6e6e6
|
||||||
|
/deep/.dark-theme .mat-expansion-panel
|
||||||
|
background: #121212
|
@ -1,20 +1,20 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import { AppScaffoldComponent } from './app-scaffold.component';
|
import { GroupComponent } from './group.component';
|
||||||
|
|
||||||
describe('AppScaffoldComponent', () => {
|
describe('GroupComponent', () => {
|
||||||
let component: AppScaffoldComponent;
|
let component: GroupComponent;
|
||||||
let fixture: ComponentFixture<AppScaffoldComponent>;
|
let fixture: ComponentFixture<GroupComponent>;
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [ AppScaffoldComponent ]
|
declarations: [ GroupComponent ]
|
||||||
})
|
})
|
||||||
.compileComponents();
|
.compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fixture = TestBed.createComponent(AppScaffoldComponent);
|
fixture = TestBed.createComponent(GroupComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
@ -0,0 +1,139 @@
|
|||||||
|
import { Component, OnInit, ViewChild} from '@angular/core';
|
||||||
|
import {Router, NavigationEnd} 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';
|
||||||
|
|
||||||
|
// DIALOG COMPONENT to create events
|
||||||
|
@Component({
|
||||||
|
selector: 'dialog-overview-example-dialog',
|
||||||
|
templateUrl: 'dialog.html',
|
||||||
|
})
|
||||||
|
export class DialogCreateEventComponent {
|
||||||
|
groupId: string;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public dialogRef: MatDialogRef<DialogCreateEventComponent>,
|
||||||
|
private group: GroupService,
|
||||||
|
private router: Router) {
|
||||||
|
this.groupId = this.router.url.substr(this.router.url.lastIndexOf('/') + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
onNoClick(): void {
|
||||||
|
this.dialogRef.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
createEvent(name: string, date: string, time: string) {
|
||||||
|
name = name.trim();
|
||||||
|
if (name && date && time) {
|
||||||
|
date = date + ' ' + time;
|
||||||
|
console.log(date);
|
||||||
|
console.log(new Date(date).getTime().toString());
|
||||||
|
this.group.createEvent(name, (new Date(date)).getTime().toString(), this.groupId);
|
||||||
|
this.dialogRef.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// GROUP COMPONENT
|
||||||
|
@Component({
|
||||||
|
selector: 'app-profile',
|
||||||
|
templateUrl: './group.component.html',
|
||||||
|
styleUrls: ['./group.component.sass']
|
||||||
|
})
|
||||||
|
|
||||||
|
export class GroupComponent implements OnInit {
|
||||||
|
groupProfile: Group = new Group();
|
||||||
|
self: User;
|
||||||
|
id: string;
|
||||||
|
isAdmin = false;
|
||||||
|
groupNotFound = false;
|
||||||
|
|
||||||
|
loading = false;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private router: Router,
|
||||||
|
public dialog: MatDialog,
|
||||||
|
private requestService: RequestService,
|
||||||
|
private data: DatasharingService,
|
||||||
|
private groupService: GroupService) {
|
||||||
|
router.events.forEach((event) => {
|
||||||
|
// check if url changes
|
||||||
|
if (event instanceof NavigationEnd) {
|
||||||
|
const possibleID = this.router.url.substr(this.router.url.lastIndexOf('/') + 1);
|
||||||
|
if (this.id !== possibleID && this.id && this.router.url.includes('group/')) {
|
||||||
|
// reload the group
|
||||||
|
console.log('search for group id: ' + this.router.url.substr(this.router.url.lastIndexOf('/') + 1));
|
||||||
|
this.ngOnInit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewChild(MatSort, {static: true}) sort: MatSort;
|
||||||
|
ngOnInit() {
|
||||||
|
this.loading = true;
|
||||||
|
this.id = this.router.url.substr(this.router.url.lastIndexOf('/') + 1);
|
||||||
|
this.data.currentUserInfo.subscribe(user => {
|
||||||
|
this.self = user;
|
||||||
|
});
|
||||||
|
this.groupService.getGroupData(this.id);
|
||||||
|
this.groupService.group.subscribe(response => {
|
||||||
|
this.isAdmin = false;
|
||||||
|
if (response) {
|
||||||
|
this.groupProfile = response;
|
||||||
|
// tslint:disable-next-line:max-line-length
|
||||||
|
this.groupProfile.allowedToJoinGroup = this.requestService.isAllowedToJoinGroup(this.groupProfile.id, this.self);
|
||||||
|
for (const admin of this.groupProfile.admins) {
|
||||||
|
if (admin.userID === this.self.userID) {
|
||||||
|
this.isAdmin = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const member of this.groupProfile.members) {
|
||||||
|
member.allowedToSendRequest = this.requestService.isAllowedToSendRequest(member.userID, this.self);
|
||||||
|
}
|
||||||
|
} else { this.groupNotFound = true; }
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
openDialog(): void {
|
||||||
|
const dialogRef = this.dialog.open(DialogCreateEventComponent, {
|
||||||
|
width: '250px'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public joinGroup(group: Group) {
|
||||||
|
group.allowedToJoinGroup = false;
|
||||||
|
this.requestService.joinGroup(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
public joinEvent(event: Event) {
|
||||||
|
this.groupService.joinEvent(event.id).subscribe(response => {
|
||||||
|
const pEvent = response.json().data.joinEvent;
|
||||||
|
event.joined = pEvent.joined;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public leaveEvent(event: Event) {
|
||||||
|
this.groupService.leaveEvent(event.id).subscribe(response => {
|
||||||
|
const pEvent = response.json().data.leaveEvent;
|
||||||
|
event.joined = pEvent.joined;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public showUserProfile(user: User) {
|
||||||
|
this.router.navigate(['profile/' + user.userID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sendFriendRequest(user: User) {
|
||||||
|
user.allowedToSendRequest = false;
|
||||||
|
this.requestService.sendFriendRequest(user);
|
||||||
|
}
|
||||||
|
}
|
@ -1,105 +1,125 @@
|
|||||||
<mat-toolbar color="primary">Profile</mat-toolbar>
|
<div id="profile-page">
|
||||||
<div id="profile">
|
<div id="profilecontainer" *ngIf="!profileNotFound && !loading">
|
||||||
<div id="profilecontainer" [hidden]="profileNotFound">
|
<!--on small screen-->
|
||||||
<div id="profile-card-container">
|
<mat-toolbar color="primary" id="toolbar" fxShow="true" fxHide.gt-sm="true">
|
||||||
<mat-card class="mat-elevation-z8">
|
<mat-toolbar-row>
|
||||||
<mat-card-header>
|
<div class="profile-picture"></div>
|
||||||
<div mat-card-avatar class="profile-picture"></div>
|
<span id="username">{{userProfile.username}}</span>
|
||||||
<mat-card-title>{{user.username}}</mat-card-title>
|
<button mat-icon-button
|
||||||
<mat-card-subtitle>{{user.handle}}</mat-card-subtitle>
|
class="request-button"
|
||||||
</mat-card-header>
|
(click)="sendFriendRequest(userProfile)"
|
||||||
<mat-card-content>
|
[disabled]="!userProfile.allowedToSendRequest">
|
||||||
<table id="profile-table">
|
<mat-icon>person_add</mat-icon>
|
||||||
<tr>
|
</button>
|
||||||
<div class="mat-header-cell">name: </div>
|
</mat-toolbar-row>
|
||||||
<td>{{user.username}}</td>
|
<mat-toolbar-row>
|
||||||
</tr>
|
<div class="info-box">
|
||||||
<mat-divider></mat-divider>
|
<span id="handle">@{{userProfile.handle}}</span>
|
||||||
<tr>
|
</div>
|
||||||
<div class="mat-header-cell">handle: </div>
|
</mat-toolbar-row>
|
||||||
<td>{{user.handle}}</td>
|
<mat-toolbar-row>
|
||||||
</tr>
|
<div>
|
||||||
<mat-divider></mat-divider>
|
<span class="info">{{rankname}} ({{userProfile.points}} points)</span>
|
||||||
<tr>
|
</div>
|
||||||
<div class="mat-header-cell">profileID: </div>
|
</mat-toolbar-row>
|
||||||
<td>{{user.userID}}</td>
|
<mat-toolbar-row>
|
||||||
</tr>
|
<div>
|
||||||
<mat-divider></mat-divider>
|
<span class="info">{{userProfile.friendCount}} friends</span>
|
||||||
<tr>
|
<span class="info">{{userProfile.groupCount}} groups</span>
|
||||||
<div class="mat-header-cell">points: </div>
|
</div>
|
||||||
<td>{{user.points}}</td>
|
</mat-toolbar-row>
|
||||||
</tr>
|
<mat-toolbar-row>
|
||||||
<mat-divider></mat-divider>
|
<div>
|
||||||
<tr>
|
<span class="info">joined on {{userProfile.joinedAt}}</span>
|
||||||
<div class="mat-header-cell">level: </div>
|
</div>
|
||||||
<td>{{user.level}}</td>
|
</mat-toolbar-row>
|
||||||
</tr>
|
</mat-toolbar>
|
||||||
<mat-divider></mat-divider>
|
<!--on big screen-->
|
||||||
<tr>
|
<mat-toolbar color="primary" id="toolbar" fxShow="true" fxHide.lt-md="true">
|
||||||
<div class="mat-header-cell">level name: </div>
|
<mat-toolbar-row>
|
||||||
<td>{{rankname}}</td>
|
<div class="profile-picture"></div>
|
||||||
</tr>
|
<span id="username">{{userProfile.username}}</span>
|
||||||
</table>
|
<span id="handle">@{{userProfile.handle}}</span>
|
||||||
</mat-card-content>
|
<button mat-icon-button
|
||||||
</mat-card>
|
class="request-button"
|
||||||
|
(click)="sendFriendRequest(userProfile)"
|
||||||
|
[disabled]="!userProfile.allowedToSendRequest">
|
||||||
|
<mat-icon>person_add</mat-icon>
|
||||||
|
</button>
|
||||||
|
</mat-toolbar-row>
|
||||||
|
<mat-toolbar-row>
|
||||||
|
<div class="info-box">
|
||||||
|
<span class="info">{{rankname}} ({{userProfile.points}} points)</span>
|
||||||
|
<span class="info">{{userProfile.friendCount}} friends</span>
|
||||||
|
<span class="info">{{userProfile.groupCount}} groups</span>
|
||||||
|
<span class="info">joined on {{userProfile.joinedAt}}</span>
|
||||||
|
</div>
|
||||||
|
</mat-toolbar-row>
|
||||||
|
</mat-toolbar>
|
||||||
|
<div id="postlist">
|
||||||
|
<feed-postlist [childPostList]="this.userProfile.posts"></feed-postlist>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<div id="profile">
|
||||||
<h1>What does the level mean?</h1>
|
<br>
|
||||||
<p>There are different levels you can reach through green behaviour.
|
<h1>What does the level mean?</h1>
|
||||||
Collect 100 points to level up! The levels are called:
|
<p>There are different levels you can reach through green behaviour.
|
||||||
</p>
|
Collect 100 points to level up! The levels are called:
|
||||||
<table mat-table [dataSource]="levelSource" class="mat-elevation-z8">
|
</p>
|
||||||
<ng-container matColumnDef="level">
|
<table mat-table [dataSource]="levelSource" class="mat-elevation-z8">
|
||||||
<th mat-header-cell *matHeaderCellDef> level </th>
|
<ng-container matColumnDef="level">
|
||||||
<td mat-cell *matCellDef="let level"> {{level.level}} </td>
|
<th mat-header-cell *matHeaderCellDef> level </th>
|
||||||
</ng-container>
|
<td mat-cell *matCellDef="let level"> {{level.level}} </td>
|
||||||
<ng-container matColumnDef="name">
|
</ng-container>
|
||||||
<th mat-header-cell *matHeaderCellDef> level name </th>
|
<ng-container matColumnDef="name">
|
||||||
<td mat-cell *matCellDef="let level"> {{level.name}} </td>
|
<th mat-header-cell *matHeaderCellDef> level name </th>
|
||||||
</ng-container>
|
<td mat-cell *matCellDef="let level"> {{level.name}} </td>
|
||||||
<tr mat-header-row *matHeaderRowDef="displayedLevelColumns"></tr>
|
</ng-container>
|
||||||
<tr mat-row *matRowDef="let row; columns: displayedLevelColumns;"></tr>
|
<tr mat-header-row *matHeaderRowDef="displayedLevelColumns"></tr>
|
||||||
</table>
|
<tr mat-row *matRowDef="let row; columns: displayedLevelColumns;"></tr>
|
||||||
<br>
|
</table>
|
||||||
<h1>How to level up?</h1>
|
<br>
|
||||||
<p>There is an always growing list of things you can do,
|
<h1>How to level up?</h1>
|
||||||
to support your environment
|
<p>There is an always growing list of things you can do,
|
||||||
and earn points to level up at the same time.
|
to support your environment
|
||||||
You can get a different amount of points
|
and earn points to level up at the same time.
|
||||||
for differnet actions you can see in the list below:
|
You can get a different amount of points
|
||||||
</p>
|
for differnet actions you can see in the list below:
|
||||||
<table mat-table [dataSource]="dataSource" matSort class="mat-elevation-z8">
|
</p>
|
||||||
<!--- Note that these columns can be defined in any order.
|
<table mat-table [dataSource]="dataSource" matSort class="mat-elevation-z8">
|
||||||
The actual rendered columns are set as a property on the row definition" -->
|
<!--- Note that these columns can be defined in any order.
|
||||||
|
The actual rendered columns are set as a property on the row definition" -->
|
||||||
<!-- Position Column -->
|
|
||||||
<ng-container matColumnDef="points">
|
<!-- Position Column -->
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> points </th>
|
<ng-container matColumnDef="points">
|
||||||
<td mat-cell *matCellDef="let action"> {{action.points}} </td>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header> points </th>
|
||||||
</ng-container>
|
<td mat-cell *matCellDef="let action"> {{action.points}} </td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<!-- Name Column -->
|
<!-- Name Column -->
|
||||||
<ng-container matColumnDef="name">
|
<ng-container matColumnDef="name">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> action </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header> action </th>
|
||||||
<td mat-cell *matCellDef="let action"> {{action.name}} </td>
|
<td mat-cell *matCellDef="let action"> {{action.name}} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||||
</table>
|
</table>
|
||||||
<!--<table style="width:100%">
|
<!--<table style="width:100%">
|
||||||
<tr>
|
<tr>
|
||||||
<th>points </th>
|
<th>points </th>
|
||||||
<th>action</th>
|
<th>action</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr *ngFor= "let action of actionlist.actions">
|
<tr *ngFor= "let action of actionlist.actions">
|
||||||
<td>{{action.points}}</td>
|
<td>{{action.points}}</td>
|
||||||
<td>{{action.name}}</td>
|
<td>{{action.name}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>-->
|
</table>-->
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div id="profilecontainer" *ngIf="profileNotFound">
|
<div id="profilecontainer" *ngIf="profileNotFound">
|
||||||
<h1>Profile not found :(</h1>
|
<h1>Profile not found :(</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<mat-spinner *ngIf="loading" style="margin:0 auto; margin-top: 10em;" diameter="100"></mat-spinner>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
|||||||
|
<div id="search">
|
||||||
|
<mat-toolbar>
|
||||||
|
<mat-form-field id="input"
|
||||||
|
floatLabel="never" >
|
||||||
|
<input matInput #searchWord
|
||||||
|
placeholder="search"
|
||||||
|
[ngModel]="searchWord.value"
|
||||||
|
(ngModelChange)="search(searchWord.value)">
|
||||||
|
<button mat-button matSuffix mat-icon-button>
|
||||||
|
<mat-icon>search </mat-icon>
|
||||||
|
</button>
|
||||||
|
</mat-form-field>
|
||||||
|
</mat-toolbar>
|
||||||
|
<mat-accordion>
|
||||||
|
<mat-expansion-panel *ngIf="foundUsers.length > 0" expanded>
|
||||||
|
<mat-expansion-panel-header>
|
||||||
|
<mat-panel-title>
|
||||||
|
Users
|
||||||
|
</mat-panel-title>
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
<div class="list">
|
||||||
|
<mat-card class="card" *ngFor="let user of foundUsers"
|
||||||
|
[class.selected]="user === selectedUser"
|
||||||
|
tabindex="0">
|
||||||
|
<mat-card-header>
|
||||||
|
<div mat-card-avatar class="profile-picture" (click)="showUserProfile(user)"></div>
|
||||||
|
<mat-card-title class="pointer" (click)="showUserProfile(user)">{{user.username}}</mat-card-title>
|
||||||
|
<mat-card-subtitle class="pointer" (click)="showUserProfile(user)">{{user.handle}}</mat-card-subtitle>
|
||||||
|
<div class="icon-box">
|
||||||
|
<button mat-icon-button class="request-button" (click)="sendFriendRequest(user)" [disabled]="!user.allowedToSendRequest"><mat-icon>person_add</mat-icon></button>
|
||||||
|
</div>
|
||||||
|
</mat-card-header>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
</mat-expansion-panel>
|
||||||
|
<mat-expansion-panel *ngIf="foundGroups.length > 0" [expanded]="foundUsers.length < 1">
|
||||||
|
<mat-expansion-panel-header>
|
||||||
|
<mat-panel-title>
|
||||||
|
Groups
|
||||||
|
</mat-panel-title>
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
<div class="list">
|
||||||
|
<mat-card class="card" *ngFor="let group of foundGroups"
|
||||||
|
[class.selected]="group === selectedGroup"
|
||||||
|
tabindex="0">
|
||||||
|
<mat-card-header>
|
||||||
|
<div mat-card-avatar class="profile-picture" (click)="showGroupProfile(group)"></div>
|
||||||
|
<mat-card-title class="pointer" (click)="showGroupProfile(group)">{{group.name}}</mat-card-title>
|
||||||
|
<div class="icon-box">
|
||||||
|
<button mat-icon-button class="request-button" (click)="joinGroup(group)" [disabled]="!group.allowedToJoinGroup"><mat-icon>group_add</mat-icon></button>
|
||||||
|
</div>
|
||||||
|
</mat-card-header>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
</mat-expansion-panel>
|
||||||
|
</mat-accordion>
|
||||||
|
<mat-spinner *ngIf="loading" style="margin:0 auto; margin-top: 5em;" diameter="50"></mat-spinner>
|
||||||
|
</div>
|
@ -0,0 +1,56 @@
|
|||||||
|
|
||||||
|
#search
|
||||||
|
width: 100%
|
||||||
|
overflow-x: hidden
|
||||||
|
height: 100%
|
||||||
|
|
||||||
|
#input
|
||||||
|
width: 100%
|
||||||
|
padding-left: 0.5em
|
||||||
|
padding-right: 0.5em
|
||||||
|
|
||||||
|
#category-chooser
|
||||||
|
padding-left: 0.5em
|
||||||
|
padding-right: 0.5em
|
||||||
|
|
||||||
|
#list
|
||||||
|
padding: 0.5em
|
||||||
|
|
||||||
|
.card
|
||||||
|
box-sizing: border-box
|
||||||
|
width: 100%
|
||||||
|
margin-top: 0.5em
|
||||||
|
outline: none
|
||||||
|
user-select: none
|
||||||
|
/deep/ .mat-card-header-text
|
||||||
|
width: 1000%
|
||||||
|
margin: 0
|
||||||
|
margin-left: 16px
|
||||||
|
.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
|
||||||
|
|
||||||
|
.profile-picture
|
||||||
|
background-image: url(https://material.angular.io/assets/img/examples/shiba1.jpg)
|
||||||
|
background-size: cover
|
||||||
|
.profile-picture:hover
|
||||||
|
cursor: pointer
|
||||||
|
|
||||||
|
.pointer:hover
|
||||||
|
cursor: pointer
|
||||||
|
|
||||||
|
.icon-box
|
||||||
|
text-align: right
|
||||||
|
width: 100%
|
||||||
|
|
||||||
|
/deep/ .mat-expansion-panel
|
||||||
|
background: #e6e6e6
|
||||||
|
/deep/.dark-theme .mat-expansion-panel
|
||||||
|
background: #121212
|
||||||
|
|
@ -0,0 +1,24 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { SearchComponent } from './search.component';
|
||||||
|
|
||||||
|
describe('ChatComponent', () => {
|
||||||
|
let component: SearchComponent;
|
||||||
|
let fixture: ComponentFixture<SearchComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ SearchComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(SearchComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,90 @@
|
|||||||
|
import { Component, OnInit} from '@angular/core';
|
||||||
|
import { SearchService } from 'src/app/services/search/search.service';
|
||||||
|
import { RequestService } from 'src/app/services/request/request.service';
|
||||||
|
import {Headers, Http} from '@angular/http';
|
||||||
|
import { User } from 'src/app/models/user';
|
||||||
|
import {environment} from 'src/environments/environment';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { DatasharingService } from '../../services/datasharing.service';
|
||||||
|
import { GroupInfo } from 'src/app/models/groupinfo';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'home-search',
|
||||||
|
templateUrl: './search.component.html',
|
||||||
|
styleUrls: ['./search.component.sass']
|
||||||
|
})
|
||||||
|
export class SearchComponent implements OnInit {
|
||||||
|
loading = false;
|
||||||
|
searchValue = ' ';
|
||||||
|
category = 'user';
|
||||||
|
user: User;
|
||||||
|
foundUsers: Array<User> = new Array();
|
||||||
|
foundGroups: Array<GroupInfo> = new Array();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private searchService: SearchService,
|
||||||
|
private requestService: RequestService,
|
||||||
|
private http: Http,
|
||||||
|
private router: Router,
|
||||||
|
private data: DatasharingService) { }
|
||||||
|
ngOnInit() {
|
||||||
|
this.data.currentUserInfo.subscribe(user => {
|
||||||
|
this.user = user;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
changeCategory(value: string) {
|
||||||
|
this.category = value;
|
||||||
|
this.search(this.searchValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
search(searchWord: string) {
|
||||||
|
this.foundUsers = Array<User>();
|
||||||
|
this.searchValue = searchWord;
|
||||||
|
if (searchWord) { // if not null or empty
|
||||||
|
if (this.category === 'user') {
|
||||||
|
this.loading = true;
|
||||||
|
this.findUser(searchWord);
|
||||||
|
} else if (this.category === 'groupe') {
|
||||||
|
// this.findUserByHandle(searchWord);
|
||||||
|
console.log('search group');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
findUser(name: String) {
|
||||||
|
const headers = new Headers();
|
||||||
|
headers.set('Content-Type', 'application/json');
|
||||||
|
this.http.post(environment.graphQLUrl, this.searchService.buildJsonUser(name))
|
||||||
|
.subscribe(response => {
|
||||||
|
this.foundUsers = this.searchService.renderUsers(response.json());
|
||||||
|
this.foundGroups = this.searchService.renderGroups(response.json());
|
||||||
|
for (const foundUser of this.foundUsers) {
|
||||||
|
foundUser.allowedToSendRequest = this.requestService.isAllowedToSendRequest(foundUser.userID, this.user);
|
||||||
|
}
|
||||||
|
for (const foundGroup of this.foundGroups) {
|
||||||
|
foundGroup.allowedToJoinGroup = this.requestService.isAllowedToJoinGroup(foundGroup.id, this.user);
|
||||||
|
}
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public showUserProfile(user: User) {
|
||||||
|
this.router.navigate(['profile/' + user.userID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public showGroupProfile(group: GroupInfo) {
|
||||||
|
this.router.navigate(['group/' + group.id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sendFriendRequest(user: User) {
|
||||||
|
user.allowedToSendRequest = false;
|
||||||
|
this.requestService.sendFriendRequest(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public joinGroup(group: GroupInfo) {
|
||||||
|
group.allowedToJoinGroup = false;
|
||||||
|
this.requestService.joinGroup(group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
|||||||
|
<h1 mat-dialog-title>Create a new group!</h1>
|
||||||
|
<div mat-dialog-content>
|
||||||
|
<mat-form-field>
|
||||||
|
<input matInput placeholder="Enter groupname" #name>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div mat-dialog-actions>
|
||||||
|
<button mat-button (click)="onNoClick()">Cancel</button>
|
||||||
|
<button mat-button cdkFocusInitial (click)="createGroup(name.value)">Create Group</button>
|
||||||
|
</div>
|
@ -1,21 +1,59 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { GroupInfo } from 'src/app/models/groupinfo';
|
import { GroupInfo } from 'src/app/models/groupinfo';
|
||||||
|
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 { Router } from '@angular/router';
|
||||||
|
|
||||||
|
// DIALOG COMPONENT to create groups
|
||||||
|
@Component({
|
||||||
|
selector: 'dialog-overview-example-dialog',
|
||||||
|
templateUrl: 'dialog.html',
|
||||||
|
})
|
||||||
|
export class DialogCreateGroupComponent {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public dialogRef: MatDialogRef<DialogCreateGroupComponent>, private social: SocialService) {}
|
||||||
|
|
||||||
|
onNoClick(): void {
|
||||||
|
this.dialogRef.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
createGroup(name: string) {
|
||||||
|
console.log('create groupe ' + name);
|
||||||
|
name = name.trim();
|
||||||
|
if (name) {
|
||||||
|
this.social.createGroup(name);
|
||||||
|
this.dialogRef.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GROUP COMPONENT
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'social-groups',
|
selector: 'social-groups',
|
||||||
templateUrl: './groups.component.html',
|
templateUrl: './groups.component.html',
|
||||||
styleUrls: ['./groups.component.sass']
|
styleUrls: ['./groups.component.sass']
|
||||||
})
|
})
|
||||||
export class GroupsComponent implements OnInit {
|
export class GroupsComponent implements OnInit {
|
||||||
// TODO: replace with actual logic that loads the groups from the backend
|
user: User;
|
||||||
groups: Array<GroupInfo> = [
|
constructor(public dialog: MatDialog, private data: DatasharingService, private router: Router) { }
|
||||||
new GroupInfo(1, 'Group 1', []),
|
|
||||||
new GroupInfo(1, 'Group 2', []),
|
|
||||||
new GroupInfo(1, 'Group 3', []),
|
|
||||||
new GroupInfo(1, 'Group 4', [])];
|
|
||||||
constructor() { }
|
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
this.data.currentUserInfo.subscribe(user => {
|
||||||
|
this.user = user; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public showGroupProfile(group: GroupInfo) {
|
||||||
|
this.router.navigate(['group/' + group.id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
openDialog(): void {
|
||||||
|
const dialogRef = this.dialog.open(DialogCreateGroupComponent, {
|
||||||
|
width: '250px'
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,2 +1,25 @@
|
|||||||
<social-friends id="friendscontainer"></social-friends>
|
<div id="content" fxShow="true" fxHide.lt-md="true">
|
||||||
<social-groups id="groupscontainer"></social-groups>
|
<mat-tab-group selectedIndex="0" mat-stretch-tabs id="tabs">
|
||||||
|
<mat-tab>
|
||||||
|
<ng-template mat-tab-label>
|
||||||
|
<mat-icon>people</mat-icon>
|
||||||
|
</ng-template>
|
||||||
|
<div id="friendscontainer">
|
||||||
|
<social-friends></social-friends>
|
||||||
|
</div>
|
||||||
|
<social-groups id="groupscontainer"></social-groups>
|
||||||
|
</mat-tab>
|
||||||
|
<mat-tab>
|
||||||
|
<ng-template mat-tab-label>
|
||||||
|
<mat-icon>search</mat-icon>
|
||||||
|
</ng-template>
|
||||||
|
<home-search class="tab-content"></home-search>
|
||||||
|
</mat-tab>
|
||||||
|
</mat-tab-group>
|
||||||
|
</div>
|
||||||
|
<div fxShow="true" fxHide.gt-sm="true">
|
||||||
|
<social-friends id="friendscontainer"></social-friends>
|
||||||
|
<social-groups id="groupscontainer"></social-groups>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="64px"
|
||||||
|
height="64px"
|
||||||
|
viewBox="0 0 64 64"
|
||||||
|
version="1.1"
|
||||||
|
id="SVGRoot"
|
||||||
|
inkscape:version="0.92.4 5da689c313, 2019-01-14"
|
||||||
|
sodipodi:docname="gv-new-logo-white.svg">
|
||||||
|
<defs
|
||||||
|
id="defs3412" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="5.656854"
|
||||||
|
inkscape:cx="-16.580479"
|
||||||
|
inkscape:cy="40.712852"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer2"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1003"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:grid-bbox="true" />
|
||||||
|
<metadata
|
||||||
|
id="metadata3415">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer2"
|
||||||
|
inkscape:label="Layer 2"
|
||||||
|
style="display:inline">
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#ffffff;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 59.638425,10.982918 c -2.598034,1.65974 -5.164767,1.536797 -6.79245,1.598268 -1.627684,0.06147 -7.89147,-0.248912 -10.548644,-0.307359 -2.031158,-0.04467 -10.408921,-0.634292 -18.029729,3.227272 -6.189793,3.136452 -10.030686,7.78418 -11.299883,11.09567 -1.095556,2.858442 -1.721588,5.317315 -1.095556,9.896969 0.334798,2.449172 0.916715,4.631314 0.829032,5.615672 -0.07744,0.869314 0.04741,1.638006 -2.331509,4.035408 -2.3789231,2.397403 -7.5630585,6.702992 -7.5630585,6.702992"
|
||||||
|
id="path3986"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="csssssssc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#ffffff;stroke-width:2.81999993;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 17.040936,45.75125 c 0,0 5.71124,1.10058 9.863991,0.923511 4.152753,-0.177069 10.503177,-1.963537 14.640251,-4.074381 2.654809,-1.354554 8.010685,-4.452479 10.623857,-9.671077 1.545586,-3.086589 2.392221,-6.933871 2.615983,-8.836099 0.374688,-3.185266 0.215574,-5.492636 0.858958,-6.968217"
|
||||||
|
id="path3988"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cssssc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 16.515165,41.68934 c 0,0 3.942744,-4.483925 8.75,-9 3.732038,-3.505984 5.757466,-5.519577 10.967068,-8.580806 3.85598,-2.265823 12.426015,-6.277728 15.87316,-7.736136"
|
||||||
|
id="path3990"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cssc" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.4 KiB |
@ -0,0 +1,13 @@
|
|||||||
|
export class Event {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
date: string;
|
||||||
|
joined: boolean;
|
||||||
|
|
||||||
|
constructor(pId: string, pName: string, pdate: string, pjoined: boolean) {
|
||||||
|
this.id = pId;
|
||||||
|
this.name = pName;
|
||||||
|
this.date = pdate;
|
||||||
|
this.joined = pjoined;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
import { User } from 'src/app/models/user';
|
||||||
|
|
||||||
|
export class FriendRequest {
|
||||||
|
id: number;
|
||||||
|
senderUserID: number;
|
||||||
|
senderHandle: string;
|
||||||
|
senderUsername: string;
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
import { User } from 'src/app/models/user';
|
||||||
|
import { Event } from 'src/app/models/event';
|
||||||
|
|
||||||
|
export class Group {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
handle: string;
|
||||||
|
creator: User = new User();
|
||||||
|
members: User[] = new Array();
|
||||||
|
admins: User[] = new Array();
|
||||||
|
events: Event[] = new Array();
|
||||||
|
joined: boolean;
|
||||||
|
allowedToJoinGroup = false;
|
||||||
|
}
|
@ -1,11 +1,10 @@
|
|||||||
export class GroupInfo {
|
export class GroupInfo {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
members: number[];
|
allowedToJoinGroup = false;
|
||||||
|
|
||||||
constructor(pId: number, pName: string, pMembers: number[]) {
|
constructor(pId: number, pName: string) {
|
||||||
this.id = pId;
|
this.id = pId;
|
||||||
this.name = pName;
|
this.name = pName;
|
||||||
this.members = pMembers;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,29 @@
|
|||||||
|
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';
|
||||||
|
|
||||||
export class User {
|
export class User {
|
||||||
loggedIn: boolean;
|
loggedIn = false;
|
||||||
userID: number;
|
userID: number;
|
||||||
username: string;
|
username: string;
|
||||||
handle: string;
|
handle: string;
|
||||||
email: string;
|
email: string;
|
||||||
points: number;
|
points: number;
|
||||||
level: number;
|
level: number;
|
||||||
|
profilePicture: string;
|
||||||
|
joinedAt: string;
|
||||||
|
friendCount: number;
|
||||||
|
groupCount: number;
|
||||||
|
|
||||||
friendIDs: number[];
|
darkmode = false;
|
||||||
groupIDs: number[];
|
|
||||||
chatIDs: number[];
|
|
||||||
|
|
||||||
requestIDs: number[];
|
friends: FriendInfo[] = new Array();
|
||||||
|
groups: GroupInfo[] = new Array();
|
||||||
|
posts: Post[] = new Array();
|
||||||
|
chatIDs: number[];
|
||||||
|
receivedRequests: FriendRequest[] = new Array();
|
||||||
|
sentRequestUserIDs: number[] = new Array(); // IDs of users that already received requests of the logged in user
|
||||||
|
allowedToSendRequest = true; /* if a user already received a request this should
|
||||||
|
be false to avoid multiple invitations*/
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { GroupService } from './group.service';
|
||||||
|
|
||||||
|
describe('GroupService', () => {
|
||||||
|
beforeEach(() => TestBed.configureTestingModule({}));
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
const service: GroupService = TestBed.get(GroupService);
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,134 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Http } from '@angular/http';
|
||||||
|
import { Author } from 'src/app/models/author';
|
||||||
|
import { environment } from 'src/environments/environment';
|
||||||
|
import { User } from 'src/app/models/user';
|
||||||
|
import { Event } from 'src/app/models/event';
|
||||||
|
import { Observable, BehaviorSubject } from 'rxjs';
|
||||||
|
import { Group } from 'src/app/models/group';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class GroupService {
|
||||||
|
|
||||||
|
public group: BehaviorSubject<Group> = new BehaviorSubject(new Group());
|
||||||
|
|
||||||
|
constructor(private http: Http) { }
|
||||||
|
|
||||||
|
public getGroupData(groupId: string) {
|
||||||
|
const headers = new Headers();
|
||||||
|
headers.set('Content-Type', 'application/json');
|
||||||
|
this.http.post(environment.graphQLUrl, this.buildGetGroupJson(groupId)).subscribe(result => {
|
||||||
|
// push onto subject
|
||||||
|
this.group.next(this.renderGroup(result.json()));
|
||||||
|
return this.group;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public buildGetGroupJson(id: string): any {
|
||||||
|
const body = {
|
||||||
|
query: `query($groupId: ID!) {
|
||||||
|
getGroup(groupId:$groupId){
|
||||||
|
id
|
||||||
|
name
|
||||||
|
joined
|
||||||
|
creator{id name handle}
|
||||||
|
admins{id name handle}
|
||||||
|
members{id name handle}
|
||||||
|
events{id name dueDate joined}
|
||||||
|
}
|
||||||
|
}`, variables: {
|
||||||
|
groupId: id
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public renderGroup(response: any): Group {
|
||||||
|
const group = new Group();
|
||||||
|
if (response.data.getGroup != null) {
|
||||||
|
group.id = response.data.getGroup.id;
|
||||||
|
group.name = response.data.getGroup.name;
|
||||||
|
group.creator.userID = response.data.getGroup.creator.id;
|
||||||
|
group.creator.handle = response.data.getGroup.creator.handle;
|
||||||
|
group.creator.username = response.data.getGroup.creator.name;
|
||||||
|
group.joined = response.data.getGroup.joined;
|
||||||
|
|
||||||
|
for (const member of response.data.getGroup.members) {
|
||||||
|
const user = new User();
|
||||||
|
user.userID = member.id;
|
||||||
|
user.username = member.name;
|
||||||
|
user.handle = member.handle;
|
||||||
|
group.members.push(user);
|
||||||
|
}
|
||||||
|
for (const admin of response.data.getGroup.admins) {
|
||||||
|
const user = new User();
|
||||||
|
user.userID = admin.id;
|
||||||
|
user.username = admin.name;
|
||||||
|
user.handle = admin.handle;
|
||||||
|
group.admins.push(user);
|
||||||
|
}
|
||||||
|
for (const event of response.data.getGroup.events) {
|
||||||
|
const temp = new Date(Number(event.dueDate));
|
||||||
|
const date = temp.toLocaleString('en-GB');
|
||||||
|
group.events.push(new Event(event.id, event.name, date, event.joined));
|
||||||
|
}
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public createEvent(name: string, date: string, groupId: string) {
|
||||||
|
const headers = new Headers();
|
||||||
|
headers.set('Content-Type', 'application/json');
|
||||||
|
const body = {query: `mutation($groupId: ID!, $name: String, $date: String) {
|
||||||
|
createEvent(name: $name, dueDate: $date, groupId: $groupId) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
dueDate
|
||||||
|
joined
|
||||||
|
}
|
||||||
|
}`, variables: {
|
||||||
|
name: name,
|
||||||
|
date: date,
|
||||||
|
groupId: groupId
|
||||||
|
}};
|
||||||
|
|
||||||
|
this.http.post(environment.graphQLUrl, body).subscribe(response => {
|
||||||
|
const event = response.json().data.createEvent;
|
||||||
|
const temp = new Date(Number(event.dueDate));
|
||||||
|
const pdate = temp.toLocaleString('en-GB');
|
||||||
|
this.group.next(
|
||||||
|
this.renderGroup(this.group.getValue().events.push(new Event(event.id, event.name, pdate, event.joined)))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public joinEvent(eventId: string) {
|
||||||
|
const headers = new Headers();
|
||||||
|
headers.set('Content-Type', 'application/json');
|
||||||
|
const body = {query: `mutation($eventId: ID!) {
|
||||||
|
joinEvent(eventId: $eventId) {
|
||||||
|
joined
|
||||||
|
}
|
||||||
|
}`, variables: {
|
||||||
|
eventId: eventId
|
||||||
|
}};
|
||||||
|
return this.http.post(environment.graphQLUrl, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
public leaveEvent(eventId: string) {
|
||||||
|
const headers = new Headers();
|
||||||
|
headers.set('Content-Type', 'application/json');
|
||||||
|
const body = {query: `mutation($eventId: ID!) {
|
||||||
|
leaveEvent(eventId: $eventId) {
|
||||||
|
joined
|
||||||
|
}
|
||||||
|
}`, variables: {
|
||||||
|
eventId: eventId
|
||||||
|
}};
|
||||||
|
return this.http.post(environment.graphQLUrl, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ProfileService } from './profile.service';
|
||||||
|
|
||||||
|
describe('ProfileService', () => {
|
||||||
|
beforeEach(() => TestBed.configureTestingModule({}));
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
const service: ProfileService = TestBed.get(ProfileService);
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,98 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Http } from '@angular/http';
|
||||||
|
import { Post } from 'src/app/models/post';
|
||||||
|
import { Author } from 'src/app/models/author';
|
||||||
|
import { environment } from 'src/environments/environment';
|
||||||
|
import { User } from 'src/app/models/user';
|
||||||
|
import { Observable, Subject } from 'rxjs';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class ProfileService {
|
||||||
|
|
||||||
|
public proflile: Subject<any> = new Subject();
|
||||||
|
|
||||||
|
constructor(private http: Http) { }
|
||||||
|
|
||||||
|
public getUserData(userId: string) {
|
||||||
|
const headers = new Headers();
|
||||||
|
headers.set('Content-Type', 'application/json');
|
||||||
|
// return this.renderProfile(this.http.post(environment.graphQLUrl, this.buildGetProfileJson(userId)));
|
||||||
|
this.http.post(environment.graphQLUrl, this.buildGetProfileJson(userId)).subscribe(result => {
|
||||||
|
// push onto subject
|
||||||
|
this.proflile.next(this.renderProfile(result.json()));
|
||||||
|
return this.proflile;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public buildGetProfileJson(id: string): any {
|
||||||
|
const body = {query: `query($userId: ID) {
|
||||||
|
getUser(userId:$userId){
|
||||||
|
id
|
||||||
|
handle
|
||||||
|
name
|
||||||
|
profilePicture
|
||||||
|
points
|
||||||
|
level
|
||||||
|
friendCount
|
||||||
|
groupCount
|
||||||
|
joinedAt
|
||||||
|
friends{
|
||||||
|
id
|
||||||
|
}
|
||||||
|
posts{
|
||||||
|
id,
|
||||||
|
content,
|
||||||
|
htmlContent,
|
||||||
|
upvotes,
|
||||||
|
downvotes,
|
||||||
|
userVote,
|
||||||
|
deletable,
|
||||||
|
author{
|
||||||
|
name,
|
||||||
|
handle,
|
||||||
|
id},
|
||||||
|
createdAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`, variables: {
|
||||||
|
userId: id,
|
||||||
|
}};
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public renderProfile(response: any): User {
|
||||||
|
const posts = new Array<Post>();
|
||||||
|
const profile = new User();
|
||||||
|
if (response.data.getUser != null) {
|
||||||
|
|
||||||
|
profile.userID = response.data.getUser.id;
|
||||||
|
profile.username = response.data.getUser.name;
|
||||||
|
profile.handle = response.data.getUser.handle;
|
||||||
|
profile.points = response.data.getUser.points;
|
||||||
|
profile.level = response.data.getUser.level;
|
||||||
|
profile.friendCount = response.data.getUser.friendCount;
|
||||||
|
profile.groupCount = response.data.getUser.groupCount;
|
||||||
|
const temp = new Date(Number(response.data.getUser.joinedAt));
|
||||||
|
const date = temp.toLocaleString('en-GB');
|
||||||
|
profile.joinedAt = date;
|
||||||
|
for (const post of response.data.getUser.posts) {
|
||||||
|
const id: number = post.id;
|
||||||
|
const content: string = post.content;
|
||||||
|
const htmlContent: string = post.htmlContent;
|
||||||
|
const upvotes: number = post.upvotes;
|
||||||
|
const downvotes: number = post.downvotes;
|
||||||
|
const userVote: string = post.userVote;
|
||||||
|
const deletable: boolean = post.deletable;
|
||||||
|
const author = new Author(post.author.id, post.author.name, post.author.handle);
|
||||||
|
const ptemp = new Date(Number(post.createdAt));
|
||||||
|
const pdate = ptemp.toLocaleString('en-GB');
|
||||||
|
posts.push(new Post(id, content, htmlContent, upvotes, downvotes, userVote, deletable, pdate, author));
|
||||||
|
}
|
||||||
|
profile.posts = posts;
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { RequestService } from './request.service';
|
||||||
|
|
||||||
|
describe('RequestService', () => {
|
||||||
|
beforeEach(() => TestBed.configureTestingModule({}));
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
const service: RequestService = TestBed.get(RequestService);
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,123 @@
|
|||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
import {Headers, Http} from '@angular/http';
|
||||||
|
import {DatasharingService} from '../datasharing.service';
|
||||||
|
import {Router} from '@angular/router';
|
||||||
|
import {environment} from 'src/environments/environment';
|
||||||
|
import { User } from 'src/app/models/user';
|
||||||
|
import { GroupInfo } from 'src/app/models/groupinfo';
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class RequestService {
|
||||||
|
|
||||||
|
constructor(private http: Http, private data: DatasharingService, private router: Router) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public isAllowedToSendRequest(userID: number, self: User): boolean {
|
||||||
|
if (!self.loggedIn) { return false; } else {
|
||||||
|
for (const receiverID of self.sentRequestUserIDs) {
|
||||||
|
if (userID === receiverID ||
|
||||||
|
userID === self.userID) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const friend of self.friends) {
|
||||||
|
if (userID === friend.id) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const sender of self.receivedRequests) {
|
||||||
|
if (userID === sender.senderUserID) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isAllowedToJoinGroup(groupId: number, self: User): boolean {
|
||||||
|
// returns false if user is not logged in or is member of the group(Id)
|
||||||
|
if (!self.loggedIn) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (const group of self.groups) {
|
||||||
|
if (group.id === groupId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public sendFriendRequest(user: User) {
|
||||||
|
this.data.addSentRequestUserID(user.userID);
|
||||||
|
const headers = new Headers();
|
||||||
|
headers.set('Content-Type', 'application/json');
|
||||||
|
this.http.post(environment.graphQLUrl, this.buildJsonRequest(user.userID, 'FRIENDREQUEST'))
|
||||||
|
.subscribe(response => {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public joinGroup(group: GroupInfo) {
|
||||||
|
const headers = new Headers();
|
||||||
|
headers.set('Content-Type', 'application/json');
|
||||||
|
this.http.post(environment.graphQLUrl, this.buildJsonJoinGroup(group.id))
|
||||||
|
.subscribe(response => {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public buildJsonRequest(id_: number, type_: String): any {
|
||||||
|
const body = {
|
||||||
|
query: `mutation($id: ID!, $type: RequestType) {
|
||||||
|
sendRequest(receiver: $id, type: $type) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
, variables: {
|
||||||
|
id: id_,
|
||||||
|
type: type_
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public buildJsonJoinGroup(id_: number): any {
|
||||||
|
const body = {
|
||||||
|
query: `mutation($id: ID!) {
|
||||||
|
joinGroup(id: $id) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
, variables: {
|
||||||
|
id: id_
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public buildJsonAcceptRequest(id_: number): any {
|
||||||
|
const body = {
|
||||||
|
query: `mutation($id: ID!) {
|
||||||
|
acceptRequest(sender: $id, type: FRIENDREQUEST)
|
||||||
|
}`
|
||||||
|
, variables: {
|
||||||
|
id: id_
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public buildJsonDenyRequest(id_: number): any {
|
||||||
|
const body = {
|
||||||
|
query: `mutation($id: ID!) {
|
||||||
|
denyRequest(sender: $id, type: FRIENDREQUEST)
|
||||||
|
}`
|
||||||
|
, variables: {
|
||||||
|
id: id_
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { SearchService } from './search.service';
|
||||||
|
|
||||||
|
describe('SearchService', () => {
|
||||||
|
beforeEach(() => TestBed.configureTestingModule({}));
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
const service: SearchService = TestBed.get(SearchService);
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,71 @@
|
|||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
import {Headers, Http} from '@angular/http';
|
||||||
|
import {DatasharingService} from '../datasharing.service';
|
||||||
|
import {Router} from '@angular/router';
|
||||||
|
import {environment} from 'src/environments/environment';
|
||||||
|
import { User } from 'src/app/models/user';
|
||||||
|
import { GroupInfo } from 'src/app/models/groupinfo';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class SearchService {
|
||||||
|
|
||||||
|
users: Array<User>;
|
||||||
|
constructor(private http: Http, private data: DatasharingService, private router: Router) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public renderUsers(pResponse: any): Array<User> {
|
||||||
|
const users = new Array<User>();
|
||||||
|
for (const user of pResponse.data.search.users) {
|
||||||
|
const pUser = new User();
|
||||||
|
pUser.profilePicture = user.profilePicture;
|
||||||
|
pUser.username = user.name;
|
||||||
|
pUser.userID = user.id;
|
||||||
|
pUser.handle = user.handle;
|
||||||
|
pUser.points = user.points;
|
||||||
|
pUser.level = user.level;
|
||||||
|
pUser.friends = user.friends;
|
||||||
|
users.push(pUser);
|
||||||
|
}
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
public renderGroups(pResponse: any): Array<GroupInfo> {
|
||||||
|
const groups = new Array<GroupInfo>();
|
||||||
|
for (const group of pResponse.data.search.groups) {
|
||||||
|
groups.push(new GroupInfo(group.id, group.name));
|
||||||
|
}
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public buildJsonUser(name_: String): any {
|
||||||
|
const body = {
|
||||||
|
query: `query($name: String!) {
|
||||||
|
search(query:$name, first: 100, offset: 0) {
|
||||||
|
users{
|
||||||
|
profilePicture,
|
||||||
|
name,
|
||||||
|
id,
|
||||||
|
handle,
|
||||||
|
points,
|
||||||
|
level,
|
||||||
|
friends {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
groups{
|
||||||
|
id
|
||||||
|
name
|
||||||
|
creator{id name handle}
|
||||||
|
members{id name handle}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
, variables: {
|
||||||
|
name: name_
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { SettingsService } from './settings.service';
|
||||||
|
|
||||||
|
describe('SettingsService', () => {
|
||||||
|
beforeEach(() => TestBed.configureTestingModule({}));
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
const service: SettingsService = TestBed.get(SettingsService);
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,37 @@
|
|||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
import {Http} from '@angular/http';
|
||||||
|
import { User } from 'src/app/models/user';
|
||||||
|
import { environment } from 'src/environments/environment';
|
||||||
|
import {DatasharingService} from '../datasharing.service';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class SettingsService {
|
||||||
|
|
||||||
|
users: Array<User>;
|
||||||
|
constructor(private http: Http, private data: DatasharingService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
setDarkModeActive(active: boolean) {
|
||||||
|
this.data.setDarkMode(active);
|
||||||
|
const url = environment.graphQLUrl;
|
||||||
|
const headers = new Headers();
|
||||||
|
headers.set('Content-Type', 'application/json');
|
||||||
|
const body = this.buildJsonDarkMode('darkmode: ' + '\'' + active + '\'');
|
||||||
|
this.http.post(url, body).subscribe(response => {
|
||||||
|
console.log(response.text()); });
|
||||||
|
}
|
||||||
|
|
||||||
|
public buildJsonDarkMode(setting_: string): any {
|
||||||
|
const body = {
|
||||||
|
query: `mutation($setting: String!) {
|
||||||
|
setUserSettings(settings: $setting)
|
||||||
|
}`
|
||||||
|
, variables: {
|
||||||
|
setting: setting_
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { SocialService } from './social.service';
|
||||||
|
|
||||||
|
describe('SocialService', () => {
|
||||||
|
beforeEach(() => TestBed.configureTestingModule({}));
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
const service: SocialService = TestBed.get(SocialService);
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,37 @@
|
|||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
import {Headers, Http} from '@angular/http';
|
||||||
|
import {DatasharingService} from '../datasharing.service';
|
||||||
|
import {Router} from '@angular/router';
|
||||||
|
import {environment} from 'src/environments/environment';
|
||||||
|
import { User } from 'src/app/models/user';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class SocialService {
|
||||||
|
|
||||||
|
users: Array<User>;
|
||||||
|
constructor(private http: Http, private data: DatasharingService, private router: Router) {
|
||||||
|
}
|
||||||
|
|
||||||
|
createGroup(name: string) {
|
||||||
|
const headers = new Headers();
|
||||||
|
headers.set('Content-Type', 'application/json');
|
||||||
|
this.http.post(environment.graphQLUrl, this.buildJsonGroup(name)).subscribe(response => {
|
||||||
|
console.log(response.text()); });
|
||||||
|
}
|
||||||
|
|
||||||
|
public buildJsonGroup(name_: String): any {
|
||||||
|
const body = {
|
||||||
|
query: `mutation($name: String!) {
|
||||||
|
createGroup(name: $name) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
, variables: {
|
||||||
|
name: name_
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
}
|
@ -1,27 +1,6 @@
|
|||||||
$cPrimaryBackground: #fff
|
@import '~@angular/material/theming'
|
||||||
$cSecondaryBackground: #ddd
|
|
||||||
$cInactiveText: #555
|
|
||||||
$cPrimarySurface: #fff
|
|
||||||
|
|
||||||
//Headerbar
|
$primary: mat-palette($mat-light-green);
|
||||||
$cHeadPrimaryBackground: #0d6b14
|
$primary-color: mat-color($primary);
|
||||||
$cHeadFontColor: #adffc1ee
|
|
||||||
|
|
||||||
//Home -- Feed
|
|
||||||
$cFeedPrimaryFontColor: #243dca
|
|
||||||
$cFeedSecondaryFontColor: #243dca
|
|
||||||
$cFeedInputBorder: #396d51
|
|
||||||
$cFeedItemBackground: #b0ecb0fb
|
|
||||||
$cFeedChooserBackground: #259145
|
|
||||||
$cFeedBackground: #36ce64
|
|
||||||
$cFeedUpVote: #2cb149
|
|
||||||
$cFeedDownVote: #ff5f5f
|
|
||||||
|
|
||||||
//Home -- Chat, Friends, Groups
|
|
||||||
$cFontWhite: #fff//#adffc1ee //this is also the background color lol
|
|
||||||
$cBoxHeaderBackground: #259145
|
|
||||||
$cBoxBodyBackground: #fff//#3deb71
|
|
||||||
$cMessageOwn: #cfe4c9
|
|
||||||
$cMessageForeign: #baca5d
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
declare module '*.svg' {
|
||||||
|
const svg: string;
|
||||||
|
export default svg;
|
||||||
|
}
|
Loading…
Reference in New Issue