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 { AppScaffoldComponent } from './app-scaffold.component';
|
||||
import { GroupComponent } from './group.component';
|
||||
|
||||
describe('AppScaffoldComponent', () => {
|
||||
let component: AppScaffoldComponent;
|
||||
let fixture: ComponentFixture<AppScaffoldComponent>;
|
||||
describe('GroupComponent', () => {
|
||||
let component: GroupComponent;
|
||||
let fixture: ComponentFixture<GroupComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ AppScaffoldComponent ]
|
||||
declarations: [ GroupComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AppScaffoldComponent);
|
||||
fixture = TestBed.createComponent(GroupComponent);
|
||||
component = fixture.componentInstance;
|
||||
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);
|
||||
}
|
||||
}
|
@ -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 { 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({
|
||||
selector: 'social-groups',
|
||||
templateUrl: './groups.component.html',
|
||||
styleUrls: ['./groups.component.sass']
|
||||
})
|
||||
export class GroupsComponent implements OnInit {
|
||||
// TODO: replace with actual logic that loads the groups from the backend
|
||||
groups: Array<GroupInfo> = [
|
||||
new GroupInfo(1, 'Group 1', []),
|
||||
new GroupInfo(1, 'Group 2', []),
|
||||
new GroupInfo(1, 'Group 3', []),
|
||||
new GroupInfo(1, 'Group 4', [])];
|
||||
constructor() { }
|
||||
user: User;
|
||||
constructor(public dialog: MatDialog, private data: DatasharingService, private router: Router) { }
|
||||
|
||||
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 @@
|
||||
<div id="content" fxShow="true" fxHide.lt-md="true">
|
||||
<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 {
|
||||
id: number;
|
||||
name: string;
|
||||
members: number[];
|
||||
allowedToJoinGroup = false;
|
||||
|
||||
constructor(pId: number, pName: string, pMembers: number[]) {
|
||||
constructor(pId: number, pName: string) {
|
||||
this.id = pId;
|
||||
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 {
|
||||
loggedIn: boolean;
|
||||
loggedIn = false;
|
||||
userID: number;
|
||||
username: string;
|
||||
handle: string;
|
||||
email: string;
|
||||
points: number;
|
||||
level: number;
|
||||
profilePicture: string;
|
||||
joinedAt: string;
|
||||
friendCount: number;
|
||||
groupCount: number;
|
||||
|
||||
friendIDs: number[];
|
||||
groupIDs: number[];
|
||||
chatIDs: number[];
|
||||
darkmode = false;
|
||||
|
||||
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
|
||||
$cSecondaryBackground: #ddd
|
||||
$cInactiveText: #555
|
||||
$cPrimarySurface: #fff
|
||||
@import '~@angular/material/theming'
|
||||
|
||||
//Headerbar
|
||||
$cHeadPrimaryBackground: #0d6b14
|
||||
$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
|
||||
$primary: mat-palette($mat-light-green);
|
||||
$primary-color: mat-color($primary);
|
||||
|
||||
|
||||
|
@ -0,0 +1,5 @@
|
||||
|
||||
declare module '*.svg' {
|
||||
const svg: string;
|
||||
export default svg;
|
||||
}
|
Loading…
Reference in New Issue