From 9ddc7de6effacd0a8a8fcf2ae1a0d997c68dca0e Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 19 Jan 2020 12:29:30 +0100 Subject: [PATCH 1/5] Remove unused document stuff --- src/app/app.module.ts | 4 --- .../document-list.component.html | 5 --- .../document-list.component.scss | 28 --------------- .../document-list.component.spec.ts | 25 ------------- .../document-list/document-list.component.ts | 36 ------------------- .../document/document.component.html | 1 - .../document/document.component.scss | 12 ------- .../document/document.component.spec.ts | 25 ------------- .../components/document/document.component.ts | 32 ----------------- 9 files changed, 168 deletions(-) delete mode 100644 src/app/components/document-list/document-list.component.html delete mode 100644 src/app/components/document-list/document-list.component.scss delete mode 100644 src/app/components/document-list/document-list.component.spec.ts delete mode 100644 src/app/components/document-list/document-list.component.ts delete mode 100644 src/app/components/document/document.component.html delete mode 100644 src/app/components/document/document.component.scss delete mode 100644 src/app/components/document/document.component.spec.ts delete mode 100644 src/app/components/document/document.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 73b2909..ddd3cfd 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -6,8 +6,6 @@ import {SocketIoConfig, SocketIoModule} from 'ngx-socket-io'; import {HttpModule} from '@angular/http'; import {AppComponent} from './app.component'; -import {DocumentListComponent} from './components/document-list/document-list.component'; -import {DocumentComponent} from './components/document/document.component'; import {RegisterComponent} from './components/register/register.component'; import {LoginComponent} from './components/login/login.component'; import {ChatComponent} from './components/chat/chat.component'; @@ -81,8 +79,6 @@ const appRoutes: Routes = [ @NgModule({ declarations: [ AppComponent, - DocumentListComponent, - DocumentComponent, RegisterComponent, LoginComponent, ChatComponent, diff --git a/src/app/components/document-list/document-list.component.html b/src/app/components/document-list/document-list.component.html deleted file mode 100644 index d99fd52..0000000 --- a/src/app/components/document-list/document-list.component.html +++ /dev/null @@ -1,5 +0,0 @@ -
- New Document - {{ docId }} -
diff --git a/src/app/components/document-list/document-list.component.scss b/src/app/components/document-list/document-list.component.scss deleted file mode 100644 index 10001b7..0000000 --- a/src/app/components/document-list/document-list.component.scss +++ /dev/null @@ -1,28 +0,0 @@ -.sidenav { - position: fixed; - height: 100%; - width: 220px; - top: 0; - left: 0; - background-color: #111111; - overflow-x: hidden; - padding-top: 20px; - - span { - padding: 6px 8px 6px 16px; - text-decoration: none; - font-size: 25px; - font-family: 'Roboto', Tahoma, Geneva, Verdana, sans-serif; - color: #818181; - display: block; - } - - .selected { - color: #e1e1e1; - } - - :hover { - color: #f1f1f1; - cursor: pointer; - } -} diff --git a/src/app/components/document-list/document-list.component.spec.ts b/src/app/components/document-list/document-list.component.spec.ts deleted file mode 100644 index 2ba5f52..0000000 --- a/src/app/components/document-list/document-list.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import {async, ComponentFixture, TestBed} from '@angular/core/testing'; - -import {DocumentListComponent} from './document-list.component'; - -describe('DocumentListComponent', () => { - let component: DocumentListComponent; - let fixture: ComponentFixture; - - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [DocumentListComponent] - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(DocumentListComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/components/document-list/document-list.component.ts b/src/app/components/document-list/document-list.component.ts deleted file mode 100644 index 6a68c2f..0000000 --- a/src/app/components/document-list/document-list.component.ts +++ /dev/null @@ -1,36 +0,0 @@ -import {Component, OnDestroy, OnInit} from '@angular/core'; -import {Observable, Subscription} from 'rxjs'; - -import {DocumentService} from 'src/app/services/document.service'; - -@Component({ - selector: 'app-document-list', - templateUrl: './document-list.component.html', - styleUrls: ['./document-list.component.scss'] -}) -export class DocumentListComponent implements OnInit, OnDestroy { - documents: Observable; - currentDoc: string; - private _docSub: Subscription; - - constructor(private documentService: DocumentService) { - } - - ngOnInit() { - this.documents = this.documentService.documents; - this._docSub = this.documentService.currentDocument.subscribe(doc => this.currentDoc = doc.id); - } - - ngOnDestroy() { - this._docSub.unsubscribe(); - } - - loadDoc(id: string) { - this.documentService.getDocument(id); - } - - newDoc() { - this.documentService.newDocument(); - } - -} diff --git a/src/app/components/document/document.component.html b/src/app/components/document/document.component.html deleted file mode 100644 index 093deaa..0000000 --- a/src/app/components/document/document.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/components/document/document.component.scss b/src/app/components/document/document.component.scss deleted file mode 100644 index f97544b..0000000 --- a/src/app/components/document/document.component.scss +++ /dev/null @@ -1,12 +0,0 @@ -textarea { - position: fixed; - width: calc(100% - 235px); - height: 100%; - right: 0; - top: 0; - font-size: 18pt; - padding-top: 20px; - resize: none; - border: none; - padding: 20px 0px 20px 15px; -} diff --git a/src/app/components/document/document.component.spec.ts b/src/app/components/document/document.component.spec.ts deleted file mode 100644 index 5f113c4..0000000 --- a/src/app/components/document/document.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import {async, ComponentFixture, TestBed} from '@angular/core/testing'; - -import {DocumentComponent} from './document.component'; - -describe('DocumentComponent', () => { - let component: DocumentComponent; - let fixture: ComponentFixture; - - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [DocumentComponent] - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(DocumentComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/components/document/document.component.ts b/src/app/components/document/document.component.ts deleted file mode 100644 index 8bb37ba..0000000 --- a/src/app/components/document/document.component.ts +++ /dev/null @@ -1,32 +0,0 @@ -import {Component, OnDestroy, OnInit} from '@angular/core'; -import {DocumentService} from 'src/app/services/document.service'; -import {Subscription} from 'rxjs'; -import {Document} from 'src/app/models/document'; -import {startWith} from 'rxjs/operators'; - -@Component({ - selector: 'app-document', - templateUrl: './document.component.html', - styleUrls: ['./document.component.scss'] -}) -export class DocumentComponent implements OnInit, OnDestroy { - document: Document; - private _docSub: Subscription; - - constructor(private documentService: DocumentService) { - } - - ngOnInit() { - this._docSub = this.documentService.currentDocument.pipe( - startWith({id: '', doc: 'Select an existing document or create a new one to get started'}) - ).subscribe(document => this.document = document); - } - - ngOnDestroy() { - this._docSub.unsubscribe(); - } - - editDoc() { - this.documentService.editDocument(this.document); - } -} From 300b84ea85c92b22089766e9ad6a2f449b231d46 Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 19 Jan 2020 14:39:19 +0100 Subject: [PATCH 2/5] Refactor postlist and feed --- src/app/components/feed/feed.component.ts | 45 +- .../feed/postlist/postlist.component.html | 25 -- .../feed/postlist/postlist.component.ts | 2 +- src/app/models/post.ts | 41 +- src/app/services/feed/feed.service.ts | 410 +++++++++--------- src/manifest.webmanifest | 2 +- 6 files changed, 259 insertions(+), 266 deletions(-) diff --git a/src/app/components/feed/feed.component.ts b/src/app/components/feed/feed.component.ts index baf1aa8..e41d509 100644 --- a/src/app/components/feed/feed.component.ts +++ b/src/app/components/feed/feed.component.ts @@ -1,6 +1,6 @@ import {Component, OnInit} from '@angular/core'; import {Post} from 'src/app/models/post'; -import {FeedService} from 'src/app/services/feed/feed.service'; +import {FeedService, Sort} from 'src/app/services/feed/feed.service'; import {Activitylist} from 'src/app/models/activity'; import {DatasharingService} from '../../services/datasharing.service'; import {ActivityService} from 'src/app/services/activity/activity.service'; @@ -47,32 +47,33 @@ export class FeedComponent implements OnInit { this.activityService.activitylist.subscribe(response => { this.actionlist = response; }); - this.feedService.getPosts('NEW'); + this.feedService.getPosts(Sort.NEW); this.feedService.posts.subscribe(response => { this.parentSelectedPostList = response; }); - this.feedService.newPostsAvailable.subscribe(response => { - this.loadingNew = response; - }); - this.feedService.topPostsAvailable.subscribe(response => { - console.log(response); - this.loadingMostLiked = response; + this.feedService.postsAvailable.subscribe(available => { + this.loadingMostLiked = this.loadingNew = available; }); } - createPost(pElement, activityId: string) { - if (pElement && activityId && this.checked) { - this.feedService.createPostActivity(pElement.value, activityId).subscribe(() => { - pElement.value = ''; + /** + * Creates a new post + * @param postElement + * @param activityId + */ + createPost(postElement, activityId: string) { + if (postElement && activityId && this.checked) { + this.feedService.createPostActivity(postElement.value, activityId).subscribe(() => { + postElement.value = ''; this.textInputValue = ''; this.view = 'new'; }, (error: IErrorResponse) => { this.errorOccurred = true; this.errorMessage = error.error.errors[0].message; }); - } else if (pElement) { - this.feedService.createPost(pElement.value).subscribe(() => { - pElement.value = ''; + } else if (postElement) { + this.feedService.createPost(postElement.value).subscribe(() => { + postElement.value = ''; this.textInputValue = ''; this.view = 'new'; }, (error: IErrorResponse) => { @@ -82,17 +83,25 @@ export class FeedComponent implements OnInit { } } + /** + * Fetches the next posts when scrolled + */ onScroll() { - console.log('scrolled'); this.feedService.getNextPosts(); } + /** + * Shows the feed sorted by new + */ showNew() { - this.feedService.getPosts('NEW'); + this.feedService.getPosts(Sort.NEW); } + /** + * Shows the feed sorted by top + */ showMostLiked() { - this.feedService.getPosts('TOP'); + this.feedService.getPosts(Sort.TOP); } /** diff --git a/src/app/components/feed/postlist/postlist.component.html b/src/app/components/feed/postlist/postlist.component.html index fcf28eb..5e4db88 100644 --- a/src/app/components/feed/postlist/postlist.component.html +++ b/src/app/components/feed/postlist/postlist.component.html @@ -1,24 +1,3 @@ - -
@@ -34,17 +13,14 @@
- {{post.author.name}} - @{{post.author.handle}}

  {{post.date}}

-

@@ -66,4 +42,3 @@
- diff --git a/src/app/components/feed/postlist/postlist.component.ts b/src/app/components/feed/postlist/postlist.component.ts index a6175b2..4112719 100644 --- a/src/app/components/feed/postlist/postlist.component.ts +++ b/src/app/components/feed/postlist/postlist.component.ts @@ -10,7 +10,7 @@ import {Router} from '@angular/router'; }) export class PostlistComponent implements OnInit { - @Input() childPostList: Array; + @Input() childPostList: Post[]; @Output() voteEvent = new EventEmitter(); selectedPost: Post; diff --git a/src/app/models/post.ts b/src/app/models/post.ts index 1ba01c3..eb4cb67 100644 --- a/src/app/models/post.ts +++ b/src/app/models/post.ts @@ -13,28 +13,27 @@ export class Post { author: Author; activity: Activity; - // TODO: constructor properties need normal names constructor( - pId: number, - pContent: string, - pHtmlContent: string, - pUpvotes: number, - pDownvotes: number, - pUserVote: string, - pDeletable: boolean, - pDate: string, - pAuthor: Author, - pactivity: Activity + id: number, + content: string, + htmlContent: string, + upvotes: number, + downvotes: number, + userVotes: string, + deletable: boolean, + date: string, + author: Author, + activity: Activity ) { - this.id = pId; - this.content = pContent; - this.htmlContent = pHtmlContent; - this.upvotes = pUpvotes; - this.downvotes = pDownvotes; - this.userVote = pUserVote; - this.deletable = pDeletable; - this.date = pDate; - this.author = pAuthor; - this.activity = pactivity; + this.id = id; + this.content = content; + this.htmlContent = htmlContent; + this.upvotes = upvotes; + this.downvotes = downvotes; + this.userVote = userVotes; + this.deletable = deletable; + this.date = date; + this.author = author; + this.activity = activity; } } diff --git a/src/app/services/feed/feed.service.ts b/src/app/services/feed/feed.service.ts index b6755a2..9e18e45 100644 --- a/src/app/services/feed/feed.service.ts +++ b/src/app/services/feed/feed.service.ts @@ -6,139 +6,202 @@ import {environment} from 'src/environments/environment'; import {Activity} from 'src/app/models/activity'; import {BehaviorSubject} from 'rxjs'; import {tap} from 'rxjs/operators'; +import {BaseService} from '../base.service'; + +const createPostGqlQuery = `mutation($content: String!) { + createPost(content: $content) { + id, + content, + htmlContent, + upvotes, + downvotes, + userVote, + deletable, + activity{ + id + name + description + points + }, + author{ + name, + handle, + profilePicture, + id}, + createdAt} +}`; + +const createPostActivityGqlQuery = `mutation($content: String!, $id: ID) { + createPost(content: $content activityId: $id) { + id, + content, + htmlContent, + upvotes, + downvotes, + userVote, + deletable, + activity{ + id + name + description + points + }, + author{ + name, + handle, + profilePicture, + id}, + createdAt} +}`; + +const upvotePostGqlQuery = `mutation($postId: ID!) { + vote(postId: $postId, type: UPVOTE) { + post{userVote upvotes downvotes} + } +}`; + +const downvotePostGqlQuery = `mutation($postId: ID!) { + vote(postId: $postId, type: DOWNVOTE) { + post{userVote upvotes downvotes} + } +}`; + +const getPostGqlQuery = `query($first: Int, $offset: Int, $sort: SortType){ + getPosts (first: $first, offset: $offset, sort: $sort) { + id, + content, + htmlContent, + upvotes, + downvotes, + userVote, + deletable, + activity{ + id + name + description + points + }, + author{ + name, + handle, + profilePicture, + id}, + createdAt} +}`; + +export enum Sort { + NEW = 'NEW', + TOP = 'TOP', +} @Injectable({ providedIn: 'root' }) -export class FeedService { +export class FeedService extends BaseService { + + constructor(private http: HttpClient) { + super(); + } - public newPostsAvailable = new BehaviorSubject(true); - public topPostsAvailable = new BehaviorSubject(true); + public postsAvailable = new BehaviorSubject(true); public posts: BehaviorSubject = new BehaviorSubject([]); - public newPosts: BehaviorSubject = new BehaviorSubject([]); - public mostLikedPosts: BehaviorSubject = new BehaviorSubject([]); - private activePostList = 'NEW'; - private mostLikedOffset = 0; - private newOffset = 0; + private activePostList: Sort = Sort.NEW; + private offset = 0; + private offsetStep = 10; - constructor(private http: HttpClient) { + /** + * Builds the body for a getPost request + * @param sort + * @param offset + * @param first + */ + private static buildGetPostBody(sort: string, offset: number, first: number = 10) { + return { + query: getPostGqlQuery, variables: { + first, + offset, + sort + } + }; } + /** + * Creates a new post + * @param pContent + */ public createPost(pContent: String) { - const headers = new Headers(); - headers.set('Content-Type', 'application/json'); - const body = { - query: `mutation($content: String!) { - createPost(content: $content) { - id, - content, - htmlContent, - upvotes, - downvotes, - userVote, - deletable, - activity{ - id - name - description - points - }, - author{ - name, - handle, - profilePicture, - id}, - createdAt} - }`, variables: { + query: createPostGqlQuery, + variables: { content: pContent } }; - return this.http.post(environment.graphQLUrl, body).pipe(tap(response => { - const updatedposts = this.newPosts.getValue(); - updatedposts.unshift(this.renderPost(response)); - this.newPosts.next(updatedposts); - this.setPost('NEW'); - })); + return this.createPostRequest(body); } + /** + * Creates a post with an activity + * @param pContent + * @param activityId + */ public createPostActivity(pContent: String, activityId: String) { - const headers = new Headers(); - headers.set('Content-Type', 'application/json'); - const body = { - query: `mutation($content: String!, $id: ID) { - createPost(content: $content activityId: $id) { - id, - content, - htmlContent, - upvotes, - downvotes, - userVote, - deletable, - activity{ - id - name - description - points - }, - author{ - name, - handle, - profilePicture, - id}, - createdAt} - }`, variables: { + query: createPostActivityGqlQuery, variables: { content: pContent, id: activityId } }; - return this.http.post(environment.graphQLUrl, body).pipe(tap(response => { - const updatedposts = this.newPosts.getValue(); - updatedposts.unshift(this.renderPost(response)); - this.newPosts.next(updatedposts); - this.setPost('NEW'); - })); + return this.createPostRequest(body); } - public upvote(postId: number): any { - const headers = new Headers(); - headers.set('Content-Type', 'application/json'); + /** + * Creates a new post with a given request. + * @param body + */ + private createPostRequest(body: { variables: any; query: string }) { + return this.http.post(environment.graphQLUrl, body, {headers: this.headers}) + .pipe(tap(response => { + if (this.activePostList === Sort.NEW) { + const updatedPosts = this.posts.getValue(); + updatedPosts.push(this.constructPost(response)); + this.posts.next(updatedPosts); + } + })); + } + /** + * Upvotes a post + * @param postId + */ + public upvote(postId: number): any { const body = { - query: `mutation($postId: ID!) { - vote(postId: $postId, type: UPVOTE) { - post{userVote upvotes downvotes} - } - }`, variables: { + query: upvotePostGqlQuery, variables: { postId } }; - return this.http.post(environment.graphQLUrl, body); + return this.http.post(environment.graphQLUrl, body, {headers: this.headers}); } - public downvote(pPostID: number): any { - const headers = new Headers(); - headers.set('Content-Type', 'application/json'); - + /** + * Downvotes a post + * @param postId + */ + public downvote(postId: number): any { const body = { - query: `mutation($postId: ID!) { - vote(postId: $postId, type: DOWNVOTE) { - post{userVote upvotes downvotes} - } - }`, variables: { - postId: pPostID + query: downvotePostGqlQuery, variables: { + postId } }; - return this.http.post(environment.graphQLUrl, body); + return this.http.post(environment.graphQLUrl, body, {headers: this.headers}); } + /** + * Deletes a post + * @param pPostID + */ public deletePost(pPostID: number): any { - const headers = new Headers(); - headers.set('Content-Type', 'application/json'); - const body = { query: `mutation($postId: ID!) { deletePost(postId: $postId) @@ -147,108 +210,43 @@ export class FeedService { } }; - return this.http.post(environment.graphQLUrl, body); + return this.http.post(environment.graphQLUrl, body, {headers: this.headers}); } - public getPosts(sort: string) { - if ((sort === 'NEW' && this.newPosts.getValue().length === 0) || - (sort === 'TOP' && this.mostLikedPosts.getValue().length === 0)) { - const headers = new Headers(); - headers.set('Content-Type', 'application/json'); - this.http.post(environment.graphQLUrl, this.buildJson(sort, 0)) - .subscribe(response => { - if (sort === 'NEW') { - this.newPosts.next(this.renderAllPosts(response)); - } else if (sort === 'TOP') { - this.mostLikedPosts.next(this.renderAllPosts(response)); - } - this.setPost(sort); - }); - } - this.setPost(sort); + /** + * Resets the post list and fetches new posts for the given sorting + * @param sort + */ + public getPosts(sort: Sort) { + this.offset = 0; + this.postsAvailable.next(true); + this.posts.next([]); + return this.http.post(environment.graphQLUrl, FeedService.buildGetPostBody(sort, 0), + {headers: this.headers}).subscribe(response => { + this.posts.next(this.constructAllPosts(response)); + this.activePostList = sort; + }); } + /** + * Fetches the next posts for the current sorting + */ public getNextPosts() { - if (this.activePostList === 'NEW' && this.newPostsAvailable) { - this.newOffset += 10; - const headers = new Headers(); - headers.set('Content-Type', 'application/json'); - this.http.post(environment.graphQLUrl, this.buildJson(this.activePostList, this.newOffset)) - .subscribe(response => { - let updatedposts = this.newPosts.getValue(); - updatedposts = updatedposts.concat(this.renderAllPosts(response)); - if (this.renderAllPosts(response).length < 1) { - this.newPostsAvailable.next(false); - } - this.newPosts.next(updatedposts); - this.setPost('NEW'); - }); - } else if (this.activePostList === 'TOP' && this.topPostsAvailable) { - this.mostLikedOffset += 10; - const headers = new Headers(); - headers.set('Content-Type', 'application/json'); - this.http.post(environment.graphQLUrl, this.buildJson(this.activePostList, this.mostLikedOffset)) - .subscribe(response => { - let updatedposts = this.mostLikedPosts.getValue(); - updatedposts = updatedposts.concat(this.renderAllPosts(response)); - if (this.renderAllPosts(response).length < 1) { - this.topPostsAvailable.next(false); - } - this.mostLikedPosts.next(updatedposts); - this.setPost('TOP'); - }); - } - } - - setPost(sort: string) { - this.activePostList = sort; - if (sort === 'NEW') { - this.posts.next(this.newPosts.getValue()); - } else if (sort === 'TOP') { - this.posts.next(this.mostLikedPosts.getValue()); - } - } - - buildJson(sort: string, offset: number) { - const body = { - query: `query($offset: Int, $sort: SortType){ - getPosts (first: 10, offset: $offset, sort: $sort) { - id, - content, - htmlContent, - upvotes, - downvotes, - userVote, - deletable, - activity{ - id - name - description - points - }, - author{ - name, - handle, - profilePicture, - id}, - createdAt} - }`, variables: { - offset, - sort - } - }; - return body; + this.offset += this.offsetStep; + const body = FeedService.buildGetPostBody(this.activePostList, this.offset); + this.http.post(environment.graphQLUrl, body, {headers: this.headers}) + .subscribe(response => { + const posts = this.constructAllPosts(response); + const updatedPostList = this.posts.getValue().concat(posts); + this.posts.next(updatedPostList); + if (posts.length < this.offsetStep) { + this.postsAvailable.next(false); + } + }); } - public renderPost(response: any): Post { + public constructPost(response: any): Post { const post = response.data.createPost; - 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; let profilePicture: string; if (post.author.profilePicture) { profilePicture = environment.greenvironmentUrl + post.author.profilePicture; @@ -269,20 +267,22 @@ export class FeedService { activity = null; } - return new Post(id, content, htmlContent, upvotes, downvotes, userVote, deletable, date, author, activity); + return new Post( + post.id, + post.content, + post.htmlContent, + post.upvotes, + post.downvotes, + post.userVote, + post.deletable, + date, + author, + activity); } - public renderAllPosts(pResponse: any): Array { + public constructAllPosts(response: any): Post[] { const posts = new Array(); - // let options = {year: 'numeric', month: 'short', day: 'numeric', hour: '' } - for (const post of pResponse.data.getPosts) { - 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; + for (const post of response.data.getPosts) { let profilePicture: string; if (post.author.profilePicture) { profilePicture = environment.greenvironmentUrl + post.author.profilePicture; @@ -302,7 +302,17 @@ export class FeedService { } else { activity = null; } - posts.push(new Post(id, content, htmlContent, upvotes, downvotes, userVote, deletable, date, author, activity)); + posts.push(new Post( + post.id, + post.content, + post.htmlContent, + post.upvotes, + post.downvotes, + post.userVote, + post.deletable, + date, + author, + activity)); } return posts; } diff --git a/src/manifest.webmanifest b/src/manifest.webmanifest index e659809..0aa39e6 100644 --- a/src/manifest.webmanifest +++ b/src/manifest.webmanifest @@ -48,4 +48,4 @@ "type": "image/png" } ] -} \ No newline at end of file +} From 98a58c697d2d0681f45d96820df70f396ea4e1aa Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 19 Jan 2020 15:30:28 +0100 Subject: [PATCH 3/5] Add retry handling to base and feed service --- src/app/services/base.service.ts | 28 +++++++++++++++++++++++++-- src/app/services/feed/feed.service.ts | 15 ++++++++------ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/app/services/base.service.ts b/src/app/services/base.service.ts index 937eb58..d65f950 100644 --- a/src/app/services/base.service.ts +++ b/src/app/services/base.service.ts @@ -1,14 +1,38 @@ import {Injectable} from '@angular/core'; -import {HttpHeaders} from '@angular/common/http'; +import { HttpErrorResponse, HttpHeaders} from '@angular/common/http'; +import {delay, mergeMap, retryWhen} from 'rxjs/operators'; +import {Observable, of, throwError} from 'rxjs'; + +const httpTooManyCode = 429; +const httpHeaderRateRetry = 'Retry-After'; @Injectable({ providedIn: 'root' }) export abstract class BaseService { protected headers: HttpHeaders; - protected constructor() { this.headers = new HttpHeaders(); this.headers.set('Content-Type', 'application/json'); } + + /** + * Retries a request according to the rate limit + * @param maxRetry + */ + protected retryRated(maxRetry = 3) { + let retries = maxRetry; + return (src: Observable) => { + return src.pipe(retryWhen(errors => errors.pipe(mergeMap(error => { + if (error.status === httpTooManyCode) { + const retryAfter = Number(error.headers.get(httpHeaderRateRetry) || 1) * 1000; + return of(error.status).pipe(delay(retryAfter)); + } else if (retries-- > 0) { + return of(error).pipe(delay(10000)); + } + return throwError(error); + })) + )); + }; + } } diff --git a/src/app/services/feed/feed.service.ts b/src/app/services/feed/feed.service.ts index 9e18e45..0b86821 100644 --- a/src/app/services/feed/feed.service.ts +++ b/src/app/services/feed/feed.service.ts @@ -1,5 +1,5 @@ import {Injectable} from '@angular/core'; -import {HttpClient} from '@angular/common/http'; +import {HttpClient, HttpErrorResponse} from '@angular/common/http'; import {Post} from 'src/app/models/post'; import {Author} from 'src/app/models/author'; import {environment} from 'src/environments/environment'; @@ -180,7 +180,7 @@ export class FeedService extends BaseService { } }; - return this.http.post(environment.graphQLUrl, body, {headers: this.headers}); + return this.http.post(environment.graphQLUrl, body, {headers: this.headers}).pipe(this.retryRated()); } /** @@ -194,7 +194,7 @@ export class FeedService extends BaseService { } }; - return this.http.post(environment.graphQLUrl, body, {headers: this.headers}); + return this.http.post(environment.graphQLUrl, body, {headers: this.headers}).pipe(this.retryRated()); } /** @@ -209,8 +209,8 @@ export class FeedService extends BaseService { postId: pPostID } }; - - return this.http.post(environment.graphQLUrl, body, {headers: this.headers}); + return this.http.post(environment.graphQLUrl, body, {headers: this.headers}) + .pipe(this.retryRated()); } /** @@ -222,7 +222,9 @@ export class FeedService extends BaseService { this.postsAvailable.next(true); this.posts.next([]); return this.http.post(environment.graphQLUrl, FeedService.buildGetPostBody(sort, 0), - {headers: this.headers}).subscribe(response => { + {headers: this.headers}) + .pipe(this.retryRated()) + .subscribe(response => { this.posts.next(this.constructAllPosts(response)); this.activePostList = sort; }); @@ -235,6 +237,7 @@ export class FeedService extends BaseService { this.offset += this.offsetStep; const body = FeedService.buildGetPostBody(this.activePostList, this.offset); this.http.post(environment.graphQLUrl, body, {headers: this.headers}) + .pipe(this.retryRated()) .subscribe(response => { const posts = this.constructAllPosts(response); const updatedPostList = this.posts.getValue().concat(posts); From 31e915d0745df4606a0bb6e8121243e0e5f69c6f Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 19 Jan 2020 15:41:46 +0100 Subject: [PATCH 4/5] Add retry handler to all BaseService extending services --- src/app/services/profile/profile.service.ts | 4 +++- src/app/services/search/search.service.ts | 3 ++- src/app/services/selfservice/self.service.ts | 4 +++- src/app/services/social/social.service.ts | 3 ++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/app/services/profile/profile.service.ts b/src/app/services/profile/profile.service.ts index c198c43..3a7b4ca 100644 --- a/src/app/services/profile/profile.service.ts +++ b/src/app/services/profile/profile.service.ts @@ -77,7 +77,9 @@ export class ProfileService extends BaseService { public getUserData(userId: string) { const headers = new Headers(); headers.set('Content-Type', 'application/json'); - this.http.post(environment.graphQLUrl, ProfileService.buildGetProfileBody(userId)).subscribe(result => { + this.http.post(environment.graphQLUrl, ProfileService.buildGetProfileBody(userId)) + .pipe(this.retryRated()) + .subscribe(result => { this.proflile.next(this.getProfileData(result)); return this.proflile; }); diff --git a/src/app/services/search/search.service.ts b/src/app/services/search/search.service.ts index 095089d..c86ff37 100644 --- a/src/app/services/search/search.service.ts +++ b/src/app/services/search/search.service.ts @@ -101,6 +101,7 @@ export class SearchService extends BaseService { */ public search(query: string): Observable { const body = SearchService.buildRequestBody(query); - return this.http.post(environment.graphQLUrl, body, {headers: this.headers}); + return this.http.post(environment.graphQLUrl, body, {headers: this.headers}) + .pipe(this.retryRated()); } } diff --git a/src/app/services/selfservice/self.service.ts b/src/app/services/selfservice/self.service.ts index 7f56a7b..283663b 100644 --- a/src/app/services/selfservice/self.service.ts +++ b/src/app/services/selfservice/self.service.ts @@ -62,6 +62,7 @@ export class SelfService extends BaseService { headers.set('Content-Type', 'application/json'); return this.http.post(url, SelfService.buildGetSelfBody(), {headers: this.headers}) + .pipe(this.retryRated()) .pipe(tap(response => { this.updateUserInfo(response); })); @@ -74,7 +75,8 @@ export class SelfService extends BaseService { public changeProfilePicture(file: any) { const formData: any = new FormData(); formData.append('profilePicture', file); - return this.http.post(environment.greenvironmentUrl + '/upload', formData); + return this.http.post(environment.greenvironmentUrl + '/upload', formData) + .pipe(this.retryRated()); } /** diff --git a/src/app/services/social/social.service.ts b/src/app/services/social/social.service.ts index 3148ad8..872d36a 100644 --- a/src/app/services/social/social.service.ts +++ b/src/app/services/social/social.service.ts @@ -36,6 +36,7 @@ export class SocialService extends BaseService { */ createGroup(name: string) { const body = SocialService.buildGroupCreateBody(name); - return this.http.post(environment.graphQLUrl, body, {headers: this.headers}); + return this.http.post(environment.graphQLUrl, body, {headers: this.headers}) + .pipe(this.retryRated()); } } From a4f6f9e4f758b9e9866c68da1a0e0f5a0c7bc497 Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 19 Jan 2020 16:07:06 +0100 Subject: [PATCH 5/5] Fix Posting and cleanup - Fix posting not showing the new post - Remove console.logs --- .../components/chatmanager/chatmanager.component.ts | 1 - src/app/components/feed/feed.component.ts | 13 ++++++++++--- src/app/components/group/group.component.ts | 3 --- .../main-navigation/main-navigation.component.ts | 4 ---- .../profile/fileUpload/fileUpload.component.ts | 2 +- src/app/components/profile/profile.component.ts | 1 - src/app/components/search/search.component.ts | 2 -- src/app/services/feed/feed.service.ts | 2 +- src/app/services/register/register.service.ts | 3 --- src/app/services/settings/settings.service.ts | 4 +--- 10 files changed, 13 insertions(+), 22 deletions(-) diff --git a/src/app/components/chatmanager/chatmanager.component.ts b/src/app/components/chatmanager/chatmanager.component.ts index 45216f2..ffed815 100644 --- a/src/app/components/chatmanager/chatmanager.component.ts +++ b/src/app/components/chatmanager/chatmanager.component.ts @@ -51,7 +51,6 @@ export class ChatmanagerComponent implements OnInit { refresh() { this.chatService.getAllChatsRaw() .subscribe(response => { - console.log(response); this.parentChats = this.chatService.renderAllChats(response.json()); }); } diff --git a/src/app/components/feed/feed.component.ts b/src/app/components/feed/feed.component.ts index 05dbcdf..1ceb1d9 100644 --- a/src/app/components/feed/feed.component.ts +++ b/src/app/components/feed/feed.component.ts @@ -39,7 +39,6 @@ export class FeedComponent implements OnInit { } ngOnInit() { - console.log('init feedcomponent'); this.data.currentUserInfo.subscribe(user => { this.user = user; this.loggedIn = user.loggedIn; @@ -67,7 +66,10 @@ export class FeedComponent implements OnInit { this.feedService.createPostActivity(postElement.value, activityId).subscribe(() => { postElement.value = ''; this.textInputValue = ''; - this.view = 'new'; + this.checked = false; + if (this.view !== 'new') { + this.showNew(); + } }, (error: IErrorResponse) => { this.errorOccurred = true; this.errorMessage = error.error.errors[0].message; @@ -76,7 +78,10 @@ export class FeedComponent implements OnInit { this.feedService.createPost(postElement.value).subscribe(() => { postElement.value = ''; this.textInputValue = ''; - this.view = 'new'; + this.checked = false; + if (this.view !== 'new') { + this.showNew(); + } }, (error: IErrorResponse) => { this.errorOccurred = true; this.errorMessage = error.error.errors[0].message; @@ -95,6 +100,7 @@ export class FeedComponent implements OnInit { * Shows the feed sorted by new */ showNew() { + this.view = 'new'; this.feedService.getPosts(Sort.NEW); } @@ -102,6 +108,7 @@ export class FeedComponent implements OnInit { * Shows the feed sorted by top */ showMostLiked() { + this.view = 'mostliked'; this.feedService.getPosts(Sort.TOP); } diff --git a/src/app/components/group/group.component.ts b/src/app/components/group/group.component.ts index de4ad53..76d6f9f 100644 --- a/src/app/components/group/group.component.ts +++ b/src/app/components/group/group.component.ts @@ -32,8 +32,6 @@ export class DialogCreateEventComponent { 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(); } @@ -69,7 +67,6 @@ export class GroupComponent implements OnInit { 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(); } } diff --git a/src/app/components/main-navigation/main-navigation.component.ts b/src/app/components/main-navigation/main-navigation.component.ts index 4e67c2b..14a60de 100644 --- a/src/app/components/main-navigation/main-navigation.component.ts +++ b/src/app/components/main-navigation/main-navigation.component.ts @@ -121,7 +121,6 @@ export class MainNavigationComponent implements OnInit { }` }; this.http.post(url, body).subscribe(response => { - console.log(response.text()); }); this.loggedIn = false; const user = new User(); @@ -131,12 +130,10 @@ export class MainNavigationComponent implements OnInit { } 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); @@ -151,7 +148,6 @@ export class MainNavigationComponent implements OnInit { 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); diff --git a/src/app/components/profile/fileUpload/fileUpload.component.ts b/src/app/components/profile/fileUpload/fileUpload.component.ts index b4b5bf0..2e1c24d 100644 --- a/src/app/components/profile/fileUpload/fileUpload.component.ts +++ b/src/app/components/profile/fileUpload/fileUpload.component.ts @@ -54,7 +54,7 @@ export class DialogFileUploadComponent { }, (error) => { this.uploading = false; this.errorOccurred = true; - console.log(error); + console.error(error); if (error.error) { this.errorMessage = error.error.error; } else { diff --git a/src/app/components/profile/profile.component.ts b/src/app/components/profile/profile.component.ts index 147c1b7..41b8e57 100644 --- a/src/app/components/profile/profile.component.ts +++ b/src/app/components/profile/profile.component.ts @@ -60,7 +60,6 @@ export class ProfileComponent implements OnInit { this.userProfile = response; // tslint:disable-next-line:max-line-length this.userProfile.allowedToSendRequest = this.requestService.isAllowedToSendRequest(this.userProfile.userID, this.self); - console.log(this.userProfile.allowedToSendRequest); this.ownProfile = this.userProfile.userID === this.self.userID; this.rankname = this.levellist.getLevelName(this.userProfile.level); } else { diff --git a/src/app/components/search/search.component.ts b/src/app/components/search/search.component.ts index 732371e..bc379ea 100644 --- a/src/app/components/search/search.component.ts +++ b/src/app/components/search/search.component.ts @@ -44,8 +44,6 @@ export class SearchComponent implements OnInit { if (this.category === 'user') { this.loading = true; this.findUser(searchWord); - } else if (this.category === 'groupe') { - console.log('search group'); } } } diff --git a/src/app/services/feed/feed.service.ts b/src/app/services/feed/feed.service.ts index 0b86821..89659bb 100644 --- a/src/app/services/feed/feed.service.ts +++ b/src/app/services/feed/feed.service.ts @@ -163,7 +163,7 @@ export class FeedService extends BaseService { .pipe(tap(response => { if (this.activePostList === Sort.NEW) { const updatedPosts = this.posts.getValue(); - updatedPosts.push(this.constructPost(response)); + updatedPosts.unshift(this.constructPost(response)); this.posts.next(updatedPosts); } })); diff --git a/src/app/services/register/register.service.ts b/src/app/services/register/register.service.ts index 6eb16af..2eac62a 100644 --- a/src/app/services/register/register.service.ts +++ b/src/app/services/register/register.service.ts @@ -26,7 +26,6 @@ export class RegisterService { return this.http.post(url, this.buildJson(registration)) .subscribe(response => { - console.log(response.text()); this.registerSuccess(); this.updateUserInfo(response.json()); }, errorCb @@ -34,8 +33,6 @@ export class RegisterService { } public registerSuccess() { - console.log('alles supi dupi'); - // do routing this.router.navigateByUrl(''); } diff --git a/src/app/services/settings/settings.service.ts b/src/app/services/settings/settings.service.ts index 00c590f..1e14f03 100644 --- a/src/app/services/settings/settings.service.ts +++ b/src/app/services/settings/settings.service.ts @@ -20,9 +20,7 @@ export class SettingsService { 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()); - }); + this.http.post(url, body).subscribe(); } public buildJsonDarkMode(setting_: string): any {