diff options
Diffstat (limited to 'src/app')
40 files changed, 960 insertions, 1411 deletions
diff --git a/src/app/app-constants.module.ts b/src/app/app-constants.module.ts index f8722f7..39538e0 100644 --- a/src/app/app-constants.module.ts +++ b/src/app/app-constants.module.ts @@ -14,7 +14,7 @@ export class AppConstants { public static API_COMMENT_URL = AppConstants.BASE_API_URL + '/Comment'; public static PAGE_SIZE = 10; - public static FALLBACK_PROFILE_ICON = 'assets/images/feed/profile-pic.png'; + public static FALLBACK_PROFILE_ICON = 'assets/icons/tabler-icon-user.svg'; public static SESSION_TOKEN_KEY = 'UserCred'; public static ADMIN_ROLE_NAME = 'Admin'; diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 0d83079..4367db7 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -8,7 +8,6 @@ import { ProfileSettingsComponent } from './components/profile-settings/profile- import { NotFoundComponent } from './components/not-found/not-found.component'; import { PostPageComponent } from './components/post-page/post-page.component'; import {AdminPanelPageComponent} from './components/admin-panel-page/admin-panel-page.component'; -import {CommentPageComponent} from './components/comment-page/comment-page.component'; const routes: Routes = [ { path: '', component: FeedComponent }, @@ -17,7 +16,6 @@ const routes: Routes = [ { path: 'profile/:username', component: ProfileComponent }, { path: 'profile/:username/settings', component: ProfileSettingsComponent }, { path: 'post/:id', component: PostPageComponent }, - { path: 'comment/:id', component: CommentPageComponent }, { path: 'admin-panel', component: AdminPanelPageComponent }, { path: 'not-found', component: NotFoundComponent }, { path: '**', component: NotFoundComponent } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 1bf44ad..47651d4 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -6,6 +6,7 @@ import { MatInputModule } from '@angular/material/input'; import { MatButtonModule } from '@angular/material/button'; import { MatFormFieldModule } from '@angular/material/form-field'; import { HttpClientModule } from '@angular/common/http'; +import { ClipboardModule } from 'ngx-clipboard'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @@ -22,9 +23,9 @@ import { SuccessBarComponent } from './components/success-bar/success-bar.compon import { PostPageComponent } from './components/post-page/post-page.component'; import { AdminPanelPageComponent } from './components/admin-panel-page/admin-panel-page.component'; import { CommentComponent } from './components/comment/comment.component'; -import { CommentPageComponent } from './components/comment-page/comment-page.component'; import { PostAttachmentComponent } from './components/post-attachment/post-attachment.component'; import { RouterModule } from '@angular/router'; +import { NavbarComponent } from './components/navbar/navbar.component'; @NgModule({ declarations: [ @@ -42,8 +43,8 @@ import { RouterModule } from '@angular/router'; PostPageComponent, AdminPanelPageComponent, CommentComponent, - CommentPageComponent, - PostAttachmentComponent + PostAttachmentComponent, + NavbarComponent, ], imports: [ BrowserModule.withServerTransition({ appId: 'serverApp' }), @@ -54,7 +55,8 @@ import { RouterModule } from '@angular/router'; MatInputModule, MatButtonModule, HttpClientModule, - RouterModule + RouterModule, + ClipboardModule ], providers: [], bootstrap: [AppComponent] diff --git a/src/app/components/admin-panel-page/admin-panel-page.component.css b/src/app/components/admin-panel-page/admin-panel-page.component.css index 1f98e20..ec7aa5d 100644 --- a/src/app/components/admin-panel-page/admin-panel-page.component.css +++ b/src/app/components/admin-panel-page/admin-panel-page.component.css @@ -1,42 +1,5 @@ -#content { - max-width: 22em; - justify-content: start; -} - -hr { - width: calc(100% - 1em); - color: black; - border: 1px solid black; -} - -#navigation { - width: 100%; - display: flex; -} - -#navigation > * { - flex: 1; - margin-left: .4em; -} - -.submit-btn:first-of-type { - margin-left: 0 !important; -} - -#all-languages, #all-technologies { - display: flex; - flex-wrap: wrap; -} - -.flexbox { - display: flex; -} - -.flexbox > * { - flex: 1; - margin-left: 1em; -} - -.flexbox > *:first-child { - margin-left: 0; +.sec-info { + width: fit-content; + background-color: #424242; + margin: 0 0.3em 0.3em 0; } diff --git a/src/app/components/admin-panel-page/admin-panel-page.component.html b/src/app/components/admin-panel-page/admin-panel-page.component.html index 31f0849..bc4a71f 100644 --- a/src/app/components/admin-panel-page/admin-panel-page.component.html +++ b/src/app/components/admin-panel-page/admin-panel-page.component.html @@ -1,85 +1,118 @@ -<!-- <app-loading *ngIf="!dataArrived"></app-loading> --> +<app-navbar></app-navbar> -<main id="content" *ngIf="!dataArrived"> - <nav id="navigation"> - <button class="submit-btn" (click)="backToProfile()">ᐊ Back to profile</button> - <button class="submit-btn" (click)="backToFeed()">ᐊ Back to feed</button> - <button class="submit-btn" (click)="logout()">Logout</button> - </nav> - <hr> - <article class="scroll-standalone"> - <app-success-bar></app-success-bar> - <app-error-bar></app-error-bar> +<app-loading *ngIf="!dataArrived"></app-loading> - <button type="button" class="submit-btn edit-btn" (click)="toggleLanguages()">▼ Edit Languages ▼</button> - <form [formGroup]="languageForm" (ngSubmit)="submitLanguages()" *ngIf="showLanguages"> - <div class="input-selection"> - <label>Create language:</label> - <input type="text" class="input-field" formControlName="languageCreate" placeholder="New language name"> - </div> - <label>Update language:</label> - <div class="flexbox input-selection"> - <input type="text" class="input-field" formControlName="updateLanguageOldName" placeholder="Old language name"> - <input type="text" class="input-field" formControlName="updateLanguageNewName" placeholder="New language name"> - </div> - <label>Delete language:</label> - <div class="flexbox input-selection"> - <input type="text" class="input-field" formControlName="deleteLanguageName" placeholder="Language name"> - </div> - <button class="submit-btn" type="submit">Modify languages</button> - <hr> - Available languages: - <div id="all-languages"> - <div class="user-language" *ngFor="let lang of availableLanguages"> - {{ lang.name }} +<main class="scroll-standalone under-navbar centered-content flex-col" *ngIf="dataArrived"> + <app-success-bar></app-success-bar> + <app-error-bar></app-error-bar> + + <div class="card width-full"> + <section> + <button type="button" class="fg-focus width-full border-faded-slim padding-dot3 lighter-hover click-effect" (click)="toggleLanguages()"> + ▼ Edit Languages ▼ + </button> + <form class="flex-col margin-top-bot-dot3" [formGroup]="languageForm" (ngSubmit)="submitLanguages()" *ngIf="showLanguages"> + <label class="fg-focus"> + Create language: + </label> + <input type="text" class="fancy-input width-full border-faded-slim border-bottom-only" formControlName="languageCreate" placeholder="New language name"> + + <label class="fg-focus"> + Update language: + </label> + <div class="flex-row flexible-children"> + <input type="text" class="fancy-input border-faded-slim border-bottom-only margin-right-dot2" formControlName="updateLanguageOldName" placeholder="Old language name"> + <input type="text" class="fancy-input border-faded-slim border-bottom-only" formControlName="updateLanguageNewName" placeholder="New language name"> </div> - </div> - <hr> - </form> - <button type="button" class="submit-btn edit-btn" (click)="toggleTechnologies()">▼ Edit Technologies ▼</button> - <form [formGroup]="technologyForm" (ngSubmit)="submitTechnologies()" *ngIf="showTechnologies"> - <div class="input-selection"> - <label>Create technology:</label> - <input type="text" class="input-field" formControlName="technologyCreate" placeholder="New technology name"> - </div> - <label>Update technology:</label> - <div class="flexbox input-selection"> - <input type="text" class="input-field" formControlName="updateTechnologyOldName" placeholder="Old technology name"> - <input type="text" class="input-field" formControlName="updateTechnologyNewName" placeholder="New technology name"> - </div> - <label>Delete technology:</label> - <div class="flexbox input-selection"> - <input type="text" class="input-field" formControlName="deleteTechnologyName" placeholder="Technology name"> - </div> - <button class="submit-btn" type="submit">Modify technologies</button> - <hr> - Available technologies: - <div id="all-technologies"> - <div class="user-technology" *ngFor="let tech of availableTechnologies"> - {{ tech.name }} + <label class="fg-focus"> + Delete language: + </label> + <input type="text" class="fancy-input width-full border-faded-slim border-bottom-only" formControlName="deleteLanguageName" placeholder="Language name"> + + <button class="width-full border-faded-slim padding-dot3 lighter-hover click-effect border-radius-dot3" type="submit"> + Modify languages + </button> + <section class="border-faded-slim padding-dot4 margin-top-dot4"> + <div class="none-message" *ngIf="availableLanguages.length === 0"> + No languages in database! + </div> + <div *ngIf="availableLanguages.length > 0"> + Available languages: + </div> + <div class="flex-row margin-top-dot4" *ngFor="let lang of availableLanguages"> + <div class="sec-info border-radius-dot5r padding-dot2"> + {{ lang.name }} + </div> + </div> + </section> + </form> + </section> + <section> + <button type="button" class="fg-focus width-full border-faded-slim padding-dot3 lighter-hover click-effect margin-top-dot4" (click)="toggleTechnologies()"> + ▼ Edit Technologies ▼ + </button> + <form class="flex-col margin-top-bot-dot3" [formGroup]="technologyForm" (ngSubmit)="submitTechnologies()" *ngIf="showTechnologies"> + <label class="fg-focus"> + Create technology: + </label> + <input type="text" class="fancy-input width-full border-faded-slim border-bottom-only" formControlName="technologyCreate" placeholder="New technology name"> + + <label class="fg-focus"> + Update technology: + </label> + <div class="flex-row flexible-children"> + <input type="text" class="fancy-input border-faded-slim border-bottom-only margin-right-dot2" formControlName="updateTechnologyOldName" placeholder="Old technology name"> + <input type="text" class="fancy-input border-faded-slim border-bottom-only" formControlName="updateTechnologyNewName" placeholder="New technology name"> </div> - </div> - <hr> - </form> - <button type="button" class="submit-btn delete-btn" (click)="toggleDeletions()">▼ Deletions ▼</button> - <form [formGroup]="deleteForm" (ngSubmit)="submitDelete()" *ngIf="showDeletions"> - <div class="input-selection"> - <label>Delete user by Id:</label> - <input type="text" class="input-field" formControlName="deleteUser" placeholder="User Id"> - </div> + <label class="fg-focus"> + Delete technology: + </label> + <input type="text" class="fancy-input width-full border-faded-slim border-bottom-only" formControlName="deleteTechnologyName" placeholder="Technology name"> + + <button class="width-full border-faded-slim padding-dot3 lighter-hover click-effect border-radius-dot3" type="submit"> + Modify technology + </button> + <section class="border-faded-slim padding-dot4 margin-top-dot4"> + <div class="none-message" *ngIf="availableTechnologies.length === 0"> + No technologies in database! + </div> + <div *ngIf="availableTechnologies.length > 0"> + Available technologies: + </div> + <div class="flex-row margin-top-dot4" *ngFor="let tech of availableTechnologies"> + <div class="sec-info border-radius-dot5r padding-dot2"> + {{ tech.name }} + </div> + </div> + </section> + </form> + </section> + <section> + <button type="button" class="fg-focus width-full border-faded-slim padding-dot3 lighter-hover click-effect margin-top-dot4" (click)="toggleDeletions()"> + ▼ Deletions ▼ + </button> + <form class="flex-col margin-top-bot-dot3" [formGroup]="deleteForm" (ngSubmit)="submitDelete()" *ngIf="showDeletions"> + <label class="fg-focus"> + Delete user by Id: + </label> + <input type="text" class="fancy-input width-full border-faded-slim border-bottom-only" formControlName="deleteUser" placeholder="User Id"> + + <label class="fg-focus"> + Delete post by Id: + </label> + <input type="text" class="fancy-input width-full border-faded-slim border-bottom-only" formControlName="deletePost" placeholder="Post Id"> + + <label class="fg-focus"> + Delete comment by Id: + </label> + <input type="text" class="fancy-input width-full border-faded-slim border-bottom-only" formControlName="deleteComment" placeholder="Comment Id"> - <div class="input-selection"> - <label>Delete post by Id:</label> - <input type="text" class="input-field" formControlName="deletePost" placeholder="Post Id"> - </div> - <div class="input-selection"> - <label>Delete comment by Id:</label> - <input type="text" class="input-field" formControlName="deleteComment" placeholder="Comment Id"> - </div> - <button class="submit-btn" type="submit">Delete</button> - <hr> - </form> - </article> + <button class="width-full border-faded-slim padding-dot3 lighter-hover click-effect border-radius-dot3" type="submit"> + Delete + </button> + </form> + </section> + </div> </main> diff --git a/src/app/components/admin-panel-page/admin-panel-page.component.ts b/src/app/components/admin-panel-page/admin-panel-page.component.ts index 9beb8bc..d1070b5 100644 --- a/src/app/components/admin-panel-page/admin-panel-page.component.ts +++ b/src/app/components/admin-panel-page/admin-panel-page.component.ts @@ -103,6 +103,24 @@ export class AdminPanelPageComponent implements OnInit { this.loadAvailableTechnologies(); } + private loadAvailableLanguages(): void { + this._languageService.getAllLanguagesWithSessionStorageRequest().subscribe({ + next: (result: object) => { + this.availableLanguages = result as Language[]; + this.dataArrived = true; + } + }); + } + + private loadAvailableTechnologies(): void { + this._technologyService.getAllTechnologiesWithSessionStorageRequest().subscribe({ + next: (result: object) => { + this.availableTechnologies = result as Technology[]; + this.dataArrived = true; + } + }); + } + // Navigation backToProfile(): void { @@ -186,13 +204,6 @@ export class AdminPanelPageComponent implements OnInit { this.loadAvailableLanguages(); } - private loadAvailableLanguages(): void { - this._languageService.getAllLanguagesWithSessionStorageRequest().subscribe({ - next: (result: object) => { - this.availableLanguages = result as Language[]; - } - }); - } // Technology modifying @@ -262,14 +273,6 @@ export class AdminPanelPageComponent implements OnInit { this.loadAvailableTechnologies(); } - private loadAvailableTechnologies(): void { - this._technologyService.getAllTechnologiesWithSessionStorageRequest().subscribe({ - next: (result: object) => { - this.availableTechnologies = result as Technology[]; - } - }); - } - // Deletions toggleDeletions(): void { diff --git a/src/app/components/comment-page/comment-page.component.css b/src/app/components/comment-page/comment-page.component.css deleted file mode 100644 index f9dc390..0000000 --- a/src/app/components/comment-page/comment-page.component.css +++ /dev/null @@ -1,26 +0,0 @@ -#content { - justify-content: flex-start !important; -} - -#content > * { - width: 100%; -} - -.many-buttons { - width: 100%; - display: flex; -} - -.many-buttons > * { - flex: 1; - margin-right: .3em; -} - -.many-buttons > *:last-of-type { - margin-right: 0; -} - -.submit-btn { - margin: 0 auto; - margin-bottom: .5em; -} diff --git a/src/app/components/comment-page/comment-page.component.html b/src/app/components/comment-page/comment-page.component.html deleted file mode 100644 index ae114da..0000000 --- a/src/app/components/comment-page/comment-page.component.html +++ /dev/null @@ -1,16 +0,0 @@ -<app-loading *ngIf="!loaded"></app-loading> - -<main id="content" *ngIf="loaded"> - <nav> - <button class="submit-btn" type="submit" (click)="toPost()">ᐊ Back to post</button> - </nav> - <app-comment [paramId]="commentId.toString()"></app-comment> - <nav class="many-buttons" *ngIf="editable"> - <button class="submit-btn" (click)="editComment()">Edit comment</button> - <button class="submit-btn delete-btn" (click)="deleteComment()">Delete comment</button> - </nav> - <form [formGroup]="editCommentFormGroup" (ngSubmit)="editComment()"> - <input type="text" *ngIf="editingComment" placeholder="New comment message" class="input-field" formControlName="newCommentMessage"> - <input type="submit" style="display: none" /> - </form> -</main> diff --git a/src/app/components/comment-page/comment-page.component.ts b/src/app/components/comment-page/comment-page.component.ts deleted file mode 100644 index 5d256bf..0000000 --- a/src/app/components/comment-page/comment-page.component.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; -import { Title } from '@angular/platform-browser'; -import { Router } from '@angular/router'; -import { Guid } from 'guid-typescript'; -import { CommentService } from 'src/app/services/comment.service'; -import { TokenService } from 'src/app/services/token.service'; -import { Comment } from 'src/models/comment.model'; - -@Component({ - selector: 'app-comment-page', - templateUrl: './comment-page.component.html', - styleUrls: ['./comment-page.component.css'] -}) -export class CommentPageComponent implements OnInit { - private _title = 'Comment'; - public loaded = false; - public loggedIn = false; - public editable = false; - public editingComment = false; - public commentId: Guid; - public comment: Comment; - public editCommentFormGroup: FormGroup; - - constructor(private _titleService: Title, private _router: Router, private _fb: FormBuilder, private _tokenService: TokenService, private _commentService: CommentService){ - this._titleService.setTitle(this._title); - } - - ngOnInit(): void { - this.loggedIn = this._tokenService.getTokenFromSessionStorage() !== ''; - this.commentId = Guid.parse(this._router.url.substring(9)); - - // Gets the post and the logged in user and compares them, - // to determine if the current post is made by the user - this._commentService.getCommentRequest(this.commentId).subscribe({ - next: (result: object) => { - this.comment = result as Comment; - if (this.loggedIn) { - this.editable = this.comment.issuerUsername === this._tokenService.getUsernameFromSessionStorageToken(); - this.editCommentFormGroup.get('newCommentMessage')?.setValue(this.comment.message); - } - this.loaded = true; - }, - error: () => { - this._router.navigate(['/not-found']); - } - }); - - this.editCommentFormGroup = this._fb.group({ - newCommentMessage: new FormControl('') - }); - } - - toPost(): void { - this._router.navigate(['/post/' + this.comment.postId]); - } - - editComment(): void { - if (this._tokenService.getTokenFromSessionStorage() === '') { - this._router.navigate(['/login']); - return; - } - - if (this.editingComment) { - const newMessage = this.editCommentFormGroup.get('newCommentMessage')?.value; - - if (newMessage !== '' && newMessage !== this.comment.message) { - console.log(this.commentId); - this._commentService.putCommentWithSessionStorageRequest(this.commentId, this.comment.postId, newMessage).subscribe({ - next: () => { - this.reloadPage(); - } - }); - } - } - this.editingComment = !this.editingComment; - } - - deleteComment(): void { - this._commentService.deleteCommentWithSessionStorage(this.commentId).subscribe({ - next: () => { - this.toPost(); - } - }); - } - - private reloadPage(): void { - this._router.routeReuseStrategy.shouldReuseRoute = () => false; - this._router.onSameUrlNavigation = 'reload'; - this._router.navigate([this._router.url]); - } -} diff --git a/src/app/components/comment/comment.component.css b/src/app/components/comment/comment.component.css index 419cbf8..48d9174 100644 --- a/src/app/components/comment/comment.component.css +++ b/src/app/components/comment/comment.component.css @@ -1,56 +1,30 @@ -.comment { - display: flex; - flex-direction: column; - width: 100%; - - margin: .5em auto; +.left-pane { box-sizing: border-box; - padding: .5em; - background-color: var(--card-bg); -} - -.comment:first-child { - margin-top: 0; } /* Author */ -.author { - display: flex; - margin-bottom: .2em; -} - -.author:hover { - cursor: pointer; -} - -.author > img { - width: 1.7em; - height: 1.7em; - margin-right: .2em; +.author-picture { + width: 2.2em; + height: 2.2em; } -.author-info > .name { - font-size: .8em; -} +/* Content */ -.author-info > .handle { - font-size: .6em; - color: gray; +.content { + padding: 0 var(--card-padding); } -/* Content */ - .message { - margin: .3em 0; - word-break: break-all; + word-break: break-word; } -.timestamp { - font-size: .5em; - color: gray; +.comment-details { + margin-bottom: calc(var(--card-padding) / 1.5); + padding: 0.2em 0; } -.message:hover, .timestamp:hover { - cursor: pointer; +.comment-details > * { + margin-left: 1.1em; } + diff --git a/src/app/components/comment/comment.component.html b/src/app/components/comment/comment.component.html index e46bdb7..9403ea2 100644 --- a/src/app/components/comment/comment.component.html +++ b/src/app/components/comment/comment.component.html @@ -1,21 +1,46 @@ <app-loading *ngIf="!loaded"></app-loading> -<section class="comment rounded-border" *ngIf="loaded"> - <summary class="author" (click)="goToAuthorProfile()"> - <img class="round-image" [src]="user.profilePictureURL"> - <div class="author-info"> - <div class="name"> +<section class="card flex-row" [hidden]="loaded" (mouseleave)="resetShareBtn()"> + <aside class="left-pane"> + <img class="author-picture round-image hover-half-opacity" [src]="user.profilePictureURL" (click)="goToAuthorProfile()"> + </aside> + <main class="content flexible"> + <summary class="font-size-dot8 text-vertical-middle hover-half-opacity" (click)="goToAuthorProfile()"> + <span> {{ user.firstName }} {{ user.lastName }} - </div> - <div class="handle"> + </span> + <span class="fg-faded"> @{{ user.userName }} - </div> - </div> - </summary> - <article class="message" (click)="goToCommentPage()"> - {{ comment.message }} - </article> - <time class="timestamp" (click)="goToCommentPage()"> - {{ timeCreated }} - </time> + </span> + </summary> + <form [formGroup]="editCommentFormGroup" *ngIf="editingComment" (ngSubmit)="editComment()"> + <textarea class="textarea-new-msg width-full border-faded-slim border-bottom-only padding-dot2 margin-bot-dot5" rows="1" formControlName="newCommentMessage" placeholder="What's on your mind?"></textarea> + <button type="submit" class="border-faded-slim width-full padding-dot2 lighter-hover click-effect border-radius-dot3 margin-bot-dot5"> + Update Comment + </button> + </form> + <article class="message margin-top-bot-dot2" *ngIf="!editingComment"> + {{ comment.message }} + </article> + <section class="comment-details flex-row flex-justify-end font-size-dot7 border-faded-slim border-bottom-only"> + <time class="flex-row flex-center-align-items"> + <img class="height-font" src="/assets/icons/tabler-icon-calendar-time.svg"> + <span> + {{ timeCreated }} + </span> + </time> + </section> + <section class="flex-row justify-children-center align-children-center"> + <button class="padding-dot2 lighter-hover click-effect border-radius-dot3" *ngIf="loggedInAuthor" (click)="toggleEditing()"> + <img src="/assets/icons/tabler-icon-edit.svg"> + </button> + <button #share ngxClipboard [cbContent]="getPostLink()" class="flexible padding-dot2 lighter-hover click-effect border-radius-dot3" (click)="showCopiedMessage()"> + <img src="/assets/icons/tabler-icon-link.svg"> + Share + </button> + <button class="padding-dot2 lighter-hover click-effect border-radius-dot3" *ngIf="loggedInAuthor" (click)="deleteComment()"> + <img src="/assets/icons/tabler-icon-trash.svg"> + </button> + </section> + </main> </section> diff --git a/src/app/components/comment/comment.component.ts b/src/app/components/comment/comment.component.ts index 7da896d..2a54f92 100644 --- a/src/app/components/comment/comment.component.ts +++ b/src/app/components/comment/comment.component.ts @@ -1,7 +1,9 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { AfterViewInit, Component, ElementRef, Input, OnInit, Renderer2, ViewChild } from '@angular/core'; +import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; import { Router } from '@angular/router'; import { Guid } from 'guid-typescript'; import { CommentService } from 'src/app/services/comment.service'; +import { TokenService } from 'src/app/services/token.service'; import { UserService } from 'src/app/services/user.service'; import { Comment } from 'src/models/comment.model'; import { User } from 'src/models/identity/user.model'; @@ -11,14 +13,20 @@ import { User } from 'src/models/identity/user.model'; templateUrl: './comment.component.html', styleUrls: ['./comment.component.css'] }) -export class CommentComponent implements OnInit { +export class CommentComponent implements OnInit, AfterViewInit { public loaded = false; + public loggedInAuthor = false; + public editingComment = false; public user: User; public comment: Comment; public timeCreated: string; @Input() paramId: string; + public editCommentFormGroup: FormGroup; + @ViewChild('share') shareBtn: ElementRef; + private _defaultShareBtnInnerHTML: string; + private _linkShared = false; - constructor(private _router: Router, private _commentService: CommentService, private _userService: UserService) + constructor(private _router: Router, private _commentService: CommentService, private _userService: UserService, private _tokenService: TokenService, private _fb: FormBuilder, private _elem: ElementRef, private _renderer: Renderer2) { } ngOnInit(): void { @@ -33,22 +41,86 @@ export class CommentComponent implements OnInit { this.loadUser(); } }); + + this.editCommentFormGroup = this._fb.group({ + newCommentMessage: new FormControl('') + }); } private loadUser(): void { this._userService.getUserByUsernameRequest(this.comment.issuerUsername).subscribe({ next: (result: object) => { Object.assign(this.user, result); + + if (this._tokenService.getTokenFromSessionStorage() !== '') { + this.loggedInAuthor = this._tokenService.getUsernameFromSessionStorageToken() === this.comment.issuerUsername; + this.editCommentFormGroup.get('newCommentMessage')?.setValue(this.comment.message); + } + this.loaded = true; } }); } + ngAfterViewInit(): void { + this._defaultShareBtnInnerHTML = this.shareBtn.nativeElement.innerHTML; + } + goToAuthorProfile(): void { this._router.navigate(['/profile/' + this.comment.issuerUsername]); } - goToCommentPage(): void { - this._router.navigate(['/comment/' + this.comment.commentId]); + toggleEditing(): void { + this.editingComment = !this.editingComment; + } + + editComment(): void { + if (this._tokenService.getTokenFromSessionStorage() === '') { + this._router.navigate(['/login']); + return; + } + + if (this.editingComment) { + const newMessage = this.editCommentFormGroup.get('newCommentMessage')?.value; + + if (newMessage !== '' && newMessage !== this.comment.message) { + this._commentService.putCommentWithSessionStorageRequest(Guid.parse(this.paramId), this.comment.postId, newMessage).subscribe({ + next: () => { + this.reloadPage(); + } + }); + } + } + this.editingComment = !this.editingComment; + } + + deleteComment(): void { + this._commentService.deleteCommentWithSessionStorage(Guid.parse(this.paramId)).subscribe({ + next: () => { + this.reloadPage(); + } + }); + } + + private reloadPage(): void { + this._router.routeReuseStrategy.shouldReuseRoute = () => false; + this._router.onSameUrlNavigation = 'reload'; + this._router.navigate([this._router.url]); + } + + resetShareBtn(): void { + if (this._linkShared) { + this._renderer.setProperty(this.shareBtn.nativeElement, 'innerHTML', this._defaultShareBtnInnerHTML); + this._linkShared = false; + } + } + + showCopiedMessage(): void { + this._renderer.setProperty(this.shareBtn.nativeElement, 'innerHTML', 'Link copied to clipboard!'); + this._linkShared = true; + } + + getPostLink(): string { + return location.origin + '/comment/' + this.paramId; } } diff --git a/src/app/components/feed/feed.component.css b/src/app/components/feed/feed.component.css index 3d22349..295a379 100644 --- a/src/app/components/feed/feed.component.css +++ b/src/app/components/feed/feed.component.css @@ -1,171 +1,27 @@ -#feed-page { - height: 100%; - max-width: 40em; - box-sizing: border-box; - border: .5em solid var(--bg-color); - - margin: 0 auto; - - display: flex; -} - -@media screen and (max-width: 750px) { - #profile-bar { - display: none !important; - } - #top-bar-profile-pic { - display: initial; - } -} -@media screen and (min-width: 750px) { - #profile-bar { - display: initial; - } - #top-bar-profile-pic { - display: none !important; - } -} - -/* Content */ - -#feed-content { - flex: 1; - display: flex; - flex-direction: column; -} - -/* Profile bar */ - -#profile-bar { - width: 20%; - height: fit-content; - display: flex; - flex-direction: column; - align-items: center; - - box-sizing: border-box; - background-color: var(--bg-color); - - margin-right: .5em; - padding-bottom: 1em; - padding: .5em; - border-radius: .6em; -} - -#profile-bar-profile-pic { - width: 7em; - height: 7em; - box-sizing: border-box; - padding: .5em; -} - -#profile-bar-name { - text-align: center; -} - -#profile-bar-username { - margin: .5em 0; -} - -#profile-bar > #profile-info { - display: flex; - flex-direction: column; - align-items: center; -} - -/* Top bar */ - -#top-bar { - display: flex; - flex-direction: row; - width: 98%; - margin: 0 auto; - margin-bottom: .5em; - box-sizing: border-box; -} - -#top-bar-profile-pic { - height: 2.5em; - width: 2.5em; - margin-right: .5em; -} - -#top-bar-profile-pic > img { - height: inherit; - width: inherit; -} - -#top-bar-open-chat { - /* Until implemented */ +section:empty { display: none; } -/* Create post */ - -#create-post-form { +#create-post { width: 100%; - position: relative; - display: flex; - flex-direction: column; - box-sizing: border-box; -} - -#form-inputs { - display: flex; -} - -#top-bar-create-post { - flex: 1; - font-size: inherit; - width: 100%; - height: 100%; - margin: 0 auto; - box-sizing: border-box; - border: 2px solid var(--bg-color); - border-radius: .6em; + margin-top: 1em; } -#file-upload { - font-size: inherit; - color: transparent; - width: 1.5em; - height: 1.5em; +#attachments-btns img, .file-button > input { + height: 1.4em; + width: 1.4em; } -#file-upload:hover { - cursor: pointer; +.file-button { + position: relative; } -#attachment-img { - height: 1.5em; - width: 1.5em; +.file-button > img { position: absolute; - right: .4em; pointer-events: none; } -/* Posts */ - -#no-posts-msg { - width: 100%; - margin-top: 1em; - color: gray; - text-align: center; -} - -/* Elements, that act as buttons */ - -#profile-bar > #profile-info:hover, -#top-bar-profile-pic:hover { - cursor: pointer; -} - -/* Can't copy text from */ - -#profile-bar, -.vote { - -webkit-user-select: none; /* Safari */ - -moz-user-select: none; /* Firefox */ - -ms-user-select: none; /* IE10+/Edge */ - user-select: none; /* Standard */ +.file-button > input { + font-size: inherit; + color: transparent; } diff --git a/src/app/components/feed/feed.component.html b/src/app/components/feed/feed.component.html index 5ff2dca..4832456 100644 --- a/src/app/components/feed/feed.component.html +++ b/src/app/components/feed/feed.component.html @@ -1,48 +1,38 @@ +<app-navbar></app-navbar> + <app-loading *ngIf="!dataArrived"></app-loading> -<main id="feed-page" *ngIf="dataArrived"> - <aside id="profile-bar" class="round-image rounded-border"> - <summary id="profile-info" (click)="goToProfile()"> - <img id="profile-bar-profile-pic" class="round-image" [src]="user.profilePictureURL" alt=""/> - <div id="profile-bar-name"> - {{ user.firstName }} {{ user.lastName }} - </div> - <div id="profile-bar-username"> - @{{ user.userName }} +<main class="centered-content scroll-standalone under-navbar flex-col flex-justify-start" *ngIf="dataArrived"> + <form id="create-post" class="card flex-col" [formGroup]="createPostFormGroup" (ngSubmit)="createPost()"> + <textarea class="textarea-new-msg border-faded-slim border-bottom-only padding-dot2" rows="1" formControlName="newPostMessage" placeholder="What's on your mind?"></textarea> + <section class="flex-row flex-justify-start align-children-center padding-top-bot-dot5"> + <div class="file-button hover-half-opacity click-effect"> + <img src="/assets/icons/tabler-icon-paperclip.svg"> + <input type="file" formControlName="fileUpload" (change)="onFileUpload($event)" multiple> </div> - </summary> - <button class="submit-btn" (click)="goToSettings()">Settings</button> - <button class="submit-btn" (click)="logout()">Logout</button> - </aside> - <section id="feed-content"> - <nav id="top-bar"> - <img id="top-bar-profile-pic" class="round-image" [src]="user.profilePictureURL" alt="" (click)="goToProfile()"> - <form id="create-post-form" class="rounded-border" [formGroup]="createPostFormGroup" (ngSubmit)="createPost()"> - <section id="form-inputs"> - <input id="top-bar-create-post" type="text" formControlName="newPostMessage" placeholder="What's on your mind?"/> - <input type="submit" style="display: none" /> <!-- You need this element, so when you press enter the request is sent --> - <img id="attachment-img" src="assets/images/paper-clip.png"> - <input id="file-upload" type="file" formControlName="fileUpload" (change)="onFileUpload($event)" multiple> - </section> - <section class="form-attachments"> - <div *ngFor="let file of files" class="form-attachment"> - {{ file.name ? file.name : 'Attachment' }} - <div class="remove-form-attachment" (click)="removeAttachment(file.name)"> - ☒ - </div> - </div> - </section> - </form> - <img id="top-bar-open-chat" src="assets/images/feed/chat-pic.png" alt=""/> - </nav> - <section id="posts" class="scroll-standalone" (scroll)="onScroll($event)"> - <div id="no-posts-msg" *ngIf="posts.length === 0"> - None of your friends have posted anything yet!<br> - Try refreshing your page! - </div> - <div *ngFor="let friendPost of posts; let i = index" class="post"> - <app-post [paramId]="friendPost.postId.toString()" [index]="i"></app-post> + </section> + <section class="flex-row bot-padding-dot6ger"> + <div *ngFor="let file of files" class="form-attachment border-faded-slim flexible flex-row flex-no-wrap flex-center-align-items padding-dot2 margin-top-bot-dot2"> + <div class="flexible"> + {{ file.name ? file.name : 'Attachment' }} + </div> + <div class="flex-col hover-half-opacity border-radius-dot2 click-effect" (click)="removeAttachment(file.name)"> + <img src="/assets/icons/tabler-icon-x.svg"> + </div> </div> </section> + <button class="border-faded-slim padding-dot2 lighter-hover click-effect border-radius-dot3"> + Post + </button> + </form> + <hr class="card-hr"> + <section id="posts" (scroll)="onScroll($event)"> + <div class="text-centered" *ngIf="posts.length === 0"> + None of your friends have posted anything yet!<br> + Try refreshing your page! + </div> + <div *ngFor="let friendPost of posts" class="post"> + <app-post [paramId]="friendPost.postId.toString()"></app-post> + </div> </section> </main> diff --git a/src/app/components/login/login.component.css b/src/app/components/login/login.component.css index 103f5c0..e69de29 100644 --- a/src/app/components/login/login.component.css +++ b/src/app/components/login/login.component.css @@ -1,32 +0,0 @@ -form { - width: 100%; -} - -#content hr { - width: 100%; - border: 1px solid black; - box-sizing: border-box; -} - -.submit-btn { - transition: 0.2s; -} - -.input-selection:nth-of-type(1) { - margin-top: 1.2em; -} - -.submit-btn { - margin-bottom: .2em; -} - -.redirect-to-register { - color: var(--focus-color); - background-color: var(--bg-color); - border-color: var(--focus-color); -} - -.redirect-to-register:hover { - border-color: black !important; - color: black; -} diff --git a/src/app/components/login/login.component.html b/src/app/components/login/login.component.html index 9f74faa..29aebf9 100644 --- a/src/app/components/login/login.component.html +++ b/src/app/components/login/login.component.html @@ -1,30 +1,25 @@ -<main id="content"> - <summary class="title">Login</summary> +<main class="centered-content flex-col flex-center-align-items flex-justify-center height-full"> + <summary class="title card width-full margin-0 padding-dot2">Login</summary> - <form [formGroup]="loginUserFormGroup" (ngSubmit)="onSubmit()"> - <hr> - - <section class="input-selection"> - <input type="text" placeholder="Username" class="input-field" formControlName="username" required> - <label class="input-field-label">Username</label> + <app-error-bar class="width-full margin-top-dot4"></app-error-bar> + <form class="width-full card padding-dot6" [formGroup]="loginUserFormGroup" (ngSubmit)="onSubmit()"> + <section class="input-selection width-full"> + <input type="text" placeholder="Username" class="fancy-input width-full border-faded-slim border-bottom-only" formControlName="username" required> + <label class="fancy-input-label width-full">Username</label> <div class="input-errors"> <label *ngIf="loginUserFormGroup.get('username')?.errors?.required" class="error">*Required</label> </div> </section> - <section class="input-selection"> - <input type="password" placeholder="Password" class="input-field" formControlName="password" required> - <label class="input-field-label">Password</label> - + <input type="password" placeholder="Password" class="fancy-input width-full border-faded-slim border-bottom-only" formControlName="password" required> + <label class="fancy-input-label width-full">Password</label> <div class="input-errors"> <label *ngIf="loginUserFormGroup.get('password')?.errors?.required" class="error">*Required</label> </div> </section> - <hr> - <button class="submit-btn" type="submit">Submit</button> - <app-error-bar></app-error-bar> + <button class="border-faded-slim padding-dot3 lighter-hover click-effect border-radius-dot3 width-full" type="submit">Submit</button> </form> - <button class="submit-btn redirect-to-register" (click)="onRedirectRegister()">New to DevHive? Register instead</button> + <button class="fg-focus border-faded-slim padding-dot3 lighter-hover click-effect border-radius-dot3 width-full margin-top-dot4" (click)="onRedirectRegister()">New to DevHive? Register instead</button> </main> diff --git a/src/app/components/navbar/navbar.component.css b/src/app/components/navbar/navbar.component.css new file mode 100644 index 0000000..d02e928 --- /dev/null +++ b/src/app/components/navbar/navbar.component.css @@ -0,0 +1,38 @@ +#navbar { + height: var(--navbar-height); + width: 100%; + background-color: var(--card-bg); +} + +#nav-contents img { + height: 1.9em; + width: 1.9em; +} + +@media screen and (max-width: 30rem) { + #nav-username { + display: none; + } + + #navbar { + font-size: 0.8em; + } +} + +#nav-profile-picture { + padding: 0.1em; +} + +#nav-profile-picture img { + height: 1.8em; + width: 1.8em; +} + +.nav-item { + margin-left: 0.2em; + padding: 0 0.1em; +} + +.nav-item:first-child { + margin-left: 0; +} diff --git a/src/app/components/navbar/navbar.component.html b/src/app/components/navbar/navbar.component.html new file mode 100644 index 0000000..d05f6e1 --- /dev/null +++ b/src/app/components/navbar/navbar.component.html @@ -0,0 +1,45 @@ +<nav id="navbar"> + <div id="nav-contents" class="centered-content flex-row padding-dot3 flex-center-align-items"> + <div class="nav-item border-radius-dot2 flex-row flex-center-align-items light-hover hover-half-opacity click-effect" (click)="goToProfile()" *ngIf="loggedIn"> + <div id="nav-profile-picture" class="flex-col"> + <img class="round-image" [src]="user.profilePictureURL"> + </div> + <div id="nav-username" class="font-size-dot9 flex-col"> + <div class="padding-dot2"> + @{{ user.userName }} + </div> + </div> + </div> + <div class="nav-item flex-col border-radius-dot2 light-hover hover-half-opacity click-effect" (click)="goToFeed()" *ngIf="loggedIn"> + <img src="/assets/icons/tabler-icon-home.svg"> + </div> + <div class="nav-item flex-col border-radius-dot2 light-hover hover-half-opacity click-effect" style="display: none"> + <!-- Trending functionality isn't implemented yet! --> + <img src="/assets/icons/tabler-icon-trending-up.svg"> + </div> + <div class="nav-item flex-col border-radius-dot2 light-hover hover-half-opacity click-effect" style="display: none"> + <!-- Chat functionality isn't implemented yet! --> + <img src="/assets/icons/tabler-icon-message-circle.svg"> + </div> + <div class="nav-item flex-col border-radius-dot2 light-hover hover-half-opacity click-effect" style="display: none"> + <!-- Search functionality isn't implemented yet! --> + <img src="/assets/icons/tabler-icon-search.svg"> + </div> + <div class="flexible"> + <!-- This element serves as a spacer --> + </div> + <div class="nav-item flex-col border-radius-dot2 light-hover hover-half-opacity click-effect" (click)="goToSettings()" *ngIf="loggedIn"> + <img src="/assets/icons/tabler-icon-settings.svg"> + </div> + <div class="nav-item flex-col border-radius-dot2 light-hover hover-half-opacity click-effect" (click)="logout()" *ngIf="loggedIn"> + <img src="/assets/icons/tabler-icon-logout.svg"> + </div> + <div class="nav-item flex-row flex-center-align-items border-radius-dot2 light-hover hover-half-opacity click-effect side-padding-dot3" (click)="goToLogin()" *ngIf="!loggedIn"> + Login + <img src="/assets/icons/tabler-icon-login.svg"> + </div> + <div class="flexible" *ngIf="!loggedIn"> + <!-- This element serves as a spacer --> + </div> + </div> +</nav> diff --git a/src/app/components/navbar/navbar.component.ts b/src/app/components/navbar/navbar.component.ts new file mode 100644 index 0000000..85f07d1 --- /dev/null +++ b/src/app/components/navbar/navbar.component.ts @@ -0,0 +1,62 @@ +import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { TokenService } from 'src/app/services/token.service'; +import { UserService } from 'src/app/services/user.service'; +import { User } from 'src/models/identity/user.model'; + +@Component({ + selector: 'app-navbar', + templateUrl: './navbar.component.html', + styleUrls: ['./navbar.component.css'] +}) +export class NavbarComponent implements OnInit { + public user: User; + public loggedIn: Boolean; + + constructor(private _router: Router, private _userService: UserService, private _tokenService: TokenService) + { } + + ngOnInit(): void { + this.loggedIn = this._tokenService.getTokenFromSessionStorage() !== ''; + + this.user = this._userService.getDefaultUser(); + this.user.userName = ''; // so you don't always see a flash of 'Gosho' + + this._userService.getUserFromSessionStorageRequest().subscribe({ + next: (res: object) => { + Object.assign(this.user, res); + }, + }); + } + + goToProfile(): void { + // Properly reload the page + // Needed because if you're on someone's profile and go to yours, angular won't refresh the page (with your info) + this._router.routeReuseStrategy.shouldReuseRoute = () => false; + this._router.onSameUrlNavigation = 'reload'; + + this._router.navigate(['/profile/' + this.user.userName]); + } + + goToFeed(): void { + if (this.loggedIn) { + this._router.navigate(['/']); + } + else { + this.goToLogin(); + } + } + + goToSettings(): void { + this._router.navigate(['/profile/' + this.user.userName + '/settings']); + } + + logout(): void { + this._tokenService.logoutUserFromSessionStorage(); + this.goToLogin(); + } + + goToLogin(): void { + this._router.navigate(['/login']); + } +} diff --git a/src/app/components/not-found/not-found.component.html b/src/app/components/not-found/not-found.component.html index 83d73ce..4d1165d 100644 --- a/src/app/components/not-found/not-found.component.html +++ b/src/app/components/not-found/not-found.component.html @@ -1,10 +1,18 @@ -<main id="content"> - <summary class="title"> - Page not found! - </summary> - <hr> - <nav id="back-btns"> - <button class="submit-btn" type="submit" (click)="backToFeed()">Back to feed</button> - <button class="submit-btn" type="submit" (click)="backToLogin()">Back to login</button> - </nav> +<main class="centered-content flex-col flex-center-align-items flex-justify-center height-full"> + <div class="card width-full padding-dot6"> + <summary class="title"> + Page not found! + </summary> + <hr class="card-hr"> + <nav class="flex-row flexible-children padding-dot2"> + <button class="flex-row flex-justify-center flex-center-align-items border-faded-slim padding-dot3 lighter-hover click-effect border-radius-dot3 margin-right-dot2" (click)="backToFeed()"> + <img src="/assets/icons/tabler-icon-home.svg"> + Back to feed + </button> + <button class="flex-row flex-justify-center flex-center-align-items border-faded-slim padding-dot3 lighter-hover click-effect border-radius-dot3" (click)="backToLogin()"> + <img src="/assets/icons/tabler-icon-login.svg"> + Back to login + </button> + </nav> + </div> </main> diff --git a/src/app/components/post-attachment/post-attachment.component.css b/src/app/components/post-attachment/post-attachment.component.css index 58e8a82..6cdab0b 100644 --- a/src/app/components/post-attachment/post-attachment.component.css +++ b/src/app/components/post-attachment/post-attachment.component.css @@ -1,29 +1,3 @@ -/* Attachment */ - -.attachment { - width: 100%; - height: 100%; - display: flex; - border: 2px solid black; - border-top: 0; - border-radius: 0 0 .6em .6em; - padding: .4em; - padding-top: 1em; - margin-top: calc(-0.8em - 2px); -} - -.attachment:hover { - cursor: pointer; -} - -.attachment-name { - flex: 1; -} - -.attachment-type { - margin-left: .2em; -} - /* Full attachment */ .show-full-attachment { @@ -33,9 +7,6 @@ width: 100vw; height: 100vh; background-color: #000000AF; - display: flex; - justify-content: center; - align-items: center; z-index: 2; } @@ -46,27 +17,7 @@ .attachment-download { max-width: 420px !important; - margin: 0 .4em; + background-color: var(--card-bg); text-decoration: none; - color: white; - border-color: white; - background-color: black; -} - -.attachment-download:hover { - background-color: white; - color: var(--focus-color); -} - -.close { - position: fixed; - top: .2em; - right: .2em; - font-size: 2em; - color: whitesmoke; -} - -.close:hover { - color: var(--failure); - cursor: pointer; + color: inherit; } diff --git a/src/app/components/post-attachment/post-attachment.component.html b/src/app/components/post-attachment/post-attachment.component.html index 401068c..e5e4b5a 100644 --- a/src/app/components/post-attachment/post-attachment.component.html +++ b/src/app/components/post-attachment/post-attachment.component.html @@ -1,16 +1,16 @@ -<figure class="attachment" (click)="toggleShowFull()"> - <summary class="attachment-name"> +<figure class="form-attachment border-faded-slim flexible flex-row flex-no-wrap padding-dot2 hover-half-opacity margin-top-bot-dot2" (click)="toggleShowFull()"> + <div class="flex-col flex-justify-center margin-right-dot2" [ngSwitch]="fileType"> + <img *ngSwitchCase="'img'" src="/assets/icons/tabler-icon-photo.svg"> + <img *ngSwitchDefault src="/assets/icons/tabler-icon-file.svg"> + </div> + <summary class="flex-col flex-justify-center"> {{ fileName }} </summary> - <summary class="attachment-type"> - {{ fileType }} - </summary> </figure> -<div class="show-full-attachment" *ngIf="showFull" (click)="toggleShowFull()"> +<div class="show-full-attachment flex-row flex-justify-center flex-center-align-items" *ngIf="showFull" (click)="toggleShowFull()"> <img class="attachment-img" *ngIf="isImage" src="{{paramURL}}"> - <a class="attachment-download submit-btn" *ngIf="!isImage" href="{{paramURL}}">Download attachment</a> - <div class="close"> - ☒ - </div> + <a class="attachment-download border-faded-slim padding-dot4 hover-half-opacity click-effect border-radius-dot3" *ngIf="!isImage" href="{{paramURL}}"> + Download attachment + </a> </div> diff --git a/src/app/components/post-attachment/post-attachment.component.ts b/src/app/components/post-attachment/post-attachment.component.ts index 1d00def..1aeca37 100644 --- a/src/app/components/post-attachment/post-attachment.component.ts +++ b/src/app/components/post-attachment/post-attachment.component.ts @@ -18,7 +18,12 @@ export class PostAttachmentComponent implements OnInit { ngOnInit(): void { this.isImage = this.paramURL.includes('image') && !this.paramURL.endsWith('pdf'); this.fileType = this.isImage ? 'img' : 'raw'; - this.fileName = this.paramURL.match('(?<=\/)(?:.(?!\/))+$')?.pop() ?? 'Attachment'; + if (this.fileType === 'img') { + this.fileName = this.paramURL.match(/(?!\/)+?[^\/]+?(?=\.)/g)?.pop() ?? 'Attachment'; + } + else { + this.fileName = this.paramURL.match(/[^\/]+?$/g)?.pop() ?? 'Attachment'; + } } toggleShowFull(): void { diff --git a/src/app/components/post-page/post-page.component.css b/src/app/components/post-page/post-page.component.css index 4f2ae60..7405240 100644 --- a/src/app/components/post-page/post-page.component.css +++ b/src/app/components/post-page/post-page.component.css @@ -1,60 +1,3 @@ -#content { - justify-content: flex-start !important; -} - -#content > * { - width: 100%; -} - -.many-buttons { - width: 100%; - display: flex; -} - -.many-buttons > * { - flex: 1; - margin-right: .3em; -} - -.many-buttons > *:last-of-type { - margin-right: 0; -} - -#editPost { - display: flex; - position: relative; -} - -#new-message-input { - flex: 1; - box-sizing: border-box; -} - -#file-upload { - font-size: inherit; - color: transparent; - width: 1.99em; - height: 1.99em; - margin-left: .3em; -} - -#file-upload:hover { - cursor: pointer; -} - -#file-upload::-webkit-file-upload-button { - visibility: hidden; -} - -#attachment-img { - height: 1.99em; - width: 1.99em; - position: absolute; - right: 0; - pointer-events: none; -} - -.submit-btn { - margin: 0 auto; - margin-bottom: .5em; +main { + padding-top: 0.5em; } diff --git a/src/app/components/post-page/post-page.component.html b/src/app/components/post-page/post-page.component.html index 5da8cc7..cfca6c0 100644 --- a/src/app/components/post-page/post-page.component.html +++ b/src/app/components/post-page/post-page.component.html @@ -1,37 +1,23 @@ +<app-navbar></app-navbar> + <app-loading *ngIf="!dataArrived"></app-loading> -<main id="content" *ngIf="dataArrived"> - <nav> - <div class="many-buttons" *ngIf="loggedIn"> - <button class="submit-btn" type="submit" (click)="backToFeed()">ᐊ Back to feed</button> - <button class="submit-btn" type="submit" (click)="backToProfile()">ᐊ Back to profile</button> - </div> - <button class="submit-btn" type="submit" (click)="toLogin()" *ngIf="!loggedIn">Login</button> - </nav> - <app-post [paramId]="postId.toString()" [index]="0"></app-post> - <div class="many-buttons" *ngIf="editable"> - <button class="submit-btn" (click)="editPost()">Edit post</button> - <button class="submit-btn delete-btn" (click)="deletePost()">Delete post</button> - </div> - <form id="editPost" [formGroup]="editPostFormGroup" *ngIf="editingPost" (ngSubmit)="editPost()"> - <input id="new-message-input" type="text" placeholder="New post message" class="input-field" formControlName="newPostMessage"> - <img id="attachment-img" src="assets/images/paper-clip.png"> - <input id="file-upload" type="file" formControlName="fileUpload" (change)="onFileUpload($event)" multiple> - <input type="submit" style="display: none" /> +<main class="centered-content scroll-standalone under-navbar flex-col" *ngIf="dataArrived"> + <app-post [paramId]="postId.toString()"></app-post> + <form class="card flex-col width-full margin-0-top" [formGroup]="addCommentFormGroup" (ngSubmit)="addComment()"> + <textarea rows="1" placeholder="Add a new comment" class="textarea-new-msg border-faded-slim border-bottom-only padding-dot2 margin-bot-dot5" formControlName="newComment"></textarea> + <button class="border-faded-slim padding-dot2 lighter-hover click-effect border-radius-dot3" type="submit"> + Add Comment + </button> </form> - <figure class="form-attachments" *ngIf="editingPost"> - <div *ngFor="let file of files" class="form-attachment"> - {{ file.name ? file.name : 'Attachment' }} - <div class="remove-form-attachment" (click)="removeAttachment(file.name)"> - ☒ - </div> + <hr class="card-hr"> + <section> + <div class="text-centered" *ngIf="post?.comments?.length === 0"> + Nobody has comented on this post yet!<br> + Try refreshing the page! + </div> + <div class="comment" *ngFor="let comm of post?.comments"> + <app-comment [paramId]="comm.id.toString()"></app-comment> </div> - </figure> - <form [formGroup]="addCommentFormGroup" (ngSubmit)="addComment()"> - <input type="text" placeholder="Add comment" class="input-field" formControlName="newComment"> - <input type="submit" style="display: none" /> - </form> - <section class="comment" *ngFor="let comm of post?.comments"> - <app-comment [paramId]="comm.id.toString()"></app-comment> </section> </main> diff --git a/src/app/components/post-page/post-page.component.ts b/src/app/components/post-page/post-page.component.ts index a60f4da..0babfdf 100644 --- a/src/app/components/post-page/post-page.component.ts +++ b/src/app/components/post-page/post-page.component.ts @@ -7,7 +7,6 @@ import { CommentService } from 'src/app/services/comment.service'; import { PostService } from 'src/app/services/post.service'; import { TokenService } from 'src/app/services/token.service'; import { Post } from 'src/models/post.model'; -import { CloudinaryService } from 'src/app/services/cloudinary.service'; @Component({ selector: 'app-post-page', @@ -18,22 +17,17 @@ export class PostPageComponent implements OnInit { private _title = 'Post'; public dataArrived = false; public loggedIn = false; - public editable = false; - public editingPost = false; public postId: Guid; public post: Post; - public files: File[]; - public editPostFormGroup: FormGroup; public addCommentFormGroup: FormGroup; - constructor(private _titleService: Title, private _router: Router, private _fb: FormBuilder, private _tokenService: TokenService, private _postService: PostService, private _commentService: CommentService, private _cloudinaryService: CloudinaryService){ + constructor(private _titleService: Title, private _router: Router, private _fb: FormBuilder, private _tokenService: TokenService, private _postService: PostService, private _commentService: CommentService) { this._titleService.setTitle(this._title); } ngOnInit(): void { this.loggedIn = this._tokenService.getTokenFromSessionStorage() !== ''; this.postId = Guid.parse(this._router.url.substring(6)); - this.files = []; // Gets the post and the logged in user and compares them, // to determine if the current post is made by the user @@ -41,94 +35,19 @@ export class PostPageComponent implements OnInit { next: (result: object) => { this.post = result as Post; this.post.fileURLs = Object.values(result)[7]; - if (this.loggedIn) { - this.editable = this.post.creatorUsername === this._tokenService.getUsernameFromSessionStorageToken(); - this.editPostFormGroup.get('newPostMessage')?.setValue(this.post.message); - } - if (this.post.fileURLs.length > 0) { - this.loadFiles(); - } - else { - this.dataArrived = true; - } + + this.dataArrived = true; }, error: () => { this._router.navigate(['/not-found']); } }); - this.editPostFormGroup = this._fb.group({ - newPostMessage: new FormControl(''), - fileUpload: new FormControl('') - }); - this.addCommentFormGroup = this._fb.group({ newComment: new FormControl('') }); } - private loadFiles(): void { - for (const fileURL of this.post.fileURLs) { - this._cloudinaryService.getFileRequest(fileURL).subscribe({ - next: (result: object) => { - const file = result as File; - const tmp = { - name: fileURL.match('(?<=\/)(?:.(?!\/))+$')?.pop() ?? 'Attachment' - }; - - Object.assign(file, tmp); - this.files.push(file); - - if (this.files.length === this.post.fileURLs.length) { - this.dataArrived = true; - } - } - }); - } - } - - backToFeed(): void { - this._router.navigate(['/']); - } - - backToProfile(): void { - this._router.navigate(['/profile/' + this._tokenService.getUsernameFromSessionStorageToken()]); - } - - toLogin(): void { - this._router.navigate(['/login']); - } - - onFileUpload(event: any): void { - this.files.push(...event.target.files); - this.editPostFormGroup.get('fileUpload')?.reset(); - } - - removeAttachment(fileName: string): void { - this.files = this.files.filter(x => x.name !== fileName); - } - - editPost(): void { - if (this._tokenService.getTokenFromSessionStorage() === '') { - this.toLogin(); - return; - } - - if (this.editingPost) { - const newMessage = this.editPostFormGroup.get('newPostMessage')?.value; - - if (newMessage === '' && newMessage !== this.post.message) { - this._postService.putPostWithSessionStorageRequest(this.postId, newMessage, this.files).subscribe({ - next: () => { - this.reloadPage(); - } - }); - this.dataArrived = false; - } - } - this.editingPost = !this.editingPost; - } - addComment(): void { if (!this.loggedIn) { this._router.navigate(['/login']); @@ -139,21 +58,12 @@ export class PostPageComponent implements OnInit { if (newComment !== '' && newComment !== null) { this._commentService.createCommentWithSessionStorageRequest(this.postId, newComment).subscribe({ next: () => { - this.editPostFormGroup.reset(); this.reloadPage(); } }); } } - deletePost(): void { - this._postService.deletePostWithSessionStorage(this.postId).subscribe({ - next: () => { - this._router.navigate(['/profile/' + this._tokenService.getUsernameFromSessionStorageToken()]); - } - }); - } - private reloadPage(): void { this._router.routeReuseStrategy.shouldReuseRoute = () => false; this._router.onSameUrlNavigation = 'reload'; diff --git a/src/app/components/post/post.component.css b/src/app/components/post/post.component.css index 07d931f..1015564 100644 --- a/src/app/components/post/post.component.css +++ b/src/app/components/post/post.component.css @@ -1,129 +1,55 @@ -.post { - display: flex; - width: 98%; - - margin: .5em auto; +.left-pane { box-sizing: border-box; - padding: .5em; - background-color: var(--card-bg); - position: relative; -} - -.post:first-child { - margin-top: 0; -} - -hr { - border: 1px solid black; - width: 90%; } /* Author */ -.author { - display: flex; - margin-bottom: .2em; -} - -.author:hover { - cursor: pointer; -} - -.author > img { +.author-picture { width: 2.2em; height: 2.2em; - margin-right: .2em; -} - -.author-info > .handle { - font-size: .9em; - color: gray; } /* Content */ .content { - flex: 1; + padding: 0 var(--card-padding); } .message { - margin: .3em 0; - word-break: break-all; -} - -.bottom-post { - font-size: .5em; - color: gray; - display: flex; - align-items: center; + word-break: break-word; } -.separator { - margin: 0 .5em; +.post-details { + margin-bottom: calc(var(--card-padding) / 1.5); + padding: 0.2em 0; } -.comment-count { - font-size: 1em; +.post-details > * { + margin-left: 1.1em; } -.comment-count > img { - height: .8em; -} - -.message:hover, .timestamp:hover { - cursor: pointer; -} - -/* Rating */ - -.rating { - display: flex; - flex-direction: column; - align-items: center; - min-height: 4.4em; - margin: auto -.1em auto 0; -} - -.score { - flex: 1; - display: flex; - align-items: center; +.rating img { + height: 1.2em; + width: 1.2em; } +/* Edit */ -.vote { - display: flex; - align-items: center; - flex: 1; - - background: var(--card-bg); - font-size: 1em; - - border: 1px solid var(--card-bg); - box-sizing: border-box; - border-radius: .2em; - - } - -.vote:hover { - border: 1px solid var(--focus-color); - color: var(--focus-color); - cursor: pointer; +#attachments-btns img, .file-button > input { + height: 1.4em; + width: 1.4em; } -/* Attachments */ - -.attachments { - display: flex; - width: 98%; - margin: -.3em auto .5em auto; - flex-wrap: wrap; +.file-button { + position: relative; } -.attachments:empty { - display: none; +.file-button > img { + position: absolute; + pointer-events: none; } -.attachments > * { - flex: 1; +.file-button > input { + font-size: inherit; + color: transparent; } diff --git a/src/app/components/post/post.component.html b/src/app/components/post/post.component.html index 1603ebf..0c1cce2 100644 --- a/src/app/components/post/post.component.html +++ b/src/app/components/post/post.component.html @@ -1,48 +1,88 @@ <app-loading *ngIf="!loaded"></app-loading> -<section class="post rounded-border" *ngIf="loaded"> - <section class="content"> - <summary class="author" (click)="goToAuthorProfile()"> - <img class="round-image" [src]="user.profilePictureURL"> - <div class="author-info"> - <div class="name"> - {{ user.firstName }} {{ user.lastName }} - </div> - <div class="handle"> - @{{ user.userName }} - </div> - </div> +<section class="card flex-row" [hidden]="loaded" (mouseleave)="resetShareBtn()"> + <aside class="left-pane"> + <img class="author-picture round-image hover-half-opacity" [src]="user.profilePictureURL" (click)="goToAuthorProfile()"> + </aside> + <main class="content flexible"> + <summary class="font-size-dot8 text-vertical-middle hover-half-opacity" (click)="goToAuthorProfile()"> + <span> + {{ user.firstName }} {{ user.lastName }} + </span> + <span class="fg-faded"> + @{{ user.userName }} + </span> </summary> - <article class="message" (click)="goToPostPage()"> + <article class="message margin-top-bot-dot2" *ngIf="!editingPost"> {{ post.message }} </article> - <div class="bottom-post" (click)="goToPostPage()"> - <time class="timestamp"> - {{ timeCreated }} - </time> - <div class="separator"> - ║ + <section class="flex-row flexible-children" *ngIf="!editingPost"> + <figure *ngFor="let fileURL of post.fileURLs"> + <app-post-attachment [paramURL]="fileURL"></app-post-attachment> + </figure> + </section> + <form [formGroup]="editPostFormGroup" *ngIf="editingPost"> + <textarea class="textarea-new-msg width-full border-faded-slim border-bottom-only padding-dot2" rows="1" formControlName="newPostMessage" placeholder="What's on your mind?"></textarea> + <section class="flex-row flex-justify-start align-children-center top-bot-padding-dot6ger"> + <div class="file-button hover-half-opacity click-effect"> + <img src="/assets/icons/tabler-icon-paperclip.svg"> + <input type="file" formControlName="fileUpload" (change)="onFileUpload($event)" multiple> + </div> + </section> + </form> + <section class="flex-row bot-padding-dot6ger" *ngIf="editingPost"> + <div *ngFor="let file of files" class="form-attachment border-faded-slim flexible flex-row flex-no-wrap flex-center-align-items padding-dot2 margin-top-bot-dot2"> + <div class="flexible"> + {{ file.name ? file.name : 'Attachment' }} + </div> + <div class="flex-col hover-half-opacity border-radius-dot2 click-effect" (click)="removeAttachment(file.name)"> + <img src="/assets/icons/tabler-icon-x.svg"> + </div> </div> - <summary class="comment-count"> - {{ post.comments.length }} - <img src="assets/images/comment.png"> + </section> + <button class="border-faded-slim width-full padding-dot2 lighter-hover click-effect border-radius-dot3 margin-bot-dot5" *ngIf="editingPost" (click)="editPost()"> + Update Post + </button> + <section class="post-details flex-row flex-justify-end font-size-dot7 border-faded-slim border-bottom-only"> + <time class="flex-row flex-center-align-items"> + <img class="height-font" src="/assets/icons/tabler-icon-calendar-time.svg"> + <span> + {{ timeCreated }} + </span> + </time> + <summary class="flex-row flex-center-align-items"> + <img class="height-font" src="/assets/icons/tabler-icon-message-2.svg"> + <span> + {{ post.comments.length }} + </span> </summary> - </div> - </section> - <section class="rating"> - <button class="vote" (click)="votePost(true)"> - ᐃ + </section> + <section class="flex-row justify-children-center align-children-center"> + <button class="padding-dot2 lighter-hover click-effect border-radius-dot3" *ngIf="loggedInAuthor" (click)="toggleEditing()"> + <img src="/assets/icons/tabler-icon-edit.svg"> + </button> + <button class="flexible padding-dot2 lighter-hover click-effect border-radius-dot3" (click)="goToPostPage()"> + <img src="/assets/icons/tabler-icon-message-2.svg"> + Comment + </button> + <button #share ngxClipboard [cbContent]="getPostLink()" class="flexible padding-dot2 lighter-hover click-effect border-radius-dot3" (click)="showCopiedMessage()"> + <img src="/assets/icons/tabler-icon-link.svg"> + Share + </button> + <button class="padding-dot2 lighter-hover click-effect border-radius-dot3" *ngIf="loggedInAuthor" (click)="deletePost()"> + <img src="/assets/icons/tabler-icon-trash.svg"> + </button> + </section> + </main> + <aside class="rating flex-col flex-center-align-items"> + <button #upvote class="flex-col lighter-hover border-radius-dot2 click-effect" (click)="votePost(true)"> + <img src="/assets/icons/tabler-icon-chevron-up.svg"> </button> - <summary class="score"> + <summary class="top-bot-padding-dot2"> {{ votesNumber }} </summary> - <button class="vote" (click)="votePost(false)"> - ᐁ + <button #downvote class="flex-col lighter-hover border-radius-dot2 click-effect" (click)="votePost(false)"> + <img src="/assets/icons/tabler-icon-chevron-down.svg"> </button> - </section> + </aside> </section> -<aside class="attachments"> - <figure *ngFor="let fileURL of post.fileURLs"> - <app-post-attachment class="no-events" [paramURL]="fileURL"></app-post-attachment> - </figure> -</aside> diff --git a/src/app/components/post/post.component.ts b/src/app/components/post/post.component.ts index 24ecdb4..f0d8a44 100644 --- a/src/app/components/post/post.component.ts +++ b/src/app/components/post/post.component.ts @@ -1,6 +1,8 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { AfterViewInit, Component, ElementRef, Input, OnInit, Renderer2, ViewChild } from '@angular/core'; +import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; import { Router } from '@angular/router'; import { Guid } from 'guid-typescript'; +import { CloudinaryService } from 'src/app/services/cloudinary.service'; import { PostService } from 'src/app/services/post.service'; import { RatingService } from 'src/app/services/rating.service'; import { UserService } from 'src/app/services/user.service'; @@ -13,24 +15,33 @@ import { TokenService } from '../../services/token.service'; templateUrl: './post.component.html', styleUrls: ['./post.component.css'], }) -export class PostComponent implements OnInit { +export class PostComponent implements OnInit, AfterViewInit { public loaded = false; public user: User; public post: Post; public votesNumber: number; public timeCreated: string; @Input() paramId: string; - @Input() index: number; + @ViewChild('upvote') upvoteBtn: ElementRef; + @ViewChild('downvote') downvoteBtn: ElementRef; + @ViewChild('share') shareBtn: ElementRef; + private _defaultShareBtnInnerHTML: string; + private _linkShared = false; // For optimisation purposes public loggedIn = false; - private voteBtns: HTMLCollectionOf<HTMLElement>; + public loggedInAuthor = false; + public editingPost = false; + public files: File[]; + public editPostFormGroup: FormGroup; - constructor(private _postService: PostService, private _ratingServe: RatingService, private _userService: UserService, private _router: Router, private _tokenService: TokenService) { } + constructor(private _postService: PostService, private _ratingServe: RatingService, private _userService: UserService, private _router: Router, private _tokenService: TokenService, private _cloudinaryService: CloudinaryService, private _fb: FormBuilder, private _elem: ElementRef, private _renderer: Renderer2) + { } ngOnInit(): void { this.loggedIn = this._tokenService.getTokenFromSessionStorage() !== ''; this.post = this._postService.getDefaultPost(); this.user = this._userService.getDefaultUser(); + this.files = []; this._postService.getPostRequest(Guid.parse(this.paramId)).subscribe({ next: (result: object) => { @@ -39,13 +50,16 @@ export class PostComponent implements OnInit { this.post.fileURLs = Object.values(result)[7]; this.votesNumber = this.post.currentRating; - this.voteBtns = document.getElementsByClassName('vote') as HTMLCollectionOf<HTMLElement>; - this.timeCreated = new Date(this.post.timeCreated).toLocaleString('en-GB'); this.loadUser(); } }); + + this.editPostFormGroup = this._fb.group({ + newPostMessage: new FormControl(''), + fileUpload: new FormControl('') + }); } private loadUser(): void { @@ -54,7 +68,13 @@ export class PostComponent implements OnInit { Object.assign(this.user, result); if (this.loggedIn) { - this.highlightButtonsOnInit(); + this.loggedInAuthor = this._tokenService.getUsernameFromSessionStorageToken() === this.post.creatorUsername; + this.editPostFormGroup.get('newPostMessage')?.setValue(this.post.message); + + if (this.post.fileURLs.length > 0) { + this.loadFiles(); + return; + } } this.loaded = true; @@ -62,6 +82,38 @@ export class PostComponent implements OnInit { }); } + private loadFiles(): void { + for (const fileURL of this.post.fileURLs) { + this._cloudinaryService.getFileRequest(fileURL).subscribe({ + next: (result: object) => { + const file = result as File; + const tmp = { + name: fileURL.match('(?<=\/)(?:.(?!\/))+$')?.pop() ?? 'Attachment' + }; + + Object.assign(file, tmp); + this.files.push(file); + + if (this.files.length === this.post.fileURLs.length) { + this.loaded = true; + } + } + }); + } + } + + ngAfterViewInit(): void { + this._ratingServe.getRatingByUserAndPostWithSessionStorageRequest(Guid.parse(this.paramId)).subscribe({ + next: (x: object) => { + const isLike: boolean = Object.values(x)[3]; + + this.changeColorOfVoteButton(isLike, !isLike); + } + }); + + this._defaultShareBtnInnerHTML = this.shareBtn.nativeElement.innerHTML; + } + goToAuthorProfile(): void { this._router.navigate(['/profile/' + this.user.userName]); } @@ -70,6 +122,46 @@ export class PostComponent implements OnInit { this._router.navigate(['/post/' + this.post.postId]); } + toggleEditing(): void { + this.editingPost = !this.editingPost; + } + + onFileUpload(event: any): void { + this.files.push(...event.target.files); + this.editPostFormGroup.get('fileUpload')?.reset(); + } + + removeAttachment(fileName: string): void { + this.files = this.files.filter(x => x.name !== fileName); + } + + editPost(): void { + const newMessage = this.editPostFormGroup.get('newPostMessage')?.value; + + if (newMessage !== '') { + this._postService.putPostWithSessionStorageRequest(Guid.parse(this.paramId), newMessage, this.files).subscribe({ + next: () => { + this.reloadPage(); + } + }); + this.loaded = false; + } + } + + deletePost(): void { + this._postService.deletePostWithSessionStorage(Guid.parse(this.paramId)).subscribe({ + next: () => { + this._router.navigate(['/profile/' + this._tokenService.getUsernameFromSessionStorageToken()]); + } + }); + } + + private reloadPage(): void { + this._router.routeReuseStrategy.shouldReuseRoute = () => false; + this._router.onSameUrlNavigation = 'reload'; + this._router.navigate([this._router.url]); + } + votePost(isLike: boolean): void { if (!this.loggedIn) { this._router.navigate(['/login']); @@ -123,17 +215,23 @@ export class PostComponent implements OnInit { } private changeColorOfVoteButton(isUpvoted: boolean, isDownvoted: boolean): void { - this.voteBtns.item(this.index * 2)!.style.backgroundColor = (isUpvoted) ? 'lightblue' : 'white'; - this.voteBtns.item((this.index * 2) + 1)!.style.backgroundColor = (isDownvoted) ? 'lightblue' : 'white'; + this._renderer.setStyle(this.upvoteBtn.nativeElement, 'backgroundColor', (isUpvoted) ? 'var(--upvote-highlight)' : 'inherit'); + this._renderer.setStyle(this.downvoteBtn.nativeElement, 'backgroundColor', (isDownvoted) ? 'var(--downvote-highlight)' : 'inherit'); } - private highlightButtonsOnInit(): void { - this._ratingServe.getRatingByUserAndPostWithSessionStorageRequest(Guid.parse(this.paramId)).subscribe( - (x: object) => { - const isLike: boolean = Object.values(x)[3]; + resetShareBtn(): void { + if (this._linkShared) { + this._renderer.setProperty(this.shareBtn.nativeElement, 'innerHTML', this._defaultShareBtnInnerHTML); + this._linkShared = false; + } + } - this.changeColorOfVoteButton(isLike, !isLike); - } - ); + showCopiedMessage(): void { + this._renderer.setProperty(this.shareBtn.nativeElement, 'innerHTML', 'Link copied to clipboard!'); + this._linkShared = true; + } + + getPostLink(): string { + return location.origin + '/post/' + this.paramId; } } diff --git a/src/app/components/profile-settings/profile-settings.component.css b/src/app/components/profile-settings/profile-settings.component.css index 347c650..a8451c2 100644 --- a/src/app/components/profile-settings/profile-settings.component.css +++ b/src/app/components/profile-settings/profile-settings.component.css @@ -1,107 +1,10 @@ -* { - box-sizing: border-box; -} - -#content { - max-width: 22em; - justify-content: start; -} - -form { - width: 100%; -} - -hr { - width: calc(100% - 1em); - color: black; - border: 1px solid black; -} - -/* Navigation bar (for loggedin user) */ - -#navigation { - display: flex; - width: 100%; -} - -#navigation > .submit-btn { - flex: 1; - margin-top: 0; - margin-left: .5em; - font-size: inherit; -} - -#navigation > .submit-btn:nth-of-type(1) { - margin-left: 0; -} - -/* Form */ - -#update-profile-picture { - display: flex; - align-items: center; - justify-content: center; - padding: 0 .5em; - flex-wrap: wrap; -} - #profile-picture { width: 5em; height: 5em; } -#submit-file { - display: flex; - flex-direction: column; - align-items: center; - padding: 1em; -} - -#upload-file:hover { - cursor: inherit; -} - -#upload-file > input:hover { - cursor: pointer; -} - -#update-user { - margin-top: 1.1em; -} - -#all-languages, #all-technologies { - display: flex; - flex-wrap: wrap; -} - -/* Buttons */ - -.edit-btn { - border-radius: 0 !important; - color: var(--focus-color); - background-color: white; - border-color: var(--focus-color); -} - -.edit-btn:hover { - color: white; - background-color: black; - border-color: black !important; -} - -.submit-btn { - margin-bottom: .5em; -} - -#update-profile-btn { - margin-top: 1em; -} - -#confirm-delete { - box-sizing: border-box; - width: 100%; - background-color: var(--failure); - color: white; - padding: .2em; - text-align: center; +.sec-info { + width: fit-content; + background-color: #424242; + margin: 0 0.3em 0.3em 0; } diff --git a/src/app/components/profile-settings/profile-settings.component.html b/src/app/components/profile-settings/profile-settings.component.html index 502697d..538824d 100644 --- a/src/app/components/profile-settings/profile-settings.component.html +++ b/src/app/components/profile-settings/profile-settings.component.html @@ -1,116 +1,128 @@ +<app-navbar></app-navbar> + <app-loading *ngIf="!dataArrived"></app-loading> -<div id="content" *ngIf="dataArrived"> - <nav id="navigation"> - <button class="submit-btn" (click)="goToProfile()">ᐊ Back</button> - <button class="submit-btn" (click)="navigateToAdminPanel()" *ngIf="isAdminUser">Panel</button> - <button class="submit-btn" (click)="logout()">Logout</button> - </nav> - <hr> - <div class="scroll-standalone"> - <form id="update-profile-picture" [formGroup]="updateProfilePictureFormGroup" (ngSubmit)="updateProfilePicture()"> - <img id="profile-picture" class="round-image" [src]="user.profilePictureURL"> - <div id="submit-file"> - <div id="upload-file" class="submit-btn"> - <input type="file" accept="image/*" formControlName="fileUpload" (change)="onFileUpload($event)"> - </div> - <button class="submit-btn" type="submit">Update profile picture</button> - </div> - </form> - <hr> - <form id="update-user" [formGroup]="updateUserFormGroup" (ngSubmit)="onSubmit()"> - <div class="input-selection"> - <input type="text" class="input-field" formControlName="firstName" required> - <label class="input-field-label">First Name</label> +<main class="scroll-standalone under-navbar centered-content flex-col"> + <section class="card width-full" *ngIf="this.isAdminUser"> + <button class="width-full border-faded-slim padding-dot3 lighter-hover click-effect border-radius-dot3" (click)="goToAdminPanel()"> + Go to admin panel + </button> + </section> + <form class="flex-row card width-full font-size-dot9 margin-top-bot-dot7" [formGroup]="updateProfilePictureFormGroup" (ngSubmit)="updateProfilePicture()"> + <img id="profile-picture" class="round-image" [src]="user.profilePictureURL"> + <section class="flexible flex-col flex-center-align-items flex-justify-center padding-side-font"> + <input class="width-full border-faded-slim padding-dot3 lighter-hover click-effect border-radius-dot3" type="file" accept="image/*" formControlName="fileUpload" (change)="onFileUpload($event)"> + <button class="width-full border-faded-slim padding-dot3 lighter-hover click-effect border-radius-dot3 margin-top-dot4" type="submit" *ngIf="newProfilePicture.size > 0"> + Update profile picture + </button> + </section> + </form> + <form class="flex-col card width-full padding-dot6" [formGroup]="updateUserFormGroup" (ngSubmit)="onSubmit()"> + <section class="flex-col"> + <div class="flex-row"> + <label class="flexible fg-focus">First Name</label> - <div class="input-errors"> - <label *ngIf="updateUserFormGroup.get('firstName')?.errors?.required" class="error">*Required</label> - <label *ngIf="updateUserFormGroup.get('firstName')?.errors?.minlength" class="error">*Minimum 3 characters</label> - </div> + <label *ngIf="updateUserFormGroup.get('firstName')?.errors?.required" class="error">*Required</label> + <label *ngIf="updateUserFormGroup.get('firstName')?.errors?.minlength" class="error">*Minimum 3 characters</label> </div> + <input type="text" class="fancy-input border-faded-slim border-bottom-only" formControlName="firstName" required> + </section> + <section class="flex-col"> + <div class="flex-row"> + <label class="flexible fg-focus">Last Name</label> - <div class="input-selection"> - <input type="text" class="input-field" formControlName="lastName" required> - <label class="input-field-label">Last Name</label> - - <div class="input-errors"> - <label *ngIf="updateUserFormGroup.get('lastName')?.errors?.required" class="error">*Required</label> - <label *ngIf="updateUserFormGroup.get('lastName')?.errors?.minlength" class="error">*Minimum 3 characters</label> - </div> + <label *ngIf="updateUserFormGroup.get('lastName')?.errors?.required" class="error">*Required</label> + <label *ngIf="updateUserFormGroup.get('lastName')?.errors?.minlength" class="error">*Minimum 3 characters</label> </div> + <input type="text" class="fancy-input border-faded-slim border-bottom-only" formControlName="lastName" required> + </section> + <section class="flex-col"> + <div class="flex-row"> + <label class="flexible fg-focus">Username</label> - <div class="input-selection"> - <input type="text" class="input-field" formControlName="username" required> - <label class="input-field-label">Username</label> - - <div class="input-errors"> - <label *ngIf="updateUserFormGroup.get('username')?.errors?.required" class="error">*Required</label> - <label *ngIf="updateUserFormGroup.get('username')?.errors?.minlength" class="error">*Minimum 3 characters</label> - </div> + <label *ngIf="updateUserFormGroup.get('username')?.errors?.required" class="error">*Required</label> + <label *ngIf="updateUserFormGroup.get('username')?.errors?.minlength" class="error">*Minimum 3 characters</label> </div> + <input type="text" class="fancy-input border-faded-slim border-bottom-only" formControlName="username" required> + </section> + <section class="flex-col"> + <div class="flex-row"> + <label class="flexible fg-focus">Email</label> - <div class="input-selection"> - <input type="text" class="input-field" formControlName="email" required> - <label class="input-field-label">Email</label> - - <div class="input-errors"> - <label *ngIf="updateUserFormGroup.get('email')?.errors?.required" class="error">*Required</label> - <label *ngIf="updateUserFormGroup.get('email')?.errors?.email" class="error">*Invalid email</label> - </div> + <label *ngIf="updateUserFormGroup.get('email')?.errors?.required" class="error">*Required</label> + <label *ngIf="updateUserFormGroup.get('email')?.errors?.email" class="error">*Invalid email</label> </div> + <input type="text" class="fancy-input border-faded-slim border-bottom-only" formControlName="email" required> + </section> + <section class="flex-col"> + <div class="flex-row"> + <label class="flexible fg-focus">Password</label> - <div class="input-selection"> - <input type="password" class="input-field" formControlName="password" required> - <label class="input-field-label">Password</label> - - <div class="input-errors"> - <label *ngIf="updateUserFormGroup.get('password')?.errors?.required" class="error">*Required</label> - <label *ngIf="updateUserFormGroup.get('password')?.errors?.minlength" class="error">*Minimum 3 characters</label> - <label *ngIf="updateUserFormGroup.get('password')?.errors?.pattern" class="error">*At least 1 number</label> - </div> + <label *ngIf="updateUserFormGroup.get('password')?.errors?.required" class="error">*Required</label> + <label *ngIf="updateUserFormGroup.get('password')?.errors?.minlength" class="error">*Minimum 3 characters</label> + <label *ngIf="updateUserFormGroup.get('password')?.errors?.pattern" class="error">*At least 1 number</label> </div> - <button type="button" class="submit-btn edit-btn" (click)="toggleLanguages()">▼ Edit Languages ▼</button> - <div *ngIf="showLanguages"> - <div class="input-selection"> - <input type="text" class="input-field" formControlName="languageInput" required> - - <div class="input-errors"> - <label class="error">Type in your desired languages, separated by a space</label> - </div> - </div> + <input type="password" class="fancy-input border-faded-slim border-bottom-only" formControlName="password" required> + </section> + <button type="button" class="fg-focus width-full border-faded-slim padding-dot3 lighter-hover click-effect margin-top-dot4" (click)="toggleLanguages()"> + ▼ Edit Languages ▼ + </button> + <section *ngIf="showLanguages"> + <div class="margin-top-dot5"> + <label class="error"> + Type in your desired languages, separated by a space + </label> + <input class="fancy-input width-full border-faded-slim border-bottom-only" type="text" placeholder="You have no selected languages!" formControlName="languageInput" required> + </div> + <div class="none-message" *ngIf="availableLanguages.length === 0"> + No languages available! + </div> + <div *ngIf="availableLanguages.length > 0"> Available languages: - <div id="all-languages"> - <div class="user-language" *ngFor="let lang of availableLanguages"> - {{ lang.name }} - </div> - </div> </div> - - <button type="button" class="submit-btn edit-btn" (click)="toggleTechnologies()">▼ Edit Technologies ▼</button> - <div *ngIf="showTechnologies"> - <div class="input-selection"> - <input type="text" class="input-field" formControlName="technologyInput" required> - - <div class="input-errors"> - <label class="error">Type in your desired technologies, separated by a space</label> - </div> + <div class="flex-row margin-top-dot4" *ngFor="let lang of availableLanguages"> + <div class="sec-info border-radius-dot5r padding-dot2"> + {{ lang.name }} </div> + </div> + </section> + <button type="button" class="fg-focus width-full border-faded-slim padding-dot3 lighter-hover click-effect margin-top-dot4" (click)="toggleTechnologies()"> + ▼ Edit Technologies ▼ + </button> + <section *ngIf="showTechnologies"> + <div class="margin-top-dot5"> + <label class="error"> + Type in your desired technologies, separated by a space + </label> + <input class="fancy-input width-full border-faded-slim border-bottom-only" type="text" placeholder="You have no selected technologies!" formControlName="technologyInput" required> + </div> + <div class="none-message" *ngIf="availableTechnologies.length === 0"> + No technologies available! + </div> + <div *ngIf="availableTechnologies.length > 0"> Available technologies: - <div id="all-technologies"> - <div class="user-technology" *ngFor="let tech of availableTechnologies"> - {{ tech.name }} - </div> + </div> + <div class="flex-row margin-top-dot4" *ngFor="let tech of availableTechnologies"> + <div class="sec-info border-radius-dot5r padding-dot2"> + {{ tech.name }} </div> </div> - - <button id="update-profile-btn" class="submit-btn" type="submit">Update profile</button> + </section> + <section class="margin-top-bot-dot3"> <app-success-bar></app-success-bar> <app-error-bar></app-error-bar> - </form> - <hr> - <div id="confirm-delete" *ngIf="deleteAccountConfirm"> + </section> + <button class="width-full border-faded-slim padding-dot3 lighter-hover click-effect border-radius-dot3" type="submit"> + Update profile + </button> + </form> + <section class="card width-full"> + <div class="margin-bot-dot5 text-centered fg-error" *ngIf="deleteAccountConfirm"> Are you sure you want to delete your account?<br>This is permanent! </div> - <button class="submit-btn delete-btn" (click)="deleteAccount()">Delete account</button> - </div> -</div> + <button class="width-full border-faded-slim padding-dot3 lighter-hover click-effect border-radius-dot3 fg-error" (click)="deleteAccount()"> + Delete account + </button> + </section> + </main> + diff --git a/src/app/components/profile-settings/profile-settings.component.ts b/src/app/components/profile-settings/profile-settings.component.ts index b314a9a..79519aa 100644 --- a/src/app/components/profile-settings/profile-settings.component.ts +++ b/src/app/components/profile-settings/profile-settings.component.ts @@ -50,6 +50,23 @@ export class ProfileSettingsComponent implements OnInit { this.availableTechnologies = []; this.newProfilePicture = new File([], ''); + // Initializing forms with blank (default) values + this.updateUserFormGroup = this._fb.group({ + firstName: new FormControl(''), + lastName: new FormControl(''), + username: new FormControl(''), + email: new FormControl(''), + password: new FormControl(''), + languageInput: new FormControl(''), + languages: new FormControl(''), + technologyInput: new FormControl(''), + technologies: new FormControl('') + }); + this.updateProfilePictureFormGroup = this._fb.group({ + fileUpload: new FormControl('') + }); + + this._userService.getUserByUsernameRequest(this._urlUsername).subscribe({ next: (res: object) => { Object.assign(this.user, res); @@ -273,13 +290,13 @@ export class ProfileSettingsComponent implements OnInit { this._router.navigate([this._router.url.substring(0, this._router.url.length - 9)]); } - navigateToAdminPanel(): void { + goToAdminPanel(): void { this._router.navigate(['/admin-panel']); } logout(): void { this._tokenService.logoutUserFromSessionStorage(); - this.goToProfile(); + this._router.navigate(['/login']); } toggleLanguages(): void { diff --git a/src/app/components/profile/profile.component.css b/src/app/components/profile/profile.component.css index ebcd406..c7e112f 100644 --- a/src/app/components/profile/profile.component.css +++ b/src/app/components/profile/profile.component.css @@ -1,105 +1,27 @@ -* { - box-sizing: border-box; +#user-info { + font-size: 1.3em; } -#content { - max-width: 22em; - justify-content: start; +#profile-picture { + height: 5rem; + width: 5rem; } -hr { - width: calc(100% - 1em); - color: black; - border: 1px solid black; +.sec-info-card { + padding-bottom: calc(var(--card-padding) - 0.3em); } -form { - width: 100%; +.sec-info-title { + padding-bottom: 0.2em; + margin-bottom: 0.3em; } -/* Navigation bar (for loggedin user) */ - -#navigation { - display: flex; - width: 100%; -} - -.submit-btn { - flex: 1; - margin-top: 0; - margin-left: .5em; - font-size: inherit; -} - -#navigation > .submit-btn:first-child { - margin-left: 0; -} - -/* Top card */ - -#main-info { - display: flex; - width: 100%; - margin-bottom: .25em -} - -#main-info > img { - width: 5em; - height: 5em; -} - -#other-main-info { - flex: 1; - display: flex; - flex-direction: column; - align-items: center; - text-align: center; -} - -#other-main-info > * { - font-size: 1.4em; -} - -#other-main-info *:nth-child(1) { - margin-top: auto; -} - -#other-main-info *:nth-last-child(1) { - margin-bottom: auto; -} - -#add-friend, #loggedin-password { - flex: 0 !important; - margin-top: .4em; - max-width: 8em; - font-size: .6em !important; -} - -#loggedin-password { - max-width: 100%; -} - -/* Languages and technologies */ - -.secondary-info { - margin-top: .25em; - margin-bottom: .25em; - width: 100%; - display: flex; - align-items: center; - flex-wrap: wrap; -} - -/* Posts */ - -#no-posts { - width: 100%; - text-align: center; - color: gray; - margin-top: .2em; +.none-message { + margin-bottom: 0.3em; } -#posts { - width: 100%; - height: 100%; +.sec-info { + width: fit-content; + background-color: #424242; + margin: 0 0.3em 0.3em 0; } diff --git a/src/app/components/profile/profile.component.html b/src/app/components/profile/profile.component.html index 5c21cee..7de1d09 100644 --- a/src/app/components/profile/profile.component.html +++ b/src/app/components/profile/profile.component.html @@ -1,60 +1,60 @@ +<app-navbar></app-navbar> + <app-loading *ngIf="!dataArrived"></app-loading> -<div id="content" *ngIf="dataArrived"> - <nav id="navigation"> - <button class="submit-btn" (click)="goBack()">ᐊ Back</button> - <button class="submit-btn" (click)="navigateToSettings()" *ngIf="isTheLoggedInUser">Settings</button> - <button class="submit-btn" (click)="navigateToAdminPanel()" *ngIf="isTheLoggedInUser && isAdminUser">Panel</button> - <button class="submit-btn" (click)="logout()" *ngIf="isTheLoggedInUser">Logout</button> - </nav> - <hr> - <div class="scroll-standalone" (scroll)="onScroll($event)"> - <div id="main-info" class="rounded-border"> - <img class="round-image" [src]="user.profilePictureURL" alt=""/> - <div id="other-main-info"> - <div id="name"> - {{ user.firstName }} {{ user.lastName }} - </div> - <div id="username"> - @{{ user.userName }} - </div> - <form [formGroup]="updateFrienship" (ngSubmit)="modifyFriend()" *ngIf="!isTheLoggedInUser && isUserLoggedIn"> - <button id="add-friend" type="submit" class="submit-btn">{{ friendOfUser ? 'Unfriend' : 'Add friend' }}</button> - <br> - <input id="loggedin-password" type="password" formControlName="password" class="input-field" *ngIf="updatingFriendship" placeholder="Type in password to confirm"> - </form> - </div> +<main class="scroll-standalone under-navbar flex-col centered-content" *ngIf="dataArrived" (scroll)="onScroll($event)"> + <section id="user-info" class="card flex-row width-full flex-justify-center"> + <div> + <img id="profile-picture" class="round-image" [src]="user.profilePictureURL"> </div> - <div class="secondary-info rounded-border"> - Languages: - <div *ngFor="let lang of user.languages"> - <div class="user-language"> - {{ lang.name }} - </div> + <div class="flexible flex-col flex-center-align-items flex-justify-center side-padding-dot3"> + <div class="text-centered"> + {{ user.firstName }} {{ user.lastName }} </div> - <div *ngIf="user.languages.length === 0"> - None + <div> + @{{ user.userName }} </div> + <form class="flex-row flexible-children width-full font-size-dot7 margin-top-dot4" [formGroup]="updateFrienship" (ngSubmit)="modifyFriend()" *ngIf="!isTheLoggedInUser && isUserLoggedIn"> + <input class="border-faded-slim border-bottom-only margin-right-dot2" type="password" formControlName="password" *ngIf="updatingFriendship" placeholder="Type in password to confirm"> + <button id="add-friend" type="submit" class="border-faded-slim padding-dot1 lighter-hover click-effect border-radius-dot3 width-full"> + {{ updatingFriendship ? 'Confirm' : (friendOfUser ? 'Unfriend' : 'Add friend') }} + </button> + </form> </div> - <div class="secondary-info rounded-border"> - Technologies: - <div *ngFor="let tech of user.technologies"> - <div class="user-language"> - {{ tech.name }} - </div> - </div> - <div *ngIf="user.technologies.length === 0"> - None - </div> + </section> + <section class="card sec-info-card flex-col width-full"> + <div class="sec-info-title border-faded-slim border-bottom-only"> + Languages + </div> + <div class="none-message" *ngIf="user.languages.length === 0"> + None </div> - <hr> - <div id="posts"> - <div id="no-posts" *ngIf="userPosts.length === 0"> - {{ user.firstName }} {{ user.lastName }} hasn't posted anything yet! + <div class="flex-row" *ngFor="let lang of user.languages"> + <div class="sec-info border-radius-dot5r padding-dot2"> + {{ lang.name }} </div> - <div *ngFor="let userPost of userPosts; let i = index"> - <app-post [paramId]="userPost.postId.toString()" [index]="i"></app-post> + </div> + </section> + <section class="card sec-info-card flex-col width-full"> + <div class="sec-info-title border-faded-slim border-bottom-only"> + Technologies + </div> + <div class="none-message" *ngIf="user.technologies.length === 0"> + None + </div> + <div class="flex-row" *ngFor="let tech of user.technologies"> + <div class="sec-info border-radius-dot5r padding-dot2"> + {{ tech.name }} </div> </div> - </div> -</div> + </section> + <hr class="card-hr"> + <section> + <div class="text-centered" *ngIf="userPosts.length === 0"> + {{ user.firstName }} {{ user.lastName }} hasn't posted anything yet! + </div> + <div *ngFor="let userPost of userPosts"> + <app-post [paramId]="userPost.postId.toString()"></app-post> + </div> + </section> +</main> diff --git a/src/app/components/profile/profile.component.ts b/src/app/components/profile/profile.component.ts index ed17f33..fc5d4d6 100644 --- a/src/app/components/profile/profile.component.ts +++ b/src/app/components/profile/profile.component.ts @@ -131,18 +131,6 @@ export class ProfileComponent implements OnInit { } } - goBack(): void { - this._router.navigate(['/']); - } - - navigateToAdminPanel(): void { - this._router.navigate(['/admin-panel']); - } - - navigateToSettings(): void { - this._router.navigate([this._router.url + '/settings']); - } - logout(): void { this._tokenService.logoutUserFromSessionStorage(); diff --git a/src/app/components/register/register.component.css b/src/app/components/register/register.component.css index 973c6f0..e69de29 100644 --- a/src/app/components/register/register.component.css +++ b/src/app/components/register/register.component.css @@ -1,40 +0,0 @@ -/* A lot of stuff are moved to the global styles! */ - -form { - width: 100%; -} - -@media screen and (max-height: 630px) { - #content { - height: fit-content !important; - } -} - -#content hr { - width: 100%; - border: 1px solid black; - box-sizing: border-box; -} - -.submit-btn { - transition: 0.2s; -} - -.input-selection:nth-of-type(1) { - margin-top: 1.2em; -} - -.submit-btn { - margin-bottom: .2em; -} - -.redirect-to-login { - color: var(--focus-color); - background-color: var(--bg-color); - border-color: var(--focus-color); -} - -.redirect-to-login:hover { - border-color: black !important; - color: black; -} diff --git a/src/app/components/register/register.component.html b/src/app/components/register/register.component.html index 0075b1d..1f547c4 100644 --- a/src/app/components/register/register.component.html +++ b/src/app/components/register/register.component.html @@ -1,55 +1,44 @@ -<main id="content"> - <summary class="title">Register</summary> +<main class="centered-content flex-col flex-center-align-items flex-justify-center height-full"> + <summary class="title card width-full margin-0 padding-dot2">Register</summary> - <form [formGroup]="registerUserFormGroup" (ngSubmit)="onSubmit()"> - <hr> - <!-- Value: {{ registerUserFormGroup.value | json }} - <hr> --> - - <section class="input-selection"> - <input type="text" placeholder="Goshko, is that u?" class="input-field" formControlName="firstName" required> - <label class="input-field-label">First Name</label> + <app-error-bar class="width-full margin-top-dot4"></app-error-bar> + <form class="width-full card padding-dot6" [formGroup]="registerUserFormGroup" (ngSubmit)="onSubmit()"> + <section class="input-selection width-full"> + <input type="text" placeholder="First Name" class="fancy-input width-full border-faded-slim border-bottom-only" formControlName="firstName" required> + <label class="fancy-input-label width-full">First Name</label> <div class="input-errors"> <label *ngIf="registerUserFormGroup.get('firstName')?.errors?.required" class="error">*Required</label> <label *ngIf="registerUserFormGroup.get('firstName')?.errors?.minlength" class="error">*Minimum 3 characters</label> </div> </section> - <section class="input-selection"> - <input type="text" placeholder="Trapov? Really??" class="input-field" formControlName="lastName" required> - <label class="input-field-label">Last Name</label> - + <input type="text" placeholder="Last Name" class="fancy-input width-full border-faded-slim border-bottom-only" formControlName="lastName" required> + <label class="fancy-input-label width-full">Last Name</label> <div class="input-errors"> <label *ngIf="registerUserFormGroup.get('lastName')?.errors?.required" class="error">*Required</label> <label *ngIf="registerUserFormGroup.get('lastName')?.errors?.minlength" class="error">*Minimum 3 characters</label> </div> </section> - <section class="input-selection"> - <input type="text" placeholder="Think of something cool to flex on other kids" class="input-field" formControlName="username" required> - <label class="input-field-label">Username</label> - + <input type="text" placeholder="Username" class="fancy-input width-full border-faded-slim border-bottom-only" formControlName="username" required> + <label class="fancy-input-label width-full">Username</label> <div class="input-errors"> <label *ngIf="registerUserFormGroup.get('username')?.errors?.required" class="error">*Required</label> <label *ngIf="registerUserFormGroup.get('username')?.errors?.minlength" class="error">*Minimum 3 characters</label> </div> </section> - <section class="input-selection"> - <input type="text" placeholder="You expect an email joke? I have none, mail me one" class="input-field" formControlName="email" required> - <label class="input-field-label">Email</label> - + <input type="text" placeholder="Email" class="fancy-input width-full border-faded-slim border-bottom-only" formControlName="email" required> + <label class="fancy-input-label width-full">Email</label> <div class="input-errors"> <label *ngIf="registerUserFormGroup.get('email')?.errors?.required" class="error">*Required</label> <label *ngIf="registerUserFormGroup.get('email')?.errors?.email" class="error">*Invalid email</label> </div> </section> - <section class="input-selection"> - <input type="password" placeholder="Make sure it's long & strong (just like my d***)" class="input-field" formControlName="password" required> - <label class="input-field-label">Password</label> - + <input type="password" placeholder="Password" class="fancy-input width-full border-faded-slim border-bottom-only" formControlName="password" required> + <label class="fancy-input-label width-full">Password</label> <div class="input-errors"> <label *ngIf="registerUserFormGroup.get('password')?.errors?.required" class="error">*Required</label> <label *ngIf="registerUserFormGroup.get('password')?.errors?.minlength" class="error">*Minimum 3 characters</label> @@ -57,9 +46,10 @@ </div> </section> - <hr> - <button class="submit-btn" type="submit">Submit</button> - <app-error-bar></app-error-bar> + + <button class="border-faded-slim padding-dot3 lighter-hover click-effect border-radius-dot3 width-full" type="submit">Submit</button> </form> - <button class="submit-btn redirect-to-login" (click)="onRedirectLogin()">Already have an account? Login here</button> + <button class="fg-focus border-faded-slim padding-dot3 lighter-hover click-effect border-radius-dot3 width-full margin-top-dot4" (click)="onRedirectLogin()"> + Already have an account? Login here + </button> </main> diff --git a/src/app/services/comment.service.ts b/src/app/services/comment.service.ts index 70ab005..9839b01 100644 --- a/src/app/services/comment.service.ts +++ b/src/app/services/comment.service.ts @@ -14,7 +14,7 @@ export class CommentService { { } getDefaultComment(): Comment { - return new Comment(Guid.createEmpty(), Guid.createEmpty(), 'Gosho', 'Trapov', 'gosho_trapov', 'Your opinion on my idea?', new Date()); + return new Comment(Guid.createEmpty(), Guid.createEmpty(), '', '', '', '', new Date()); } /* Requests from session storage */ diff --git a/src/app/services/post.service.ts b/src/app/services/post.service.ts index b49ffea..1a6e021 100644 --- a/src/app/services/post.service.ts +++ b/src/app/services/post.service.ts @@ -15,7 +15,7 @@ export class PostService { { } getDefaultPost(): Post { - return new Post(Guid.createEmpty(), 'Gosho', 'Trapov', 'gosho_trapov', 'Your opinion on my idea?', new Date(), [], [], 0); + return new Post(Guid.createEmpty(), '', '', '', '', new Date(), [], [], 0); } /* Requests from session storage */ diff --git a/src/app/services/user.service.ts b/src/app/services/user.service.ts index f22952e..29058b4 100644 --- a/src/app/services/user.service.ts +++ b/src/app/services/user.service.ts @@ -17,7 +17,7 @@ export class UserService { { } getDefaultUser(): User { - return new User(Guid.createEmpty(), 'gosho_trapov', 'Gosho', 'Trapov', 'gotra@bg.com', AppConstants.FALLBACK_PROFILE_ICON, [], [], [], []); + return new User(Guid.createEmpty(), '', '', '', '', AppConstants.FALLBACK_PROFILE_ICON, [], [], [], []); } /* Requests from session storage */ |
