Merge branch 'master' into julius-dev

master
Trivernis 5 years ago
commit dea36c122d

2114
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -17,47 +17,47 @@
"@angular/compiler": "~8.2.14", "@angular/compiler": "~8.2.14",
"@angular/core": "^8.2.14", "@angular/core": "^8.2.14",
"@angular/flex-layout": "^8.0.0-beta.27", "@angular/flex-layout": "^8.0.0-beta.27",
"@angular/forms": "~7.0.0", "@angular/forms": "^7.2.15",
"@angular/http": "~7.0.0", "@angular/http": "^7.2.15",
"@angular/material": "^8.2.3", "@angular/material": "^8.2.3",
"@angular/platform-browser": "8.2.14", "@angular/platform-browser": "8.2.14",
"@angular/platform-browser-dynamic": "^8.2.14", "@angular/platform-browser-dynamic": "^8.2.14",
"@angular/router": "~8.2.14", "@angular/router": "~8.2.14",
"apollo-angular": "^1.7.0", "apollo-angular": "^1.8.0",
"apollo-angular-link-http": "^1.6.0", "apollo-angular-link-http": "^1.9.0",
"apollo-cache-inmemory": "^1.3.2", "apollo-cache-inmemory": "^1.6.5",
"apollo-client": "^2.6.0", "apollo-client": "^2.6.8",
"apollo-link": "^1.2.11", "apollo-link": "^1.2.11",
"core-js": "^2.5.4", "core-js": "^2.6.11",
"graphql": "^14.3.1", "graphql": "^14.3.1",
"graphql-tag": "^2.10.0", "graphql-tag": "^2.10.0",
"hammerjs": "^2.0.8", "hammerjs": "^2.0.8",
"js-sha512": "^0.8.0", "js-sha512": "^0.8.0",
"ngx-socket-io": "^2.0.0", "ngx-socket-io": "^2.1.1",
"node-sass": "^4.13.0", "node-sass": "^4.13.0",
"rxjs": "~6.3.3", "rxjs": "~6.3.3",
"ts-md5": "^1.2.7", "ts-md5": "^1.2.7",
"zone.js": "~0.8.26" "zone.js": "^0.8.29"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "^0.803.20", "@angular-devkit/build-angular": "^0.803.21",
"@angular/cli": "^8.3.20", "@angular/cli": "^8.3.21",
"@angular/compiler-cli": "^8.2.14", "@angular/compiler-cli": "^8.2.14",
"@angular/language-service": "~7.0.0", "@angular/language-service": "^7.2.15",
"@types/jasmine": "~2.8.8", "@types/jasmine": "^2.8.16",
"@types/jasminewd2": "~2.0.3", "@types/jasminewd2": "^2.0.8",
"@types/node": "~8.9.4", "@types/node": "~8.9.4",
"codelyzer": "~4.5.0", "codelyzer": "~4.5.0",
"jasmine-core": "~2.99.1", "jasmine-core": "~2.99.1",
"jasmine-spec-reporter": "~4.2.1", "jasmine-spec-reporter": "~4.2.1",
"karma": "^4.4.1", "karma": "^4.4.1",
"karma-chrome-launcher": "~2.2.0", "karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.1", "karma-coverage-istanbul-reporter": "^2.1.1",
"karma-jasmine": "~1.1.2", "karma-jasmine": "~1.1.2",
"karma-jasmine-html-reporter": "^0.2.2", "karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.4.0", "protractor": "^5.4.2",
"ts-node": "~7.0.0", "ts-node": "~7.0.0",
"tslint": "^5.11.0", "tslint": "^5.20.1",
"typescript": "~3.5.0" "typescript": "~3.5.0"
} }
} }

@ -12,31 +12,12 @@ export class AppComponent implements OnInit {
constructor(private data: DatasharingService, private selfservice: SelfService) { } constructor(private data: DatasharingService, private selfservice: SelfService) { }
userInfo: User;
loggedIn = false;
userID: number;
username: string;
handle: string;
email: string;
points: number;
level: number;
friendIDs: number[];
groupIDs: number[];
chatIDs: number[];
requestIDs: number[];
ngOnInit() { ngOnInit() {
this.data.currentUserInfo.subscribe(user => { this.data.currentUserInfo.subscribe(user => {
this.userInfo = user; if (user.loggedIn !== true) {
console.log(this.userInfo);
this.data.changeChatIDs(user.chatIDs);
});
if (this.loggedIn !== true) {
this.selfservice.checkIfLoggedIn(); this.selfservice.checkIfLoggedIn();
} }
});
} }
} }

@ -10,19 +10,21 @@ import { DocumentListComponent } from './components/document-list/document-list.
import { DocumentComponent } from './components/document/document.component'; import { DocumentComponent } from './components/document/document.component';
import { RegisterComponent } from './components/register/register.component'; import { RegisterComponent } from './components/register/register.component';
import { LoginComponent } from './components/login/login.component'; import { LoginComponent } from './components/login/login.component';
import { AppScaffoldComponent } from './components/app-scaffold/app-scaffold.component';
import { ChatComponent } from './components/chat/chat.component'; import { ChatComponent } from './components/chat/chat.component';
import { FriendsComponent } from './components/social/friends/friends.component'; import { FriendsComponent } from './components/social/friends/friends.component';
import { FeedComponent } from './components/feed/feed.component'; import { FeedComponent } from './components/feed/feed.component';
import { HomeComponent } from './components/home/home.component'; import { HomeComponent } from './components/home/home.component';
import { SocialComponent } from './components/social/social.component'; import { SocialComponent } from './components/social/social.component';
import { GroupsComponent } from './components/social/groups/groups.component'; import { GroupsComponent } from './components/social/groups/groups.component';
import { DialogCreateGroupComponent } from './components/social/groups/groups.component';
import { DialogCreateEventComponent } from './components/group/group.component';
import { ChatmanagerComponent } from './components/chatmanager/chatmanager.component'; import { ChatmanagerComponent } from './components/chatmanager/chatmanager.component';
import { ChatlistComponent } from './components/chatlist/chatlist.component'; import { ChatlistComponent } from './components/chatlist/chatlist.component';
import { PostlistComponent } from './components/feed/postlist/postlist.component'; import { PostlistComponent } from './components/feed/postlist/postlist.component';
import { GraphQLModule } from './graphql.module'; import { GraphQLModule } from './graphql.module';
import { HttpClientModule } from '@angular/common/http'; import { HttpClientModule } from '@angular/common/http';
import { ProfileComponent } from './components/profile/profile.component'; import { ProfileComponent } from './components/profile/profile.component';
import { GroupComponent } from './components/group/group.component';
import { ImprintComponent } from './components/imprint/imprint.component'; import { ImprintComponent } from './components/imprint/imprint.component';
import { AboutComponent } from './components/about/about.component'; import { AboutComponent } from './components/about/about.component';
import { ChatcontactsComponent } from './components/chatmanager/chatcontacts/chatcontacts.component'; import { ChatcontactsComponent } from './components/chatmanager/chatcontacts/chatcontacts.component';
@ -45,6 +47,8 @@ import { OverlayModule} from '@angular/cdk/overlay';
import {MatSlideToggleModule} from '@angular/material/slide-toggle'; import {MatSlideToggleModule} from '@angular/material/slide-toggle';
import {MatMenuModule} from '@angular/material/menu'; import {MatMenuModule} from '@angular/material/menu';
import {MatRippleModule} from '@angular/material/core'; import {MatRippleModule} from '@angular/material/core';
import {MatBadgeModule} from '@angular/material/badge';
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
import { FlexLayoutModule } from '@angular/flex-layout'; import { FlexLayoutModule } from '@angular/flex-layout';
import { MainNavigationComponent } from './components/main-navigation/main-navigation.component'; import { MainNavigationComponent } from './components/main-navigation/main-navigation.component';
@ -52,6 +56,17 @@ import { LayoutModule } from '@angular/cdk/layout';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatListModule } from '@angular/material/list'; import { MatListModule } from '@angular/material/list';
import {MatSortModule} from '@angular/material/sort'; import {MatSortModule} from '@angular/material/sort';
import { SearchComponent } from './components/search/search.component';
import {DomSanitizer} from '@angular/platform-browser';
import {MatIconRegistry} from '@angular/material/icon';
import {MatDialogModule} from '@angular/material/dialog';
import {MatTooltipModule} from '@angular/material/tooltip';
import {MatExpansionModule} from '@angular/material/expansion';
import {MatDatepickerModule} from '@angular/material/datepicker';
import {MatNativeDateModule} from '@angular/material/';
// import logo from 'src/assets/gv-new-logo.svg';
import logo from '!!raw-loader!./gv-new-logo-white.svg';
const config: SocketIoConfig = { url: 'http://localhost:4444', options: {} }; const config: SocketIoConfig = { url: 'http://localhost:4444', options: {} };
@ -59,6 +74,7 @@ const config: SocketIoConfig = { url: 'http://localhost:4444', options: {} };
const appRoutes: Routes = [ const appRoutes: Routes = [
{ path: '', component: HomeComponent }, { path: '', component: HomeComponent },
{ path: 'profile/:id', component: ProfileComponent }, { path: 'profile/:id', component: ProfileComponent },
{ path: 'group/:id', component: GroupComponent },
{ path: 'login', component: LoginComponent }, { path: 'login', component: LoginComponent },
{ path: 'register', component: RegisterComponent }, { path: 'register', component: RegisterComponent },
{ path: 'about', component: AboutComponent }, { path: 'about', component: AboutComponent },
@ -72,7 +88,6 @@ const appRoutes: Routes = [
DocumentComponent, DocumentComponent,
RegisterComponent, RegisterComponent,
LoginComponent, LoginComponent,
AppScaffoldComponent,
ChatComponent, ChatComponent,
FriendsComponent, FriendsComponent,
FeedComponent, FeedComponent,
@ -86,7 +101,11 @@ const appRoutes: Routes = [
ImprintComponent, ImprintComponent,
AboutComponent, AboutComponent,
ProfileComponent, ProfileComponent,
MainNavigationComponent MainNavigationComponent,
SearchComponent,
DialogCreateGroupComponent,
GroupComponent,
DialogCreateEventComponent
], ],
imports: [ imports: [
BrowserModule, BrowserModule,
@ -95,6 +114,8 @@ const appRoutes: Routes = [
SocketIoModule.forRoot(config), SocketIoModule.forRoot(config),
GraphQLModule, GraphQLModule,
HttpClientModule, HttpClientModule,
MatDatepickerModule,
MatNativeDateModule,
RouterModule.forRoot( RouterModule.forRoot(
appRoutes appRoutes
), ),
@ -120,9 +141,21 @@ const appRoutes: Routes = [
MatMenuModule, MatMenuModule,
MatRippleModule, MatRippleModule,
MatTableModule, MatTableModule,
MatSortModule MatSortModule,
MatBadgeModule,
MatProgressSpinnerModule,
MatDialogModule,
MatTooltipModule,
MatExpansionModule,
MatDatepickerModule
], ],
entryComponents: [ DialogCreateGroupComponent, DialogCreateEventComponent ],
providers: [], providers: [],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })
export class AppModule { } export class AppModule {
constructor(iconRegistry: MatIconRegistry, sanitizer: DomSanitizer) {
iconRegistry.addSvgIconLiteral(
'logo', sanitizer.bypassSecurityTrustHtml(logo));
}
}

@ -1,3 +1,4 @@
<div id="about">
<div id="text0" style="text-align: center;"> <div id="text0" style="text-align: center;">
<h1>Greenvironment</h1> <h1>Greenvironment</h1>
<br> <br> <br> <br> <br> <br> <br> <br> <br> <br>
@ -8,7 +9,7 @@
</div> </div>
<div id="text1" style="text-align: center;"> <div id="text1" style="text-align: center;">
<h1>What's Greenvironment?</h1> <h1>What's Greenvironment?</h1>
<p class="mat-display-1">We, the greenviroment team want to create a netwok for environmentalists who care for our nature and our planet as much as we do.</p> <p class="mat-display-1">We, the greenviroment team want to create a network for environmentalists who care for our nature and our planet as much as we do.</p>
</div> </div>
<div id="text2" style="text-align: center;"> <div id="text2" style="text-align: center;">
<p class="mat-display-1">We believe, that together we can do amazing things to protect our environment and keep it clean and green.</p> <p class="mat-display-1">We believe, that together we can do amazing things to protect our environment and keep it clean and green.</p>
@ -17,3 +18,4 @@
<br> <br>
<a mat-raised-button class="link-button" routerLink="/login">Login</a> <a mat-raised-button class="link-button" routerLink="/login">Login</a>
</div> </div>
</div>

@ -3,6 +3,12 @@
@import '~@angular/material/theming' @import '~@angular/material/theming'
@import '../../../styles/greenvironment-material-theme.scss' @import '../../../styles/greenvironment-material-theme.scss'
#about
position: fixed
width: 100%
height: calc(100% - 56px)
overflow: scroll
#text0, #text2 #text0, #text2
padding: 2em padding: 2em
max-width: 100% max-width: 100%

@ -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,4 +1,4 @@
<div id="chat"> <!--<div id="chat">
<div id='header'> <div id='header'>
<button id="goback" (click)="goBack()"><span><i class="fa fa-arrow-left fa-3x" aria-hidden="true"></i></span></button> <button id="goback" (click)="goBack()"><span><i class="fa fa-arrow-left fa-3x" aria-hidden="true"></i></span></button>
<span class='title'>{{childChat.memberName}}</span> <span class='title'>{{childChat.memberName}}</span>
@ -13,4 +13,4 @@
<textarea #content id='input' placeholder="Write message here ..." rows='3' wrap="soft"></textarea> <textarea #content id='input' placeholder="Write message here ..." rows='3' wrap="soft"></textarea>
<button id="send" type='submit' (click)="sendMessage(content)"><span><i class="fa fa-send-o fa-2x" aria-hidden="true"></i></span></button> <button id="send" type='submit' (click)="sendMessage(content)"><span><i class="fa fa-send-o fa-2x" aria-hidden="true"></i></span></button>
</div> </div>
</div> </div>-->

@ -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

@ -1,4 +1,4 @@
<div *ngIf="showChatlist"> <!--<div *ngIf="showChatlist">
<chatmanager-chatlist (showChatEvent)="showSpecialChat($event)" (showCreateChatEvent)="showNewChat($event)" [childChats]="parentChats"></chatmanager-chatlist> <chatmanager-chatlist (showChatEvent)="showSpecialChat($event)" (showCreateChatEvent)="showNewChat($event)" [childChats]="parentChats"></chatmanager-chatlist>
</div> </div>
<div *ngIf="showChat"> <div *ngIf="showChat">
@ -6,4 +6,4 @@
</div> </div>
<div *ngIf="showCreateNewChat"> <div *ngIf="showCreateNewChat">
<chatmanager-chatcontacts (goBackEvent)="goBackToChatlist($event)"></chatmanager-chatcontacts> <chatmanager-chatcontacts (goBackEvent)="goBackToChatlist($event)"></chatmanager-chatcontacts>
</div> </div>-->

@ -1,13 +1,9 @@
<!--<div id="postinput">
<textarea #content id='input' placeholder="Post something ..." rows='3' wrap="soft"></textarea>
<button id="attach" type='submit'><span><i class="fa fa-paperclip fa-2x" aria-hidden="true"></i></span></button>
<button id="submit" type='submit' (click)=createPost(content)><span><i class="fa fa-send-o fa-2x" aria-hidden="true"></i></span></button>
</div>-->
<div id="home"> <div id="home">
<mat-card > <div [hidden]="!loggedIn">
<mat-card >
<mat-card-content> <mat-card-content>
<mat-form-field id="input"> <mat-form-field id="input">
<textarea matInput #content type="text" mat-autosize="true" matAutosizeMaxRows="3" placeholder="post something"></textarea> <textarea matInput #content type="text" [(ngModel)]="empty" mat-autosize="true" matAutosizeMaxRows="3" placeholder="post something"></textarea>
<button mat-button matSuffix mat-icon-button> <button mat-button matSuffix mat-icon-button>
<mat-icon>add</mat-icon> <mat-icon>add</mat-icon>
</button> </button>
@ -24,11 +20,22 @@
</mat-option> </mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<button mat-raised-button color="primary" id="post-button" (click)=createPost(content)> <button mat-raised-button *ngIf="empty" color="primary" id="post-button" (click)=createPost(content)>
POST POST
</button> </button>
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>
</div>
<div [hidden]="loggedIn">
<mat-card id="info">
<mat-card-header>
<mat-card-title >
You need to <a routerLink="/login" class="primary-color">login</a> to post something.
</mat-card-title>
</mat-card-header>
</mat-card>
</div>
<div id="chooser-div" style="text-align: center; margin-top: 1em;"> <div id="chooser-div" style="text-align: center; margin-top: 1em;">
<mat-button-toggle-group id="feedchooser" value="new"> <mat-button-toggle-group id="feedchooser" value="new">
<mat-button-toggle (click)="showNew()" value="new">New</mat-button-toggle> <mat-button-toggle (click)="showNew()" value="new">New</mat-button-toggle>
@ -36,10 +43,6 @@
</mat-button-toggle-group> </mat-button-toggle-group>
</div> </div>
<div id="complete-feed"> <div id="complete-feed">
<!--<div id='feedchooser'>
<button id="new" (click)="showNew()">New</button>
<button id='mostliked' (click)="showMostLiked()">Most Liked</button>
</div>-->
<div id="feedlist"> <div id="feedlist">
<div *ngIf = "viewNew"> <div *ngIf = "viewNew">
<feed-postlist (voteEvent)="refresh($event)" [childPostList]="parentSelectedPostList"></feed-postlist> <feed-postlist (voteEvent)="refresh($event)" [childPostList]="parentSelectedPostList"></feed-postlist>
@ -47,6 +50,7 @@
<div *ngIf = "viewMostLiked"> <div *ngIf = "viewMostLiked">
<feed-postlist (voteEvent)="refresh($event)" [childPostList]="parentSelectedPostList"></feed-postlist> <feed-postlist (voteEvent)="refresh($event)" [childPostList]="parentSelectedPostList"></feed-postlist>
</div> </div>
<mat-spinner *ngIf="loading" style="margin:0 auto; margin-top: 5em;" diameter="50"></mat-spinner>
</div> </div>
</div> </div>
</div> </div>

@ -1,6 +1,10 @@
@import '../../../styles/mixins.sass' @import '../../../styles/mixins.sass'
@import '../../../styles/vars.sass' @import '../../../styles/vars.sass'
.primary-color
color: $primary-color
#home #home
width: 100% width: 100%
height: 100% height: 100%
@ -10,6 +14,9 @@
display: flex display: flex
width: 100% width: 100%
padding: 0.5em padding: 0.5em
#info
::ng-deep .mat-card-header-text
margin: 0px
#feedlist #feedlist
width: 100% width: 100%

@ -11,7 +11,9 @@ import { User } from 'src/app/models/user';
styleUrls: ['./feed.component.sass'] styleUrls: ['./feed.component.sass']
}) })
export class FeedComponent implements OnInit { export class FeedComponent implements OnInit {
loading = true;
checked: boolean; // if the "I protected the environment."-box is checked checked: boolean; // if the "I protected the environment."-box is checked
empty: boolean;
// points value of the green action // points value of the green action
value: any; value: any;
viewNew = true; viewNew = true;
@ -34,15 +36,14 @@ export class FeedComponent implements OnInit {
this.data.currentUserInfo.subscribe(user => { this.data.currentUserInfo.subscribe(user => {
this.user = user; this.user = user;
this.loggedIn = user.loggedIn; this.loggedIn = user.loggedIn;
if (this.loggedIn) { this.userId = user.userID; } this.feedService.getAllPostsRaw().subscribe(response => {
console.log('the userId is ' + this.userId); this.loading = false;
});
this.feedService.getAllPostsRawByUserId(this.userId).subscribe(response => {
this.feedNew = this.feedService.renderAllPosts(response.json()); this.feedNew = this.feedService.renderAllPosts(response.json());
this.parentSelectedPostList = this.feedNew; this.parentSelectedPostList = this.feedNew;
this.feedMostLiked = this.feedNew; this.feedMostLiked = this.feedNew;
console.log(this.feedNew);
}); });
});
} }
createPost(pElement) { createPost(pElement) {
@ -55,8 +56,7 @@ export class FeedComponent implements OnInit {
} }
showNew() { showNew() {
console.log('showNew()'); this.feedService.getAllPostsRaw().subscribe(response => {
this.feedService.getAllPostsRawByUserId(this.userId).subscribe(response => {
this.feedNew = this.feedService.renderAllPosts(response.json()); this.feedNew = this.feedService.renderAllPosts(response.json());
this.parentSelectedPostList = this.feedNew; }); this.parentSelectedPostList = this.feedNew; });
this.viewNew = true; this.viewNew = true;
@ -64,8 +64,7 @@ export class FeedComponent implements OnInit {
} }
showMostLiked() { showMostLiked() {
console.log('showMostLiked()'); this.feedService.getAllPostsRaw().subscribe(response => {
this.feedService.getAllPostsRawByUserId(this.userId).subscribe(response => {
this.feedMostLiked = this.feedService.renderAllPosts(response.json()); this.feedMostLiked = this.feedService.renderAllPosts(response.json());
this.parentSelectedPostList = this.feedMostLiked; }); this.parentSelectedPostList = this.feedMostLiked; });
this.viewNew = false; this.viewNew = false;
@ -74,9 +73,8 @@ export class FeedComponent implements OnInit {
refresh($event) { refresh($event) {
this.feedService.getAllPostsRawByUserId(this.userId).subscribe(response => { this.feedService.getAllPostsRaw().subscribe(response => {
this.parentSelectedPostList = this.feedService.renderAllPosts(response.json()); this.parentSelectedPostList = this.feedService.renderAllPosts(response.json());
console.log('Refresh');
}); });
} }

@ -21,10 +21,21 @@
<mat-card class="post" *ngFor = "let post of childPostList" [class.selected]="post === selectedPost" tabindex="0"> <mat-card class="post" *ngFor = "let post of childPostList" [class.selected]="post === selectedPost" tabindex="0">
<mat-card-header> <mat-card-header>
<div id="button-box">
<button mat-icon-button [matMenuTriggerFor]="menu" id="menu-button" *ngIf="post.deletable">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="deletePost(post)">
<span>delete post</span>
</button>
</mat-menu>
</div>
<!-- <div mat-card-avatar class="example-header-image"></div> --> <!-- <div mat-card-avatar class="example-header-image"></div> -->
<mat-card-title> <mat-card-title>
{{post.author.name}} {{post.author.name}}
<a class="mat-card-subtitle" routerLink="/profile/{{post.author.id}}">@{{post.author.handle}}</a> <!--<a class="mat-card-subtitle" routerLink="/profile/{{post.author.id}}">@{{post.author.handle}}</a>-->
<a class="mat-card-subtitle" (click)="showUserProfile(this.post)">@{{post.author.handle}}</a>
<p class="mat-card-subtitle">&nbsp; {{post.date}}</p> <p class="mat-card-subtitle">&nbsp; {{post.date}}</p>
</mat-card-title> </mat-card-title>
<mat-card-subtitle> <mat-card-subtitle>
@ -35,15 +46,16 @@
<p [innerHTML]="post.htmlContent"></p> <p [innerHTML]="post.htmlContent"></p>
</mat-card-content> </mat-card-content>
<mat-card-actions> <mat-card-actions>
<button mat-button (click)="voteUp(post)"> <button mat-button (click)="voteUp(post)" matTooltip="vote up" matTooltipShowDelay="500">
<mat-icon aria-hidden="false" color="primary" *ngIf="post.userVote == 'UPVOTE'">keyboard_arrow_up</mat-icon> <mat-icon aria-hidden="false" color="primary" *ngIf="post.userVote == 'UPVOTE'">keyboard_arrow_up</mat-icon>
<mat-icon aria-hidden="false" *ngIf="!post.userVote || post.userVote == 'DOWNVOTE'">keyboard_arrow_up</mat-icon> <mat-icon aria-hidden="false" *ngIf="!post.userVote || post.userVote == 'DOWNVOTE'">keyboard_arrow_up</mat-icon>
</button> </button>
{{post.upvotes}} {{post.upvotes}}
<button mat-button (click)="voteDown(post)"> <button mat-button (click)="voteDown(post)" matTooltip="vote down" matTooltipShowDelay="500">
<mat-icon aria-hidden="false" color="primary" *ngIf="post.userVote == 'DOWNVOTE'">keyboard_arrow_down</mat-icon> <mat-icon aria-hidden="false" color="primary" *ngIf="post.userVote == 'DOWNVOTE'">keyboard_arrow_down</mat-icon>
<mat-icon aria-hidden="false" *ngIf="!post.userVote || post.userVote == 'UPVOTE'">keyboard_arrow_down</mat-icon> <mat-icon aria-hidden="false" *ngIf="!post.userVote || post.userVote == 'UPVOTE'">keyboard_arrow_down</mat-icon>
</button> </button>
{{post.downvotes}} {{post.downvotes}}
</mat-card-actions> </mat-card-actions>
</mat-card> </mat-card>

@ -5,11 +5,20 @@
box-sizing: border-box box-sizing: border-box
width: 100% width: 100%
margin-top: 0.5em margin-top: 0.5em
outline: none
user-select: none
::ng-deep .mat-card-header-text ::ng-deep .mat-card-header-text
margin: 0px margin: 0px
.mat-card-header
.mat-card-subtitle .mat-card-subtitle
display: contents display: contents
a:hover
cursor: pointer
#button-box
text-align: right
margin-left: auto
::ng-deep img
max-width: 100%
height: auto
border-radius: 4px

@ -1,6 +1,7 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { Post } from 'src/app/models/post'; import { Post } from 'src/app/models/post';
import { FeedService } from 'src/app/services/feed/feed.service'; import { FeedService } from 'src/app/services/feed/feed.service';
import { Router } from '@angular/router';
@Component({ @Component({
selector: 'feed-postlist', selector: 'feed-postlist',
@ -13,19 +14,41 @@ export class PostlistComponent implements OnInit {
@Output() voteEvent = new EventEmitter<boolean>(); @Output() voteEvent = new EventEmitter<boolean>();
selectedPost: Post; selectedPost: Post;
constructor(private feedService: FeedService) { } constructor(private feedService: FeedService, private router: Router) { }
ngOnInit() { ngOnInit() {
} }
voteUp(pPost: Post) { voteUp(pPost: Post) {
this.feedService.upvote(pPost.id).subscribe(response => { this.feedService.upvote(pPost.id).subscribe(response => {
this.voteEvent.emit(true); }); // this.voteEvent.emit(true);
pPost.userVote = response.json().data.vote.post.userVote;
pPost.upvotes = response.json().data.vote.post.upvotes;
pPost.downvotes = response.json().data.vote.post.downvotes;
});
} }
voteDown(pPost: Post) { voteDown(pPost: Post) {
this.feedService.downvote(pPost.id).subscribe(response => { this.feedService.downvote(pPost.id).subscribe(response => {
this.voteEvent.emit(true); }); // this.voteEvent.emit(true);
pPost.userVote = response.json().data.vote.post.userVote;
pPost.upvotes = response.json().data.vote.post.upvotes;
pPost.downvotes = response.json().data.vote.post.downvotes;
});
} }
deletePost(pPost: Post) {
this.feedService.deletePost(pPost.id).subscribe(response => {
for (let i = 0; i < this.childPostList.length; i++) {
if (this.childPostList[i].id === pPost.id) {
this.childPostList.splice(i, 1);
return;
}
}
});
}
public showUserProfile(post: any) {
this.router.navigate(['profile/' + post.author.id]);
}
} }

@ -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,7 +1,8 @@
<div id="content" fxShow="true" fxHide.lt-md="true"> <div id="content" fxShow="true" fxHide.lt-md="true">
<div id="chat"><home-chatmanager id="chatcontainer" [hidden]="!loggedIn"></home-chatmanager></div> <div id="chat"><home-chatmanager [hidden]="!loggedIn"></home-chatmanager></div>
<div id="feed"><home-feed id="feedcontainer"></home-feed></div> <div id="feed"><home-feed></home-feed></div>
<div id="social"><home-social id="socialcontainer" [hidden]="!loggedIn"></home-social></div> <div class="social" [hidden]="!loggedIn"><home-social></home-social></div>
<div class="social" [hidden]="loggedIn"><home-search></home-search></div>
</div> </div>
<!-- <!--
<mat-tab-group headerPosition="below" position="0" id="bottom-menu" fxShow="true" fxHide.gt-sm="true"> <mat-tab-group headerPosition="below" position="0" id="bottom-menu" fxShow="true" fxHide.gt-sm="true">
@ -12,7 +13,7 @@
--> -->
<div class="bottom-menu" fxShow="true" fxHide.gt-sm="true"> <div class="bottom-menu" fxShow="true" fxHide.gt-sm="true">
<mat-tab-group id="tab-group" selectedIndex="1" mat-stretch-tabs headerPosition="below"> <mat-tab-group id="tab-group" selectedIndex="1" mat-stretch-tabs headerPosition="below">
<mat-tab> <mat-tab disabled>
<ng-template mat-tab-label> <ng-template mat-tab-label>
<mat-icon>chat</mat-icon> <mat-icon>chat</mat-icon>
</ng-template> </ng-template>
@ -24,12 +25,18 @@
</ng-template> </ng-template>
<home-feed class="tab-content"></home-feed> <home-feed class="tab-content"></home-feed>
</mat-tab> </mat-tab>
<mat-tab > <mat-tab [disabled]="!loggedIn">
<ng-template mat-tab-label> <ng-template mat-tab-label>
<mat-icon>people</mat-icon> <mat-icon>people</mat-icon>
</ng-template> </ng-template>
<home-social class="tab-content"></home-social> <home-social class="tab-content"></home-social>
</mat-tab> </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> </mat-tab-group>
</div> </div>

@ -20,19 +20,13 @@
float: left float: left
overflow-y: auto overflow-y: auto
#social .social
box-sizing: content-box box-sizing: content-box
height: 100% height: 100%
width: 25% width: 25%
float: left float: left
overflow-y: auto overflow-y: auto
.mat-toolbar.mat-primary
width: 100%
position: sticky
top: 0
z-index: 1
/deep/ .mat-tab-body-wrapper /deep/ .mat-tab-body-wrapper
height: 100% height: 100%
@ -45,8 +39,9 @@
height: 100% height: 100%
.tab-content .tab-content
height: 50% box-sizing: content-box
width: 100% width: 100%

@ -26,20 +26,15 @@ export class LoginComponent implements OnInit {
} }
public loginError(error: any) { public loginError(error: any) {
console.log(error.errors[0].message);
this.errorOccurred = true; this.errorOccurred = true;
this.errorMessage = error.errors[0].message; this.errorMessage = error.errors[0].message;
} }
onClickSubmit(pEmail: string, pPasswordHash: string) { onClickSubmit(pEmail: string, pPasswordHash: string) {
console.log('try to login with mail adress:' + pEmail);
this.errorOccurred = false; this.errorOccurred = false;
this.errorMessage = ' '; this.errorMessage = ' ';
this.login.email = pEmail.trim(); this.login.email = pEmail.trim().toLowerCase();
this.login.passwordHash = sha512.sha512(pPasswordHash); this.login.passwordHash = sha512.sha512(pPasswordHash);
console.log(this.login.passwordHash);
console.log(this.login.passwordHash);
this.loginService.login(this.login, error => this.loginError(error.json())); this.loginService.login(this.login, error => this.loginError(error.json()));
} }

@ -1,11 +1,16 @@
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet"> <!-- getting the google material fonts -->
<mat-sidenav-container class="sidenav-container" class="mat-typography"> <meta name="viewport" content="width=device-width,height=device-height,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0"> <!-- diables zoom -->
<mat-sidenav-container class="mat-typography">
<!-- SIDENAV -->
<mat-sidenav #drawer class="sidenav" <mat-sidenav #drawer class="sidenav"
fxShow="true" fxHide.gt-sm="true" fxShow="true" fxHide.gt-sm="true"
fixedInViewport="false" fixedInViewport="false"
autoFocus="false" autoFocus="false">
> <mat-toolbar *ngIf="!loggedIn">Menu</mat-toolbar>
<mat-toolbar>Menu</mat-toolbar> <mat-toolbar *ngIf="loggedIn">
<span>Hello, {{user.username}}</span>
</mat-toolbar>
<mat-nav-list> <mat-nav-list>
<a mat-list-item routerLink="" (click)="drawer.close()">Home</a> <a mat-list-item routerLink="" (click)="drawer.close()">Home</a>
<a mat-list-item *ngIf="loggedIn" routerLink={{profileUrl}} (click)="drawer.close()">Profile</a> <a mat-list-item *ngIf="loggedIn" routerLink={{profileUrl}} (click)="drawer.close()">Profile</a>
@ -19,8 +24,12 @@
</div> </div>
</mat-nav-list> </mat-nav-list>
</mat-sidenav> </mat-sidenav>
<!-- TOOLBAR -->
<mat-sidenav-content> <mat-sidenav-content>
<mat-toolbar color="primary" class="mat-elevation-z4"> <mat-toolbar color="primary" class="mat-elevation-z4">
<!--content on SMALL SCREEN-->
<button <button
type="button" type="button"
aria-label="Toggle sidenav" aria-label="Toggle sidenav"
@ -29,9 +38,9 @@
fxShow="true" fxHide.gt-sm="true"> fxShow="true" fxHide.gt-sm="true">
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon> <mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
</button> </button>
<span>Greenvironment</span> <mat-icon svgIcon="logo" style="min-width: 35px;" routerLink="" class="link"></mat-icon>
<!--The following menu items will be hidden on both SM and XS screen sizes --> <span routerLink="" class="link">Greenvironment</span>
<nav mat-tab-nav-bar backgroundColor="primary" fxShow="true" fxHide.lt-md="true"> <nav mat-tab-nav-bar backgroundColor="primary" fxShow="true" fxHide.lt-md="true" routerLinkActive #rla="">
<div [hidden]="!loggedIn"> <div [hidden]="!loggedIn">
<a mat-tab-link class="link" <a mat-tab-link class="link"
*ngFor="let link of navLinksLoggedIn" *ngFor="let link of navLinksLoggedIn"
@ -55,17 +64,40 @@
</a> </a>
</div> </div>
</nav> </nav>
<!--content on BIG SCREEN-->
<div id="menu-button-box"> <div id="menu-button-box">
<span class="mat-button" *ngIf="loggedIn" fxShow="true" fxHide.lt-md="true" routerLink={{profileUrl}}>Hello, {{user.username}}</span>
<span class="mat-button" *ngIf="!loggedIn" fxShow="true" fxHide.lt-md="true" routerLink="/login"><span>Hello, Sign in</span></span>
<button mat-icon-button [matMenuTriggerFor]="requestMenu" [disabled]="!loggedIn" id="menu-button">
<mat-icon [matBadge]="user.receivedRequests.length" [matBadgeHidden]="!(user.receivedRequests.length > 0)" matBadgeColor="accent">notifications</mat-icon>
</button>
<button mat-icon-button [matMenuTriggerFor]="menu" id="menu-button"> <button mat-icon-button [matMenuTriggerFor]="menu" id="menu-button">
<mat-icon>more_vert</mat-icon> <mat-icon>more_vert</mat-icon>
</button> </button>
</div> </div>
<mat-menu #requestMenu="matMenu">
<span mat-menu-item disableRipple="true" disabled="true">friend requests:</span>
<button mat-menu-item *ngFor = "let request of user.receivedRequests" [class.selected]="request === selectedRequest" (click)="$event.stopPropagation();" disableRipple="true">
<button mat-icon-button (click)=acceptRequest(request.senderUserID) (click)="$event.stopPropagation();">
<mat-icon>check</mat-icon>
</button>
<button mat-icon-button (click)=denyRequest(request.senderUserID) (click)="$event.stopPropagation();">
<mat-icon>close</mat-icon>
</button>
<span>{{request.senderUsername}}</span>
<span>&nbsp; @{{request.senderHandle}}</span>
</button>
</mat-menu>
<mat-menu #menu="matMenu"> <mat-menu #menu="matMenu">
<button mat-menu-item (click)="$event.stopPropagation();"> <button mat-menu-item (click)="$event.stopPropagation();">
<mat-slide-toggle <mat-slide-toggle
color="primary" color="primary"
class="theme-button" class="theme-button"
(change)="toggleTheme()"><!--stays white when dragged--> (change)="toggleTheme()"
[checked]="darkModeButtonChecked">
dark mode dark mode
</mat-slide-toggle> </mat-slide-toggle>
</button> </button>
@ -75,7 +107,14 @@
<span>log out</span> <span>log out</span>
</button> </button>
</div> </div>
<div [hidden]="loggedIn">
<button mat-menu-item routerLink="/login">
<mat-icon>exit_to_app</mat-icon>
<span>login</span>
</button>
</div>
</mat-menu> </mat-menu>
</mat-toolbar> </mat-toolbar>
<router-outlet></router-outlet> <router-outlet></router-outlet>
</mat-sidenav-content> </mat-sidenav-content>

@ -1,31 +1,33 @@
.sidenav-container
height: 100%
.mat-sidenav-container .mat-sidenav-container
height: 100%
.mat-sidenav-content
height: 100vh height: 100vh
.sidenav .sidenav
width: 200px width: 200px
.link
user-select: none
cursor: pointer
outline: none
.sidenav .mat-toolbar .sidenav .mat-toolbar
background: inherit //background: inherit
.mat-toolbar.mat-primary .mat-toolbar.mat-primary
height: 56px height: 56px
position: sticky position: fixed
//position: sticky
top: 0 top: 0
z-index: 1000 z-index: 999
.mat-tab-nav-bar .mat-tab-nav-bar
width: 70%
height: 56px height: 56px
.mat-tab-links .mat-tab-links
height: 56px height: 56px
.mat-tab-link .mat-tab-link
height: 56px height: 56px
.mat-sidenav-content
padding-top: 56px
#link-box #link-box
padding: 0.5em padding: 0.5em
@ -37,13 +39,7 @@
/deep/ .mat-tab-link /deep/ .mat-tab-link
min-width: 5em!important min-width: 5em!important
#login-button
#menu-button-box #menu-button-box
text-align: right text-align: right
width: 100% width: 100%

@ -1,9 +1,8 @@
import { Component, OnInit, HostBinding } from '@angular/core'; import { Component, OnInit, HostBinding } from '@angular/core';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout'; import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { Observable } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators';
import { DatasharingService } from '../../services/datasharing.service'; import { DatasharingService } from '../../services/datasharing.service';
import { SelfService } from '../../services/selfservice/self.service'; import { RequestService } from '../../services/request/request.service';
import { SettingsService } from '../../services/settings/settings.service';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { Levellist } from 'src/app/models/levellist'; import { Levellist } from 'src/app/models/levellist';
import { Http } from '@angular/http'; import { Http } from '@angular/http';
@ -21,9 +20,10 @@ export class MainNavigationComponent implements OnInit {
constructor( constructor(
public overlayContainer: OverlayContainer, public overlayContainer: OverlayContainer,
private data: DatasharingService, private data: DatasharingService,
private selfservice: SelfService, private settingsService: SettingsService,
private requestservice: RequestService,
private breakpointObserver: BreakpointObserver, private breakpointObserver: BreakpointObserver,
private http: Http, private router: Router private http: Http, private router: Router,
) { ) {
this.overlay = overlayContainer.getContainerElement(); this.overlay = overlayContainer.getContainerElement();
} }
@ -36,14 +36,10 @@ export class MainNavigationComponent implements OnInit {
points: number; points: number;
profileUrl = '/profile/1'; profileUrl = '/profile/1';
darkModeButtonChecked = false;
lighttheme = true; lighttheme = true;
overlay; overlay;
isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset)
.pipe(
map(result => result.matches),
shareReplay()
);
navLinksLoggedIn = [ navLinksLoggedIn = [
{ path: '', label: 'Home' }, { path: '', label: 'Home' },
{ path: this.profileUrl, label: 'Profile' }, { path: this.profileUrl, label: 'Profile' },
@ -54,7 +50,6 @@ export class MainNavigationComponent implements OnInit {
{ path: '', label: 'Home' }, { path: '', label: 'Home' },
{ path: '/about', label: 'About' }, { path: '/about', label: 'About' },
{ path: '/imprint', label: 'Imprint' }, { path: '/imprint', label: 'Imprint' },
{ path: '/login', label: 'Login' },
]; ];
@HostBinding('class') componentCssClass; @HostBinding('class') componentCssClass;
@ -67,6 +62,13 @@ export class MainNavigationComponent implements OnInit {
this.level = this.levellist.getLevelName(user.level); this.level = this.levellist.getLevelName(user.level);
this.points = user.points; this.points = user.points;
this.profileUrl = '/profile/' + this.userId; this.profileUrl = '/profile/' + this.userId;
if (this.user.darkmode === true && this.lighttheme) {
this.toggleTheme();
this.darkModeButtonChecked = true;
// IF user activated darkmode and logged in after that
} else if (this.user.loggedIn && !this.user.darkmode && !this.lighttheme) {
this.settingsService.setDarkModeActive(true);
}
this.updateLinks(); this.updateLinks();
}); });
} }
@ -76,15 +78,22 @@ export class MainNavigationComponent implements OnInit {
this.overlay.classList.remove('dark-theme'); this.overlay.classList.remove('dark-theme');
this.overlay.classList.add('light-theme'); this.overlay.classList.add('light-theme');
this.onSetTheme('light-theme'); this.onSetTheme('light-theme');
this.lighttheme = true;
this.settingsService.setDarkModeActive(false);
} else if (this.overlay.classList.contains('light-theme')) { } else if (this.overlay.classList.contains('light-theme')) {
this.overlay.classList.remove('light-theme'); this.overlay.classList.remove('light-theme');
this.overlay.classList.add('dark-theme'); this.overlay.classList.add('dark-theme');
this.onSetTheme('dark-theme'); this.onSetTheme('dark-theme');
this.lighttheme = false;
this.settingsService.setDarkModeActive(true);
} else { } else {
this.overlay.classList.add('dark-theme'); this.overlay.classList.add('dark-theme');
this.onSetTheme('dark-theme'); this.onSetTheme('dark-theme');
this.lighttheme = false;
this.settingsService.setDarkModeActive(true);
} }
} }
updateLinks() { updateLinks() {
this.navLinksLoggedIn = [ this.navLinksLoggedIn = [
{ path: '', label: 'Home' }, { path: '', label: 'Home' },
@ -102,11 +111,9 @@ export class MainNavigationComponent implements OnInit {
const headers = new Headers(); const headers = new Headers();
headers.set('Content-Type', 'application/json'); headers.set('Content-Type', 'application/json');
const body = {query: `mutation { const body = {query: `mutation {
logout logout
}`}; }`};
this.http.post(url, body).subscribe(response => { this.http.post(url, body).subscribe(response => {
console.log(response.text()); }); console.log(response.text()); });
this.loggedIn = false; this.loggedIn = false;
@ -115,4 +122,35 @@ export class MainNavigationComponent implements OnInit {
this.data.changeUserInfo(user); this.data.changeUserInfo(user);
this.router.navigate(['login']); this.router.navigate(['login']);
} }
acceptRequest(id: number) {
console.log('try to accept request from id: ' + id);
const headers = new Headers();
headers.set('Content-Type', 'application/json');
this.http.post(environment.graphQLUrl, this.requestservice.buildJsonAcceptRequest(id))
.subscribe(response => {
console.log(response);
for (let i = 0; i < this.user.receivedRequests.length; i++) {
if (this.user.receivedRequests[i].senderUserID === id) {
this.user.receivedRequests.splice(i, 1);
return;
}
}
});
}
denyRequest(id: number) {
const headers = new Headers();
headers.set('Content-Type', 'application/json');
this.http.post(environment.graphQLUrl, this.requestservice.buildJsonDenyRequest(id))
.subscribe(response => {
console.log(response);
for (let i = 0; i < this.user.receivedRequests.length; i++) {
if (this.user.receivedRequests[i].senderUserID === id) {
this.user.receivedRequests.splice(i, 1);
return;
}
}
});
}
} }

@ -1,48 +1,65 @@
<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>
<td>{{user.level}}</td>
</tr>
<mat-divider></mat-divider>
<tr>
<div class="mat-header-cell">level name: </div>
<td>{{rankname}}</td>
</tr>
</table>
</mat-card-content>
</mat-card>
</div> </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">{{userProfile.username}}</span>
<span id="handle">@{{userProfile.handle}}</span>
<button mat-icon-button
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 id="profile">
<br> <br>
<h1>What does the level mean?</h1> <h1>What does the level mean?</h1>
<p>There are different levels you can reach through green behaviour. <p>There are different levels you can reach through green behaviour.
@ -98,8 +115,11 @@
</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>

@ -1,6 +1,13 @@
@import '../../../styles/mixins.sass' @import '../../../styles/mixins.sass'
@import '../../../styles/vars.sass' @import '../../../styles/vars.sass'
#profile-page
position: fixed
width: 100%
height: calc(100% - 56px)
overflow: scroll
overflow-x: hidden
#profile #profile
padding: 2em padding: 2em
max-width: 1200px max-width: 1200px
@ -10,6 +17,28 @@
margin: 0 auto margin: 0 auto
width: 100% width: 100%
max-width: 690px max-width: 690px
.icon-box
text-align: right
width: 100%
.request-button
margin-top: 0.5em
margin-bottom: 0.5em
margin-left: auto
#toolbar
margin-top: 32px
.mat-toolbar-row
max-height: 40px
.info-box
font-size: 14px
margin-left: calc(100px + 0.5em)
.info
margin-right: 1em
font-size: 14px
#username
margin: 0 0.5em
#handle
font-size: 14px
.mat-table .mat-table
width: 100% width: 100%
@ -18,21 +47,21 @@
.mat-header-cell .mat-header-cell
padding-right: 0.5em padding-right: 0.5em
$mat-card-header-size: 100px !default
.profile-picture .profile-picture
background-image: url(https://material.angular.io/assets/img/examples/shiba1.jpg) 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 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
#profile-table
width: 100% #postlist
.mat-table margin: 0.5em auto
display: block
.mat-cell,
.mat-header-cell
align-items: center
display: flex
min-height: 48px
padding: 0 padding: 0
flex: 1 max-width: 690px
overflow: hidden
word-wrap: break-word

@ -1,12 +1,13 @@
import { Component, OnInit, ViewChild} from '@angular/core'; import { Component, OnInit, ViewChild} from '@angular/core';
import {Router} from '@angular/router'; import {Router, NavigationEnd} from '@angular/router';
import {Http, URLSearchParams, Headers} from '@angular/http';
import { User } from 'src/app/models/user'; import { User } from 'src/app/models/user';
import { Actionlist } from 'src/app/models/actionlist'; import { Actionlist } from 'src/app/models/actionlist';
import { Levellist } from 'src/app/models/levellist'; import { Levellist } from 'src/app/models/levellist';
import { environment } from 'src/environments/environment';
import {MatSort} from '@angular/material/sort'; import {MatSort} from '@angular/material/sort';
import {MatTableDataSource} from '@angular/material/table'; import {MatTableDataSource} from '@angular/material/table';
import { RequestService } from 'src/app/services/request/request.service';
import { DatasharingService } from '../../services/datasharing.service';
import { ProfileService } from 'src/app/services/profile/profile.service';
@Component({ @Component({
selector: 'app-profile', selector: 'app-profile',
@ -18,7 +19,8 @@ export class ProfileComponent implements OnInit {
actionlist: Actionlist = new Actionlist(); actionlist: Actionlist = new Actionlist();
levellist: Levellist = new Levellist(); levellist: Levellist = new Levellist();
user: User = new User(); userProfile: User = new User();
self: User;
id: string; id: string;
rankname: string; rankname: string;
profileNotFound = false; profileNotFound = false;
@ -26,61 +28,48 @@ export class ProfileComponent implements OnInit {
dataSource = new MatTableDataSource(this.actionlist.Actions); dataSource = new MatTableDataSource(this.actionlist.Actions);
displayedLevelColumns = ['level', 'name']; displayedLevelColumns = ['level', 'name'];
levelSource = this.levellist.levels; levelSource = this.levellist.levels;
constructor(private router: Router, private http: Http) { }
@ViewChild(MatSort, {static: true}) sort: MatSort; loading = false;
ngOnInit() {
this.dataSource.sort = this.sort;
this.id = this.router.url.substr(this.router.url.lastIndexOf('/') + 1);
// let url = './graphql'
const url = environment.graphQLUrl;
const headers = new Headers();
headers.set('Content-Type', 'application/json');
return this.http.post(url, this.buildJson(this.id)) constructor(
.subscribe(response => { private router: Router,
console.log(response.text()); private requestService: RequestService,
this.updateUserInfo(response.json()); private data: DatasharingService,
private profileService: ProfileService) {
router.events.forEach((event) => {
// check if the user is on the profile page (of userY) and routes to the page of userY (e.g. his own page)
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('profile/')) {
// reload the user
this.ngOnInit();
} }
);
}
public updateUserInfo(response: any) {
if (response.data.getUser != null) {
this.profileNotFound = false;
this.user.loggedIn = true;
this.user.userID = response.data.getUser.id;
this.user.username = response.data.getUser.name;
this.user.handle = response.data.getUser.handle;
this.user.points = response.data.getUser.points;
this.user.level = response.data.getUser.level;
this.rankname = this.levellist.getLevelName(this.user.level);
this.user.friendIDs = response.data.getUser.friends;
} else {
this.profileNotFound = true;
} }
});
} }
public buildJson(id: string): any { @ViewChild(MatSort, {static: true}) sort: MatSort;
const body = {query: `query($userId: ID) { ngOnInit() {
getUser(userId:$userId){ this.loading = true;
id this.dataSource.sort = this.sort;
handle this.id = this.router.url.substr(this.router.url.lastIndexOf('/') + 1);
name this.data.currentUserInfo.subscribe(user => {
profilePicture this.self = user;
points });
level this.profileService.getUserData(this.id);
friendCount this.profileService.proflile.subscribe(response => {
friends{ if (response) {
id this.userProfile = response;
} // tslint:disable-next-line:max-line-length
posts{ this.userProfile.allowedToSendRequest = this.requestService.isAllowedToSendRequest(this.userProfile.userID, this.self);
content this.rankname = this.levellist.getLevelName(this.userProfile.level);
} } else { this.profileNotFound = true; }
this.loading = false;
});
} }
}`, variables: {
userId: this.id public sendFriendRequest(user: User) {
}}; user.allowedToSendRequest = false;
return body; this.requestService.sendFriendRequest(user);
} }
} }

@ -33,7 +33,7 @@ export class RegisterComponent implements OnInit {
this.errorMessage = ' '; this.errorMessage = ' ';
if (this.passwordSame(pPasswordHash, pPasswordHashRepeat)) { if (this.passwordSame(pPasswordHash, pPasswordHashRepeat)) {
this.registration.username = pUsername.trim(); this.registration.username = pUsername.trim();
this.registration.email = pEmail.trim(); this.registration.email = pEmail.trim().toLowerCase();
this.registration.passwordHash = sha512.sha512(pPasswordHash); this.registration.passwordHash = sha512.sha512(pPasswordHash);
this.registerService.register(this.registration, error => this.registerError(error.json())); this.registerService.register(this.registration, error => this.registerError(error.json()));
} }

@ -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);
}
}

@ -1,16 +1,9 @@
<!--<div id="header"> <mat-toolbar>
<span class="title">Friends</span> <span>Friends</span>
<button id="new" type="submit"><span><i class="fa fa-plus fa-3x" aria-hidden="true"></i></span></button> </mat-toolbar>
<button id="invitations" type="submit"><span><i class="fa fa-envelope-o fa-3x" aria-hidden="true"></i></span></button>
</div>-->
<mat-toolbar><span>Friends</span></mat-toolbar>
<div id="friendlist"> <div id="friendlist">
<!--<div class="frienditem" *ngFor="let friend of friends" <mat-card class="friend-card" *ngFor="let friend of user.friends"
[class.selected]="friend === selectedFriend" (click)="showFriendProfile(friend)">
<div class="picture">Pic</div>
<div class="name"><span>{{friend.name}}</span></div>
</div>-->
<mat-card class="friend-card" *ngFor="let friend of friends"
[class.selected]="friend === selectedFriend" (click)="showFriendProfile(friend)" [class.selected]="friend === selectedFriend" (click)="showFriendProfile(friend)"
tabindex="0" tabindex="0"
matRipple> matRipple>

@ -10,10 +10,16 @@
width: 100% width: 100%
margin-top: 0.5em margin-top: 0.5em
cursor: pointer cursor: pointer
.mat-card-subtitle .mat-card-subtitle
margin: 0 margin: 0
.profile-picture .profile-picture
background-image: url(https://material.angular.io/assets/img/examples/shiba1.jpg) background-image: url(https://material.angular.io/assets/img/examples/shiba1.jpg)
background-size: cover background-size: cover
#button-box
text-align: right
width: 100%
.mat-toolbar
height: 40px

@ -1,9 +1,8 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { DatasharingService } from 'src/app/services/datasharing.service'; import { DatasharingService } from 'src/app/services/datasharing.service';
import { Http } from '@angular/http';
import { FriendInfo } from 'src/app/models/friendinfo'; import { FriendInfo } from 'src/app/models/friendinfo';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { environment } from 'src/environments/environment'; import { User } from 'src/app/models/user';
@Component({ @Component({
selector: 'social-friends', selector: 'social-friends',
@ -11,44 +10,12 @@ import { environment } from 'src/environments/environment';
styleUrls: ['./friends.component.sass'] styleUrls: ['./friends.component.sass']
}) })
export class FriendsComponent implements OnInit { export class FriendsComponent implements OnInit {
user: User;
friendIDs: number[] = [29, 27, 30, 31]; constructor(private data: DatasharingService, private router: Router) { }
friends = new Array<FriendInfo>(); // = ["Friend 1", "Friend 2", "Friend 3", "Friend 4", "Friend 5", "Friend 6"]
constructor(private data: DatasharingService, private http: Http, private router: Router) { }
ngOnInit() { ngOnInit() {
// this.data.currentUserInfo.subscribe(user => { this.data.currentUserInfo.subscribe(user => {
// this.friendIDs = user.friendIDs}) this.user = user; });
this.getFriendsNames();
}
getFriendsNames() {
for (const id of this.friendIDs) {
const url = environment.graphQLUrl;
const headers = new Headers();
headers.set('Content-Type', 'application/json');
this.http.post(url, this.buildJson(id))
.subscribe(response => {this.readOutFriendsNames(id, response.json()); });
}
}
readOutFriendsNames(pId: number, pResponse: any) {
this.friends.push(new FriendInfo(pId, pResponse.data.getUser.name, pResponse.data.getUser.level ));
}
buildJson(pId: number): any {
const body = {query: `query($userId: ID) {
getUser(userId:$userId) {
name
level
}
}`, variables: {
userId: pId
}};
return body;
} }
public showFriendProfile(pFriend: FriendInfo) { public showFriendProfile(pFriend: FriendInfo) {

@ -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,17 +1,13 @@
<!--<div id="header"> <mat-toolbar>
<span class="title">Groups</span> <span>Groups</span>
<button id="new" type="submit"><span><i class="fa fa-plus fa-3x" aria-hidden="true"></i></span></button> <div id="button-box">
<button id="invitations" type="submit"><span><i class="fa fa-envelope-o fa-3x" aria-hidden="true"></i></span></button> <button mat-icon-button (click)="openDialog()" matTooltip="create group" matTooltipPosition="left" matTooltipShowDelay="500"><mat-icon>group_add</mat-icon></button>
</div>--> </div>
<mat-toolbar><span>Groups</span></mat-toolbar> </mat-toolbar>
<div id="grouplist"> <div id="grouplist">
<!--<div class="groupitem" *ngFor="let group of groups" <mat-card class="group-card" *ngFor="let group of user.groups"
[class.selected]="group === selectedGroup" (click)="showGroup(group)"> [class.selected]="group === selectedGroup" (click)="showGroupProfile(group)">
<div class="picture">Pic</div>
<div class="name"><span>{{group.name}}</span></div>
</div>-->
<mat-card class="group-card" *ngFor="let group of groups"
[class.selected]="group === selectedGroup" (click)="showGroup(group)">
<mat-card-header> <mat-card-header>
<div mat-card-avatar class="group-picture"></div> <div mat-card-avatar class="group-picture"></div>
<mat-card-title>{{group.name}}</mat-card-title> <mat-card-title>{{group.name}}</mat-card-title>

@ -9,9 +9,17 @@
box-sizing: border-box box-sizing: border-box
width: 100% width: 100%
margin-top: 0.5em margin-top: 0.5em
cursor: pointer
.mat-card-subtitle .mat-card-subtitle
margin: 0 margin: 0
.group-picture .group-picture
background-image: url(https://material.angular.io/assets/img/examples/shiba1.jpg) background-image: url(https://material.angular.io/assets/img/examples/shiba1.jpg)
background-size: cover background-size: cover
#button-box
text-align: right
width: 100%
.mat-toolbar
height: 40px

@ -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>

@ -2,13 +2,12 @@
@import '../../../styles/vars.sass' @import '../../../styles/vars.sass'
#friendscontainer #friendscontainer
box-sizing: content-box
height: 50%
width: 100%
overflow: auto
#groupscontainer #groupscontainer
box-sizing: content-box
height: 50% #tabs
width: 100% /deep/ .mat-tab-label
overflow: auto min-width: 50px
/deep/ .mat-toolbar-row
max-height: 40px

@ -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;
} }
} }

@ -8,6 +8,7 @@ export class Post {
upvotes: number; upvotes: number;
downvotes: number; downvotes: number;
userVote: string; userVote: string;
deletable: boolean;
author: Author; author: Author;
// TODO: constructor properties need normal names // TODO: constructor properties need normal names
@ -18,6 +19,7 @@ export class Post {
pUpvotes: number, pUpvotes: number,
pDownvotes: number, pDownvotes: number,
pUserVote: string, pUserVote: string,
pDeletable: boolean,
pDate: string, pDate: string,
pAuthor: Author pAuthor: Author
) { ) {
@ -27,6 +29,7 @@ export class Post {
this.upvotes = pUpvotes; this.upvotes = pUpvotes;
this.downvotes = pDownvotes; this.downvotes = pDownvotes;
this.userVote = pUserVote; this.userVote = pUserVote;
this.deletable = pDeletable;
this.date = pDate; this.date = pDate;
this.author = pAuthor; this.author = pAuthor;
} }

@ -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*/
} }

@ -22,7 +22,6 @@ export class ChatService {
} }
public getAllChats(): Array<Chat> { public getAllChats(): Array<Chat> {
console.log('Getting all chats ..');
const url = environment.graphQLUrl; const url = environment.graphQLUrl;
const headers = new Headers(); const headers = new Headers();
@ -36,7 +35,6 @@ export class ChatService {
} }
public getAllChatsRaw(): any { public getAllChatsRaw(): any {
console.log('Getting all chats ..');
const url = 'https://greenvironment.net/graphql'; const url = 'https://greenvironment.net/graphql';
const headers = new Headers(); const headers = new Headers();
@ -47,7 +45,6 @@ export class ChatService {
public getChatsByID(pChatIDs: number[]): Array<Chat> { public getChatsByID(pChatIDs: number[]): Array<Chat> {
this.chats = []; this.chats = [];
console.log('Getting chats by ID..');
for (const chatId of pChatIDs) { for (const chatId of pChatIDs) {
const url = environment.graphQLUrl; const url = environment.graphQLUrl;
@ -64,7 +61,6 @@ export class ChatService {
} }
public getChatsByIDRaw(pChatIDs: number[]): any { public getChatsByIDRaw(pChatIDs: number[]): any {
console.log('Getting chats by ID..');
for (const chatId of pChatIDs) { for (const chatId of pChatIDs) {
const url = 'https://greenvironment.net/graphql'; const url = 'https://greenvironment.net/graphql';
@ -140,7 +136,6 @@ export class ChatService {
headers.set('Content-Type', 'application/json'); headers.set('Content-Type', 'application/json');
this.http.post(url, this.getBodyForGetMessagesInChat(pChatID)).subscribe(response => { this.http.post(url, this.getBodyForGetMessagesInChat(pChatID)).subscribe(response => {
console.log('Downloading messages ...');
messages = this.renderMessages(response.json()); messages = this.renderMessages(response.json());
}); });
return messages; return messages;

@ -18,6 +18,18 @@ export class DatasharingService {
this.userInfoSource.next(pUserInfo); this.userInfoSource.next(pUserInfo);
} }
addSentRequestUserID(id: number) {
const user: User = this.userInfoSource.getValue();
user.sentRequestUserIDs.push(id);
this.changeUserInfo(user);
}
setDarkMode(active: boolean) {
const user: User = this.userInfoSource.getValue();
user.darkmode = active;
this.changeUserInfo(user);
}
changeChatIDs(pChatIDs: number[]) { changeChatIDs(pChatIDs: number[]) {
this.chatIDsSource.next(pChatIDs); this.chatIDsSource.next(pChatIDs);
} }

@ -25,51 +25,50 @@ export class FeedService {
}}; }};
this.http.post(url, body).subscribe(response => { this.http.post(url, body).subscribe(response => {
console.log(response.text()); }); });
} }
public createPost2(pContent: String) { public upvote(pPostID: number): any {
const url = environment.graphQLUrl;
const headers = new Headers(); const headers = new Headers();
headers.set('Content-Type', 'application/json'); headers.set('Content-Type', 'application/json');
const body = {query: `query{ const body = {query: `mutation($postId: ID!) {
getSelf {name} vote(postId: $postId, type: UPVOTE) {
}`}; post{userVote upvotes downvotes}
this.http.post(url, body).subscribe(response => {
console.log(response.text()); });
} }
}`, variables: {
postId: pPostID
}};
public upvote(pPostID: number): any { return this.http.post(environment.graphQLUrl, body);
const url = environment.graphQLUrl; }
public downvote(pPostID: number): any {
const headers = new Headers(); const headers = new Headers();
headers.set('Content-Type', 'application/json'); headers.set('Content-Type', 'application/json');
const body = {query: `mutation($postId: ID!) { const body = {query: `mutation($postId: ID!) {
vote(postId: $postId, type: UPVOTE) vote(postId: $postId, type: DOWNVOTE) {
post{userVote upvotes downvotes}
}
}`, variables: { }`, variables: {
postId: pPostID postId: pPostID
}}; }};
return this.http.post(url, body); return this.http.post(environment.graphQLUrl, body);
} }
public downvote(pPostID: number): any { public deletePost(pPostID: number): any {
const url = environment.graphQLUrl;
const headers = new Headers(); const headers = new Headers();
headers.set('Content-Type', 'application/json'); headers.set('Content-Type', 'application/json');
const body = {query: `mutation($postId: ID!) { const body = {query: `mutation($postId: ID!) {
vote(postId: $postId, type: DOWNVOTE) deletePost(postId: $postId)
}`, variables: { }`, variables: {
postId: pPostID postId: pPostID
}}; }};
return this.http.post(url, body); return this.http.post(environment.graphQLUrl, body);
} }
public getAllPosts(): Array<Post> { public getAllPosts(): Array<Post> {
@ -81,78 +80,35 @@ export class FeedService {
this.http.post(url, this.getBodyForGetAllPosts()) this.http.post(url, this.getBodyForGetAllPosts())
.subscribe(response => { .subscribe(response => {
this.posts = this.renderAllPosts(response.json()); this.posts = this.renderAllPosts(response.json());
console.log(response);
});
return this.posts;
}
public getAllPostsById(userId: number): Array<Post> {
const url = environment.graphQLUrl;
const headers = new Headers();
headers.set('Content-Type', 'application/json');
this.http.post(url, this.getBodyForGetAllPostsByUserId(userId))
.subscribe(response => {
this.posts = this.renderAllPosts(response.json());
console.log(response);
}); });
return this.posts; return this.posts;
} }
public getAllPostsRaw(): any { public getAllPostsRaw(): any {
const url = environment.graphQLUrl;
const headers = new Headers(); const headers = new Headers();
headers.set('Content-Type', 'application/json'); headers.set('Content-Type', 'application/json');
return this.http.post(environment.graphQLUrl, this.getBodyForGetAllPosts());
return this.http.post(url, this.getBodyForGetAllPosts());
} }
public getAllPostsRawByUserId(userId: number): any { getBodyForGetAllPosts() {
const url = environment.graphQLUrl; const body = {query: `{
const headers = new Headers();
headers.set('Content-Type', 'application/json');
return this.http.post(url, this.getBodyForGetAllPostsByUserId(userId));
}
getBodyForGetAllPostsByUserId(pUserId: number) {
const body = {query: `query ($userId: ID!) {
getPosts (first: 1000, offset: 0) { getPosts (first: 1000, offset: 0) {
id, id,
content, content,
htmlContent, htmlContent,
upvotes, upvotes,
downvotes, downvotes,
userVote(userId: $userId), userVote,
deletable
author{ author{
name, name,
handle, handle,
id}, id},
createdAt} createdAt}
}`, variables: { }`, variables: {
userId: pUserId
}}; }};
return body; return body;
} }
getBodyForGetAllPosts() {
const body = {query: `query {
getPosts (first: 1000, offset: 0) {
id,
content,
htmlContent,
upvotes,
downvotes,
author{
name,
handle,
id},
createdAt}
}`
};
return body;
}
public renderAllPosts(pResponse: any): Array<Post> { public renderAllPosts(pResponse: any): Array<Post> {
const posts = new Array<Post>(); const posts = new Array<Post>();
@ -164,11 +120,12 @@ export class FeedService {
const upvotes: number = post.upvotes; const upvotes: number = post.upvotes;
const downvotes: number = post.downvotes; const downvotes: number = post.downvotes;
const userVote: string = post.userVote; const userVote: string = post.userVote;
const deletable: boolean = post.deletable;
const author = new Author(post.author.id, post.author.name, post.author.handle); const author = new Author(post.author.id, post.author.name, post.author.handle);
const temp = new Date(Number(post.createdAt)); const temp = new Date(Number(post.createdAt));
const date = temp.toLocaleString('en-GB'); const date = temp.toLocaleString('en-GB');
posts.push(new Post(id, content, htmlContent, upvotes, downvotes, userVote, date, author)); posts.push(new Post(id, content, htmlContent, upvotes, downvotes, userVote, deletable, date, author));
} }
return posts; return posts;
} }

@ -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);
}
}

@ -1,10 +1,13 @@
import {Injectable} from '@angular/core'; import {Injectable} from '@angular/core';
import {Headers, Http} from '@angular/http'; import {Headers, Http, Request} from '@angular/http';
import {Login} from '../../models/login'; import {Login} from '../../models/login';
import {User} from 'src/app/models/user'; import {User} from 'src/app/models/user';
import {DatasharingService} from '../datasharing.service'; import {DatasharingService} from '../datasharing.service';
import {Router} from '@angular/router'; import {Router} from '@angular/router';
import {environment} from 'src/environments/environment'; import {environment} from 'src/environments/environment';
import { FriendRequest } from 'src/app/models/friendRequest';
import { FriendInfo } from 'src/app/models/friendinfo';
import { GroupInfo } from 'src/app/models/groupinfo';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -21,7 +24,6 @@ export class LoginService {
return this.http.post(environment.graphQLUrl, this.buildJson(login)) return this.http.post(environment.graphQLUrl, this.buildJson(login))
.subscribe(response => { .subscribe(response => {
console.log(response.text());
this.loginSuccess(); this.loginSuccess();
this.updateUserInfo(response.json()); this.updateUserInfo(response.json());
}, errorCb }, errorCb
@ -29,12 +31,12 @@ export class LoginService {
} }
public loginSuccess() { public loginSuccess() {
console.log('alles supi dupi');
this.router.navigateByUrl(''); this.router.navigateByUrl('');
} }
public updateUserInfo(response: any) { public updateUserInfo(response: any) {
const user: User = new User(); const user: User = new User();
let friendRequest: FriendRequest = new FriendRequest();
user.loggedIn = true; user.loggedIn = true;
user.userID = response.data.login.id; user.userID = response.data.login.id;
user.username = response.data.login.name; user.username = response.data.login.name;
@ -42,18 +44,33 @@ export class LoginService {
user.email = response.data.login.email; user.email = response.data.login.email;
user.points = response.data.login.points; user.points = response.data.login.points;
user.level = response.data.login.level; user.level = response.data.login.level;
user.friendIDs = response.data.login.friends; for (const friend of response.data.login.friends) {
user.groupIDs = response.data.login.groups; user.friends.push(new FriendInfo(friend.id, friend.name, friend.level));
}
for (const group of response.data.login.groups) {
user.groups.push(new GroupInfo(group.id, group.name));
}
user.chatIDs = response.data.login.chats; user.chatIDs = response.data.login.chats;
user.requestIDs = response.data.login.requests; for (const request of response.data.login.sentRequests) {
user.sentRequestUserIDs.push(request.receiver.id);
}
for (const request of response.data.login.receivedRequests) {
friendRequest = new FriendRequest();
friendRequest.id = request.id;
friendRequest.senderUserID = request.sender.id;
friendRequest.senderUsername = request.sender.name;
friendRequest.senderHandle = request.sender.handle;
user.receivedRequests.push(friendRequest);
}
if (JSON.parse(response.data.login.settings).darkmode === 'true') {
user.darkmode = true;
}
this.data.changeUserInfo(user); this.data.changeUserInfo(user);
} }
public buildJson(login: Login): any { public buildJson(login: Login): any {
const body = { const body = {
query: `mutation($email: String, $pwHash: String) { query: `mutation($email: String!, $pwHash: String!) {
login(email: $email, passwordHash: $pwHash) { login(email: $email, passwordHash: $pwHash) {
id, id,
name, name,
@ -61,15 +78,21 @@ export class LoginService {
handle, handle,
points, points,
level, level,
receivedRequests{id, sender{name, handle, id}},
sentRequests{receiver{id}},
friends { friends {
id id,
name,
level
}, },
groups { groups {
id id,
name
}, },
chats{ chats{
id id
} },
settings
} }
}` }`
, variables: { , variables: {

@ -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;
}
}

@ -5,6 +5,8 @@ import {Router} from '@angular/router';
import { DatasharingService } from '../datasharing.service'; import { DatasharingService } from '../datasharing.service';
import { User } from 'src/app/models/user'; import { User } from 'src/app/models/user';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { FriendRequest } from 'src/app/models/friendRequest';
import { FriendInfo } from 'src/app/models/friendinfo';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -38,6 +40,7 @@ export class RegisterService {
public updateUserInfo(response: any) { public updateUserInfo(response: any) {
const user: User = new User(); const user: User = new User();
let friendRequest: FriendRequest = new FriendRequest();
user.loggedIn = true; user.loggedIn = true;
user.userID = response.data.register.id; user.userID = response.data.register.id;
user.username = response.data.register.name; user.username = response.data.register.name;
@ -45,11 +48,25 @@ export class RegisterService {
user.email = response.data.register.email; user.email = response.data.register.email;
user.points = response.data.register.points; user.points = response.data.register.points;
user.level = response.data.register.level; user.level = response.data.register.level;
user.friendIDs = response.data.register.friends; for (const friend of response.data.register.friends) {
user.groupIDs = response.data.register.groups; user.friends.push(new FriendInfo(friend.id, friend.name, friend.level));
}
// user.groupIDs = response.data.register.groups;
user.chatIDs = response.data.register.chats; user.chatIDs = response.data.register.chats;
user.requestIDs = response.data.register.requests; for (const request of response.data.register.sentRequests) {
user.sentRequestUserIDs.push(request.receiver.id);
}
for (const request of response.data.register.receivedRequests) {
friendRequest = new FriendRequest();
friendRequest.id = request.id;
friendRequest.senderUserID = request.sender.id;
friendRequest.senderUsername = request.sender.name;
friendRequest.senderHandle = request.sender.handle;
user.receivedRequests.push(friendRequest);
}
if (JSON.parse(response.data.register.settings).darkmode === 'true') {
user.darkmode = true;
}
this.data.changeUserInfo(user); this.data.changeUserInfo(user);
} }
@ -62,9 +79,16 @@ export class RegisterService {
handle, handle,
points, points,
level, level,
friends{id}, receivedRequests{id, sender{name, handle, id}},
sentRequests{receiver{id}}
friends {
id,
name,
level
},
groups{id}, groups{id},
chats{id} chats{id},
settings
} }
}`, variables: { }`, variables: {
email: registration.email, email: registration.email,

@ -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;
}
}

@ -6,6 +6,9 @@ import { DatasharingService } from '../datasharing.service';
import { userInfo } from 'os'; import { userInfo } from 'os';
import {Router} from '@angular/router'; import {Router} from '@angular/router';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { FriendRequest } from 'src/app/models/friendRequest';
import { FriendInfo } from 'src/app/models/friendinfo';
import { GroupInfo } from 'src/app/models/groupinfo';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -15,34 +18,29 @@ export class SelfService {
constructor(private http: Http, private data: DatasharingService, private router: Router) { } constructor(private http: Http, private data: DatasharingService, private router: Router) { }
public checkIfLoggedIn() { public checkIfLoggedIn() {
console.log('check if logged in...');
const url = environment.graphQLUrl; const url = environment.graphQLUrl;
const headers = new Headers(); const headers = new Headers();
headers.set('Content-Type', 'application/json'); headers.set('Content-Type', 'application/json');
return this.http.post(url, this.buildJson()) return this.http.post(url, this.buildJson())
.subscribe(response => { .subscribe(response => {
console.log(response.text());
this.stillLoggedIn(); this.stillLoggedIn();
this.updateUserInfo(response.json()); this.updateUserInfo(response.json());
}, error => { }, error => {
this.notLoggedIn(); this.notLoggedIn();
console.log(error.text()); // this.fakeLogin();
} }
); );
} }
public stillLoggedIn() { public stillLoggedIn() {
console.log('user was logged in');
} }
public notLoggedIn() { public notLoggedIn() {
console.log('user was not logged in');
} }
public updateUserInfo(response: any) { public updateUserInfo(response: any) {
const user: User = new User(); const user: User = new User();
let friendRequest: FriendRequest = new FriendRequest();
user.loggedIn = true; user.loggedIn = true;
user.userID = response.data.getSelf.id; user.userID = response.data.getSelf.id;
user.username = response.data.getSelf.name; user.username = response.data.getSelf.name;
@ -50,19 +48,78 @@ export class SelfService {
user.email = response.data.getSelf.email; user.email = response.data.getSelf.email;
user.points = response.data.getSelf.points; user.points = response.data.getSelf.points;
user.level = response.data.getSelf.level; user.level = response.data.getSelf.level;
user.friendIDs = response.data.getSelf.friends; for (const friend of response.data.getSelf.friends) {
user.groupIDs = response.data.getSelf.groups; user.friends.push(new FriendInfo(friend.id, friend.name, friend.level));
}
for (const group of response.data.getSelf.groups) {
user.groups.push(new GroupInfo(group.id, group.name));
}
user.chatIDs = response.data.getSelf.chats; user.chatIDs = response.data.getSelf.chats;
user.requestIDs = response.data.getSelf.requests; for (const request of response.data.getSelf.sentRequests) {
user.sentRequestUserIDs.push(request.receiver.id);
}
for (const request of response.data.getSelf.receivedRequests) {
friendRequest = new FriendRequest();
friendRequest.id = request.id;
friendRequest.senderUserID = request.sender.id;
friendRequest.senderUsername = request.sender.name;
friendRequest.senderHandle = request.sender.handle;
user.receivedRequests.push(friendRequest);
}
if (JSON.parse(response.data.getSelf.settings).darkmode === 'true') {
user.darkmode = true;
}
this.data.changeUserInfo(user);
}
public fakeLogin() {
const user: User = new User();
let friendRequest: FriendRequest = new FriendRequest();
user.loggedIn = true;
user.userID = 1;
user.username = 'Rapier';
user.handle = 'rapier123';
user.email = 'r@r.com';
user.points = 100;
user.level = 3;
user.friends.push(new FriendInfo(1, 'Freund77', 4));
friendRequest = new FriendRequest();
friendRequest.id = 10;
friendRequest.senderUserID = 99;
friendRequest.senderUsername = 'Löwe';
friendRequest.senderHandle = 'loewe123';
user.receivedRequests.push(friendRequest);
this.data.changeUserInfo(user); this.data.changeUserInfo(user);
} }
public buildJson(): any { public buildJson(): any {
const body = {query: `{ const body = {query: `{
getSelf{id, name,email, handle, points, level, friends{id}, groups{id},chats{id}} getSelf{
id,
name,
email,
handle,
points,
level,
receivedRequests{id, sender{name, handle, id}},
sentRequests{receiver{id}},
friends {
id,
name,
level
},
groups {
id,
name
},
chats{
id
},
settings
}
}`, variables: { }`, variables: {
}}; }};
return body; return body;
} }
}// add ,receivedRequests{id} later }

@ -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;
}
}

@ -6,12 +6,45 @@
// Be sure that you only ever include this mixin once! // Be sure that you only ever include this mixin once!
@include mat-core(); @include mat-core();
$md-gvgreen: (
50 : #e0f7e7,
100 : #b3ebc3,
200 : #80de9c,
300 : #4dd174,
400 : #26c756,
500 : #00bd38,
600 : #00b732,
700 : #00ae2b,
800 : #00a624,
900 : #009817,
A100 : #c3ffc9,
A200 : #90ff9a,
A400 : #5dff6b,
A700 : #44ff54,
contrast: (
50 : #000000,
100 : #000000,
200 : #000000,
300 : #000000,
400 : #000000,
500 : #ffffff,
600 : #ffffff,
700 : #ffffff,
800 : #ffffff,
900 : #ffffff,
A100 : #000000,
A200 : #000000,
A400 : #000000,
A700 : #000000,
)
);
// Define the palettes for your theme using the Material Design palettes available in palette.scss // Define the palettes for your theme using the Material Design palettes available in palette.scss
// (imported above). For each palette, you can optionally specify a default, lighter, and darker // (imported above). For each palette, you can optionally specify a default, lighter, and darker
// hue. Available color palettes: https://material.io/design/color/ // hue. Available color palettes: https://material.io/design/color/
$primary: mat-palette($mat-green); $primary: mat-palette($mat-light-green);
$accent: mat-palette($mat-pink, A200, A100, A400); $primary-color: mat-color($primary);
$background-color: map_get($mat-grey, 50); $accent: mat-palette($mat-brown, A200, A100, A400);
// The warn palette is optional (defaults to red). // The warn palette is optional (defaults to red).
$warn: mat-palette($mat-red); $warn: mat-palette($mat-red);
@ -19,7 +52,7 @@ $warn: mat-palette($mat-red);
$light-theme: mat-light-theme($primary, $accent, $warn); $light-theme: mat-light-theme($primary, $accent, $warn);
// Set custom background color // Set custom background color
$background-color: map_get($mat-blue-grey, 50); $background-color: #e6e6e6;
$background: map-get($light-theme, background); $background: map-get($light-theme, background);
$background: map_merge($background, (background: $background-color)); $background: map_merge($background, (background: $background-color));
@ -27,15 +60,18 @@ $light-theme: map_merge($light-theme, (background: $background));
$dark-primary: mat-palette($mat-green); $dark-primary: mat-palette($mat-light-green);
$dark-accent: mat-palette($mat-pink, A200, A100, A400); $dark-accent: mat-palette($mat-brown, A200, A100, A400);
// The warn palette is optional (defaults to red).
$dark-warn: mat-palette($mat-red); $dark-warn: mat-palette($mat-red);
// Create the theme object (a Sass map containing all of the palettes). // Create the theme object (a Sass map containing all of the palettes).
$dark-theme: mat-dark-theme($dark-primary, $dark-accent, $dark-warn); $dark-theme: mat-dark-theme($dark-primary, $dark-accent, $dark-warn);
$dark-background-color: #121212;
$dark-background: map-get($dark-theme, background);
$dark-background: map_merge($dark-background, (background: $dark-background-color));
$dark-theme: map_merge($dark-theme, (background: $dark-background));
.dark-theme { .dark-theme {
@include angular-material-theme($dark-theme); @include angular-material-theme($dark-theme);

@ -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

5
src/typings.d.ts vendored

@ -0,0 +1,5 @@
declare module '*.svg' {
const svg: string;
export default svg;
}
Loading…
Cancel
Save