Merge branch 'master' of Software_Engineering_I/greenvironment-frontend into max_dev

master
Max_ES 5 years ago committed by Gitea
commit 1baa7b6230

2487
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -17,8 +17,8 @@
"@angular/compiler": "~8.2.14",
"@angular/core": "^8.2.14",
"@angular/flex-layout": "^8.0.0-beta.27",
"@angular/forms": "^7.2.15",
"@angular/http": "^7.2.15",
"@angular/forms": "^7.2.16",
"@angular/http": "^7.2.16",
"@angular/material": "^8.2.3",
"@angular/platform-browser": "8.2.14",
"@angular/platform-browser-dynamic": "^8.2.14",
@ -41,10 +41,10 @@
"zone.js": "^0.8.29"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.803.21",
"@angular/cli": "^8.3.21",
"@angular-devkit/build-angular": "^0.803.23",
"@angular/cli": "^8.3.23",
"@angular/compiler-cli": "^8.2.14",
"@angular/language-service": "^7.2.15",
"@angular/language-service": "^7.2.16",
"@types/jasmine": "^2.8.16",
"@types/jasminewd2": "^2.0.8",
"@types/node": "~8.9.4",
@ -59,6 +59,6 @@
"protractor": "^5.4.2",
"ts-node": "~7.0.0",
"tslint": "^5.20.1",
"typescript": "~3.5.0"
"typescript": "<3.6.0"
}
}

@ -4,6 +4,7 @@ import { Login } from 'src/app/models/login';
import { LoginService } from 'src/app/services/login/login.service';
import {Router} from '@angular/router';
import * as sha512 from 'js-sha512';
import {IErrorResponse} from '../../models/interfaces/IErrorResponse';
@Component({
selector: 'app-login',
@ -21,22 +22,37 @@ export class LoginComponent implements OnInit {
errorMessage: string;
email = new FormControl('', [Validators.required, Validators.email]);
public getErrorMessage() {
private getErrorMessage() {
return this.errorMessage;
}
public loginError(error: any) {
private loginError(errorResponse: IErrorResponse) {
const error = errorResponse.error;
this.errorOccurred = true;
this.errorMessage = error.errors[0].message;
}
/**
* Fired when the submit button is pressed.
* A login request is performed and the user is redirected to the home page on success.
* @param pEmail
* @param pPasswordHash
*/
onClickSubmit(pEmail: string, pPasswordHash: string) {
this.errorOccurred = false;
this.errorMessage = ' ';
this.login.email = pEmail.trim().toLowerCase();
this.login.passwordHash = sha512.sha512(pPasswordHash);
this.loginService.login(this.login, error => this.loginError(error.json()));
this.loginService.login(this.login).subscribe( () => {
this.router.navigateByUrl('').catch((error) => {
this.errorMessage = error.message;
this.errorOccurred = true;
});
}, (error: IErrorResponse) => {
if (error.error) {
this.loginError(error);
}
});
}
ngOnInit() {}

@ -18,13 +18,12 @@ export class SearchComponent implements OnInit {
searchValue = ' ';
category = 'user';
user: User;
foundUsers: Array<User> = new Array();
foundGroups: Array<GroupInfo> = new Array();
foundUsers: User[] = [];
foundGroups: GroupInfo[] = [];
constructor(
private searchService: SearchService,
private requestService: RequestService,
private http: Http,
private router: Router,
private data: DatasharingService) { }
ngOnInit() {
@ -46,19 +45,16 @@ export class SearchComponent implements OnInit {
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))
findUser(name: string) {
this.searchService.search(name)
.subscribe(response => {
this.foundUsers = this.searchService.renderUsers(response.json());
this.foundGroups = this.searchService.renderGroups(response.json());
this.foundUsers = this.searchService.getUsersForResponse(response);
this.foundGroups = this.searchService.getGroupsForResponse(response);
for (const foundUser of this.foundUsers) {
foundUser.allowedToSendRequest = this.requestService.isAllowedToSendRequest(foundUser.userID, this.user);
}

@ -4,6 +4,7 @@
<input matInput placeholder="Enter groupname" #name>
</mat-form-field>
</div>
<mat-error *ngIf="errorOccurred">{{getErrorMessage()}}</mat-error>
<div mat-dialog-actions>
<button mat-button (click)="onNoClick()">Cancel</button>
<button mat-button cdkFocusInitial (click)="createGroup(name.value)">Create Group</button>

@ -1,10 +1,13 @@
import { Component, OnInit } from '@angular/core';
import { GroupInfo } from 'src/app/models/groupinfo';
import {Component, OnInit} from '@angular/core';
import {GroupInfo} from 'src/app/models/groupinfo';
import {MatDialog, MatDialogRef} from '@angular/material/dialog';
import { SocialService } from 'src/app/services/social/social.service';
import { User } from 'src/app/models/user';
import { DatasharingService } from 'src/app/services/datasharing.service';
import { Router } from '@angular/router';
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';
import {GraphQLError} from 'graphql';
import {IGraphqlError} from '../../../models/interfaces/IGraphqlError';
import {IErrorResponse} from '../../../models/interfaces/IErrorResponse';
// DIALOG COMPONENT to create groups
@Component({
@ -12,22 +15,31 @@ import { Router } from '@angular/router';
templateUrl: 'dialog.html',
})
export class DialogCreateGroupComponent {
errorOccurred = false;
private errorMessage: string;
constructor(
public dialogRef: MatDialogRef<DialogCreateGroupComponent>, private social: SocialService) {}
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.social.createGroup(name).subscribe(() => {
this.dialogRef.close();
}, ((error: IErrorResponse) => {
this.errorMessage = error.error.errors[0].message;
this.errorOccurred = true;
}));
}
}
getErrorMessage() {
return this.errorMessage;
}
}
@ -39,11 +51,14 @@ export class DialogCreateGroupComponent {
})
export class GroupsComponent implements OnInit {
user: User;
constructor(public dialog: MatDialog, private data: DatasharingService, private router: Router) { }
constructor(public dialog: MatDialog, private data: DatasharingService, private router: Router) {
}
ngOnInit() {
this.data.currentUserInfo.subscribe(user => {
this.user = user; });
this.user = user;
});
}
public showGroupProfile(group: GroupInfo) {

@ -5,4 +5,11 @@ export class FriendRequest {
senderUserID: number;
senderHandle: string;
senderUsername: string;
constructor(id?: number, senderUserId?: number, senderHandle?: string, senderName?: string) {
this.id = id;
this.senderUserID = senderUserId;
this.senderHandle = senderHandle;
this.senderUsername = senderName;
}
}

@ -0,0 +1,12 @@
import {IUser} from './IUser';
export interface IChat {
id: number;
namespace: string;
members: IUser[];
messages: any[];
}

@ -0,0 +1,8 @@
import {IGraphqlError} from './IGraphqlError';
export interface IErrorResponse {
error: {
errors: IGraphqlError[];
data: any;
};
}

@ -0,0 +1,8 @@
export interface IGraphqlError {
message: string;
path: string[];
location: {line: number; column: number}[];
}

@ -0,0 +1,20 @@
import {IUser} from './IUser';
export interface IGroup {
id: number;
name: string;
creator: IUser;
admins: IUser[];
members: IUser[];
chat: any;
events: any;
joined: boolean;
}

@ -0,0 +1,18 @@
import {IUser} from './IUser';
export enum RequestType {
FRIENDREQUEST = 'FRIENDREQUEST',
GROUPINVITE = 'GROUPINVITE',
EVENTINVITE = 'EVENTINVITE',
}
export interface IRequest {
id: number;
sender: IUser;
receiver: IUser;
type: RequestType;
}

@ -0,0 +1,12 @@
import {IUser} from './IUser';
import {IGroup} from './IGroup';
export interface ISearchResult {
users: IUser[];
groups: IGroup[];
posts: any[];
events: any[];
}

@ -0,0 +1,3 @@
export interface ISettings {
darkmode?: boolean;
}

@ -0,0 +1,49 @@
import {IGroup} from './IGroup';
import {ISettings} from './ISettings';
import {IChat} from './IChat';
import {IRequest} from './IRequest';
export interface IUser {
id: number;
name: string;
handle: string;
email?: string;
profilePicture?: string;
settings?: string;
level: number;
points: number;
numberOfPosts: number;
postCount: number;
posts: any[];
chats: IChat[];
receivedRequests: IRequest[];
sentRequests: IRequest[];
joinedAt: string;
friendCount: number;
friends: IUser[];
groupCount: number;
groups: IGroup[];
eventCount: number;
events: any[];
}

@ -2,6 +2,7 @@ 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';
import {IUser} from './interfaces/IUser';
export class User {
loggedIn = false;
@ -18,12 +19,39 @@ export class User {
darkmode = false;
friends: FriendInfo[] = new Array();
groups: GroupInfo[] = new Array();
posts: Post[] = new Array();
friends: FriendInfo[] = [];
groups: GroupInfo[] = [];
posts: Post[] = [];
chatIDs: number[];
receivedRequests: FriendRequest[] = new Array();
sentRequestUserIDs: number[] = new Array(); // IDs of users that already received requests of the logged in user
receivedRequests: FriendRequest[] = [];
sentRequestUserIDs: number[] = []; // 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*/
public assignFromResponse(userDataResponse: IUser) {
this.userID = userDataResponse.id;
this.username = userDataResponse.name;
this.handle = userDataResponse.handle;
this.email = userDataResponse.email;
this.points = userDataResponse.points;
this.level = userDataResponse.level;
this.profilePicture = userDataResponse.profilePicture;
this.joinedAt = userDataResponse.joinedAt;
this.friendCount = userDataResponse.friendCount;
this.groupCount = userDataResponse.groupCount;
try {
this.darkmode = !!JSON.parse(userDataResponse.settings).darkmode;
} catch (err) {
console.error(err);
}
this.friends = userDataResponse.friends
.map(friend => new FriendInfo(friend.id, friend.name, friend.level));
this.groups = userDataResponse.groups
.map(group => new GroupInfo(group.id, group.name));
this.chatIDs = userDataResponse.chats.map(chat => chat.id);
this.sentRequestUserIDs = userDataResponse.sentRequests
.map(request => request.receiver.id);
this.receivedRequests = userDataResponse.receivedRequests
.map(request => new FriendRequest(request.id, request.sender.id, request.sender.handle, request.sender.name));
}
}

@ -0,0 +1,14 @@
import {Injectable} from '@angular/core';
import {HttpHeaders} from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export abstract class BaseService {
protected headers: HttpHeaders;
protected constructor() {
this.headers = new HttpHeaders();
this.headers.set('Content-Type', 'application/json');
}
}

@ -1,7 +1,6 @@
import { Injectable } from '@angular/core';
import {Http, URLSearchParams, Headers} from '@angular/http';
import { Chat } from 'src/app/models/chat';
import { responsePathAsArray } from 'graphql';
import { Chatmessage } from 'src/app/models/chatmessage';
import { FriendInfo } from 'src/app/models/friendinfo';
import { DatasharingService } from '../datasharing.service';
@ -35,7 +34,7 @@ export class ChatService {
}
public getAllChatsRaw(): any {
const url = 'https://greenvironment.net/graphql';
const url = environment.graphQLUrl;
const headers = new Headers();
headers.set('Content-Type', 'application/json');
@ -63,7 +62,7 @@ export class ChatService {
public getChatsByIDRaw(pChatIDs: number[]): any {
for (const chatId of pChatIDs) {
const url = 'https://greenvironment.net/graphql';
const url = environment.graphQLUrl;
const headers = new Headers();
headers.set('Content-Type', 'application/json');
@ -142,7 +141,7 @@ export class ChatService {
}
public getMessagesRaw(pChatID): any {
const url = 'https://greenvironment.net/graphql';
const url = environment.graphQLUrl;
const headers = new Headers();
headers.set('Content-Type', 'application/json');
@ -242,9 +241,9 @@ export class ChatService {
getBodyForGetAllChats() {
const body = {query: `query {
getSelf {
chats(first: 1000, offset: 0) {
chats(first: 10, offset: 0) {
id, members{name, id, level},
messages(first: 1000, offset: 0) {
messages(first: 10, offset: 0) {
author {id}, createdAt, content
}
}

@ -1,76 +1,20 @@
import {Injectable} from '@angular/core';
import {Headers, Http, Request} from '@angular/http';
import {HttpClient} from '@angular/common/http';
import {Login} from '../../models/login';
import {User} from 'src/app/models/user';
import {DatasharingService} from '../datasharing.service';
import {Router} from '@angular/router';
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';
import {IUser} from '../../models/interfaces/IUser';
import {BaseService} from '../base.service';
import {tap} from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class LoginService {
constructor(private http: Http, private data: DatasharingService, private router: Router) {
}
public login(login: Login, errorCb: any) {
const headers = new Headers();
headers.set('Content-Type', 'application/json');
return this.http.post(environment.graphQLUrl, this.buildJson(login))
.subscribe(response => {
this.loginSuccess();
this.updateUserInfo(response.json());
}, errorCb
);
}
public loginSuccess() {
this.router.navigateByUrl('');
}
public updateUserInfo(response: any) {
const user: User = new User();
let friendRequest: FriendRequest = new FriendRequest();
user.loggedIn = true;
user.userID = response.data.login.id;
user.username = response.data.login.name;
user.handle = response.data.login.handle;
user.email = response.data.login.email;
user.points = response.data.login.points;
user.level = response.data.login.level;
for (const friend of response.data.login.friends) {
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;
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);
}
interface ILoginRequestResult {
data: {
login: IUser;
};
}
public buildJson(login: Login): any {
const body = {
query: `mutation($email: String!, $pwHash: String!) {
const graphqlQuery = `mutation($email: String!, $pwHash: String!) {
login(email: $email, passwordHash: $pwHash) {
id,
name,
@ -94,12 +38,42 @@ export class LoginService {
},
settings
}
}`
, variables: {
}`;
@Injectable({
providedIn: 'root'
})
export class LoginService extends BaseService {
constructor(private http: HttpClient, private datasharingService: DatasharingService) {
super();
}
/**
* Builds the body for the login request
* @param login
*/
private static buildRequestBody(login: Login): any {
return {
query: graphqlQuery,
variables: {
email: login.email,
pwHash: login.passwordHash,
}
};
return body;
}
/**
* Performs a login request and returns the data of the logged in user.
* @param login
*/
public login(login: Login) {
const body = LoginService.buildRequestBody(login);
return this.http.post<ILoginRequestResult>(environment.graphQLUrl, body, {headers: this.headers})
.pipe(tap(response => {
const user = new User();
user.assignFromResponse(response.data.login);
this.datasharingService.changeUserInfo(user);
}));
}
}

@ -1,48 +1,23 @@
import {Injectable} from '@angular/core';
import {Headers, Http} from '@angular/http';
import {HttpClient} from '@angular/common/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';
import {User} from 'src/app/models/user';
import {GroupInfo} from 'src/app/models/groupinfo';
import {Observable} from 'rxjs';
import {ISearchResult} from '../../models/interfaces/ISearchResult';
import {environment} from '../../../environments/environment';
import {BaseService} from '../base.service';
import {tap} from 'rxjs/operators';
@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;
}
interface ISearchRequestResult {
data: {
search: ISearchResult;
};
}
public buildJsonUser(name_: String): any {
const body = {
query: `query($name: String!) {
search(query:$name, first: 100, offset: 0) {
const graphqlQuery = `query($query: String!, $first: Int, $offset: Int) {
search(query:$query, first: $first, offset: $offset) {
users{
profilePicture,
name,
@ -61,11 +36,72 @@ export class SearchService {
members{id name handle}
}
}
}`
, variables: {
name: name_
}`;
@Injectable({
providedIn: 'root'
})
export class SearchService extends BaseService {
constructor(private http: HttpClient, private data: DatasharingService, private router: Router) {
super();
}
/**
* Builds the body for the request
* @param query - the search query
* @param first - the limit of elements to fetch
* @param offset - offset
*/
private static buildRequestBody(query: String, first: number = 20, offset: number = 0): any {
return {
query: graphqlQuery,
variables: {
query,
first,
offset
}
};
return body;
}
/**
* Maps the users in the response to the user class
* @param response
*/
public getUsersForResponse(response: ISearchRequestResult): User[] {
const users = new Array<User>();
for (const foundUser of response.data.search.users) {
const user = new User();
user.profilePicture = foundUser.profilePicture;
user.username = foundUser.name;
user.userID = foundUser.id;
user.handle = foundUser.handle;
user.points = foundUser.points;
user.level = foundUser.level;
// @ts-ignore
user.friends = foundUser.friends;
users.push(user);
}
return users;
}
/**
* Maps the groups in the response to the group class
* @param response
*/
public getGroupsForResponse(response: ISearchRequestResult): Array<GroupInfo> {
const groups = new Array<GroupInfo>();
for (const group of response.data.search.groups) {
groups.push(new GroupInfo(group.id, group.name));
}
return groups;
}
/**
* Searches for users, groups, events and posts with a specified query.
* @param query
*/
public search(query: string): Observable<ISearchRequestResult> {
const body = SearchService.buildRequestBody(query);
return this.http.post<ISearchRequestResult>(environment.graphQLUrl, body, {headers: this.headers});
}
}

@ -1,9 +1,7 @@
import { Injectable, EventEmitter, Output } from '@angular/core';
import {Http, URLSearchParams, Headers} from '@angular/http';
import { Login } from '../../models/login';
import { User } from 'src/app/models/user';
import { DatasharingService } from '../datasharing.service';
import { userInfo } from 'os';
import {Router} from '@angular/router';
import { environment } from 'src/environments/environment';
import { FriendRequest } from 'src/app/models/friendRequest';

@ -1,37 +1,41 @@
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 {HttpClient} from '@angular/common/http';
import {BaseService} from '../base.service';
const graphqlCreateGroupQuery = `mutation($name: String!) {
createGroup(name: $name) {
id
}
}`;
@Injectable({
providedIn: 'root'
})
export class SocialService {
export class SocialService extends BaseService {
users: Array<User>;
constructor(private http: Http, private data: DatasharingService, private router: Router) {
constructor(private http: HttpClient) {
super();
}
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_
/**
* Builds the body for a group creation request
* @param name
*/
private static buildGroupCreateBody(name: String): any {
return {
query: graphqlCreateGroupQuery, variables: {
name
}
};
return body;
}
/**
* Creates a group
* @param name
*/
createGroup(name: string) {
const body = SocialService.buildGroupCreateBody(name);
return this.http.post(environment.graphQLUrl, body, {headers: this.headers});
}
}

@ -7,12 +7,3 @@ export const environment = {
graphQLUrl: 'https://greenvironment.net/graphql',
greenvironmentUrl: 'https://greenvironment.net/',
};
/*
* For easier debugging in development mode, you can import the following file
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
*
* This import should be commented out in production mode because it will have a negative impact
* on performance if an error is thrown.
*/
// import 'zone.js/dist/zone-error'; // Included with Angular CLI.

@ -70,7 +70,7 @@
],
"no-misused-new": true,
"no-non-null-assertion": true,
"no-redundant-jsdoc": true,
"no-redundant-jsdoc": false,
"no-shadowed-variable": true,
"no-string-literal": false,
"no-string-throw": true,

Loading…
Cancel
Save