Changeset 79ae621 for src/Clients/Angular
- Timestamp:
- 10/27/21 19:40:58 (3 years ago)
- Branches:
- dev
- Children:
- d2b1fa6
- Parents:
- 81e1ed6 (diff), 7899209 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- src/Clients/Angular/finki-chattery
- Files:
-
- 63 added
- 1 deleted
- 23 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Clients/Angular/finki-chattery/angular.json
r81e1ed6 r79ae621 98 98 "tsConfig": "tsconfig.spec.json", 99 99 "karmaConfig": "karma.conf.js", 100 "assets": ["src/favicon.ico", "src/assets"], 101 "styles": ["./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", "src/styles.scss"], 100 "assets": [ 101 "src/favicon.ico", 102 "src/assets" 103 ], 104 "styles": [ 105 "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", 106 "src/styles.scss" 107 ], 102 108 "scripts": [] 103 109 } … … 106 112 "builder": "@angular-devkit/build-angular:tslint", 107 113 "options": { 108 "tsConfig": ["tsconfig.app.json", "tsconfig.spec.json", "e2e/tsconfig.json"], 109 "exclude": ["**/node_modules/**"] 114 "tsConfig": [ 115 "tsconfig.app.json", 116 "tsconfig.spec.json", 117 "e2e/tsconfig.json" 118 ], 119 "exclude": [ 120 "**/node_modules/**" 121 ] 110 122 } 111 123 }, … … 125 137 } 126 138 }, 127 "defaultProject": "finki-chattery" 139 "defaultProject": "finki-chattery", 140 "cli": { 141 "analytics": false 142 } 128 143 } -
src/Clients/Angular/finki-chattery/src/app/app-routing.module.ts
r81e1ed6 r79ae621 1 1 import { NgModule } from '@angular/core'; 2 2 import { Routes, RouterModule } from '@angular/router'; 3 import { AuthCallbackComponent } from './auth-callback/auth-callback.component'; 4 import { AuthorizedGuard } from './core/guards/authorized.guard'; 3 5 4 6 const routes: Routes = [ 5 7 { 6 path: ' **',7 redirectTo: 'public/home'8 path: 'auth-callback', 9 component: AuthCallbackComponent 8 10 }, 9 11 { 10 path: 'questions', 12 path: 'questioning', 13 canActivate: [AuthorizedGuard], 11 14 loadChildren: () => import('./modules/questioning/questioning.module').then((x) => x.QuestioningModule) 15 }, 16 { 17 path: '**', 18 redirectTo: 'questioning/preview' 12 19 } 13 20 ]; -
src/Clients/Angular/finki-chattery/src/app/app.component.html
r81e1ed6 r79ae621 1 1 <main> 2 2 <mat-progress-bar class="global-loader" [class.hidden]="!(loader.isLoading | async)" mode="indeterminate"></mat-progress-bar> 3 <app-header></app-header> 3 4 <router-outlet></router-outlet> 4 5 </main> -
src/Clients/Angular/finki-chattery/src/app/app.module.ts
r81e1ed6 r79ae621 10 10 import { CoreModule } from './core/core.module'; 11 11 import { translateConfiguration, TranslateFromJsonService } from './shared-app/services'; 12 import { SharedMaterialModule } from './shared-material/shared-material.module';12 import { AuthCallbackComponent } from './auth-callback/auth-callback.component'; 13 13 14 14 @NgModule({ 15 declarations: [AppComponent ],15 declarations: [AppComponent, AuthCallbackComponent], 16 16 imports: [ 17 17 BrowserModule, 18 18 AppRoutingModule, 19 19 CoreModule, 20 SharedMaterialModule,21 20 BrowserAnimationsModule, 22 21 ToastrModule.forRoot(), -
src/Clients/Angular/finki-chattery/src/app/core/core.module.ts
r81e1ed6 r79ae621 11 11 import { GUARDS } from './guards/guards'; 12 12 import { LoaderInterceptor } from './interceptors/loader.interceptor'; 13 import { SERVICES } from './services/services';14 13 import { reducers } from './state'; 15 14 import { TokenInterceptor } from './interceptors/token.interceptor'; 15 import { EffectsModule } from '@ngrx/effects'; 16 import { QuestionEffects } from './state/question-state/question.effects'; 17 import { CategoriesEffects } from './state/category-state/category.effects'; 16 18 17 19 @NgModule({ 18 20 declarations: [COMPONENTS], 19 21 providers: [ 20 SERVICES,21 22 GUARDS, 22 23 { provide: HTTP_INTERCEPTORS, useClass: LoaderInterceptor, multi: true }, … … 33 34 maxAge: 25, 34 35 logOnly: !environment.production 35 }) 36 }), 37 EffectsModule.forRoot([QuestionEffects, CategoriesEffects]) 36 38 ], 37 exports: [HttpClientModule, COMPONENTS]39 exports: [HttpClientModule, SharedAppModule, COMPONENTS] 38 40 }) 39 41 export class CoreModule {} -
src/Clients/Angular/finki-chattery/src/app/core/interceptors/token.interceptor.ts
r81e1ed6 r79ae621 2 2 import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http'; 3 3 import { Observable } from 'rxjs'; 4 import { switchMap } from 'rxjs/operators';5 4 6 5 import { AuthService } from '../services'; … … 16 15 } 17 16 18 return this.auth.currentUserToken().pipe( 19 switchMap((token) => { 20 const requestToForward = request.clone({ 21 setHeaders: { Authorization: `Bearer ${token}` } 22 }); 23 return next.handle(requestToForward); 24 }) 25 ); 17 const requestToForward = request.clone({ 18 setHeaders: { Authorization: `Bearer ${this.auth.currentUserToken()}` } 19 }); 20 21 return next.handle(requestToForward); 26 22 } 27 23 } -
src/Clients/Angular/finki-chattery/src/app/core/services/auth.service.ts
r81e1ed6 r79ae621 1 1 import { Injectable } from '@angular/core'; 2 import { UserManager } from 'oidc-client'; 3 import { Observable, from, of } from 'rxjs'; 4 import { map, switchMap } from 'rxjs/operators'; 2 import { User, UserManager } from 'oidc-client'; 3 import { Observable, of } from 'rxjs'; 5 4 6 5 import { environment } from '@env/environment'; … … 15 14 authority: environment.identityRoute, 16 15 client_id: environment.identityClientId, 17 redirect_uri: `${window.location.origin} `,16 redirect_uri: `${window.location.origin}/auth-callback`, 18 17 response_type: 'id_token token', 19 18 scope: 'openid app.api.finki-chattery profile', 20 19 post_logout_redirect_uri: window.location.origin 21 20 }); 21 22 public user: ApplicationUser | null = null; 23 public oidcUser: User | null = null; 22 24 23 25 constructor(private baseApi: BaseApiService) {} … … 31 33 } 32 34 33 public isLoggedIn(): Observable<boolean> { 34 return from(this.userManager.getUser()).pipe( 35 map((user) => { 36 if (user) { 37 return true; 38 } 39 40 return false; 41 }) 42 ); 35 public isLoggedIn(): boolean { 36 if (this.oidcUser) { 37 return !this.oidcUser.expired; 38 } 39 return false; 43 40 } 44 41 45 public currentUser(): Observable<ApplicationUser | null> { 46 return from(this.userManager.getUser()).pipe( 47 map((user) => { 48 if (!user) { 49 return null; 50 } 51 52 return new ApplicationUser( 53 user.profile.id, 54 user.profile.userType, 55 user.profile.emailAddress, 56 user.profile.username, 57 user.profile.isVerified 58 ); 59 }) 60 ); 42 public currentUser(): ApplicationUser | null { 43 return this.user; 61 44 } 62 45 63 public currentUserToken(): Observable<string> { 64 return from(this.userManager.getUser()).pipe( 65 map((user) => { 66 if (user?.access_token) { 67 return user.access_token; 68 } 46 public currentUserToken(): string { 47 if (this.oidcUser) { 48 return this.oidcUser.access_token; 49 } 69 50 70 return ''; 71 }) 72 ); 51 return ''; 73 52 } 74 53 75 54 public selfUserDto(): Observable<SelfUserResponse | null> { 76 return this.isLoggedIn().pipe( 77 switchMap((loggedIn) => { 78 if (loggedIn) { 79 return this.baseApi.getSelfUser(); 80 } 81 return of(null); 82 }) 83 ); 55 if (this.isLoggedIn()) { 56 return this.baseApi.getSelfUser(); 57 } 58 return of(null); 84 59 } 85 60 86 public signupCallback(): Observable<boolean> { 87 return from(this.userManager.signinRedirectCallback()).pipe(map((user) => user !== null)); 61 public async completeAuthentication(): Promise<void> { 62 return await this.userManager.signinRedirectCallback().then((user: User) => { 63 this.oidcUser = user; 64 this.user = new ApplicationUser( 65 user.profile.id, 66 user.profile.userType, 67 user.profile.emailAddress, 68 user.profile.username, 69 user.profile.isVerified 70 ); 71 }); 88 72 } 89 73 } -
src/Clients/Angular/finki-chattery/src/app/core/services/notification.service.ts
r81e1ed6 r79ae621 22 22 23 23 public successNotification(title: string, description?: string): void { 24 this.toastr.success(this.translate.instant(description), this.translate.instant(title)); 24 if (description) { 25 this.toastr.success(this.translate.instant(description), this.translate.instant(title)); 26 } 27 this.toastr.success(this.translate.instant(title)); 25 28 } 26 29 } -
src/Clients/Angular/finki-chattery/src/app/core/services/redirect.service.ts
r81e1ed6 r79ae621 1 1 import { Injectable } from '@angular/core'; 2 2 import { Router } from '@angular/router'; 3 import { switchMap } from 'rxjs/operators';4 3 5 4 import { ApplicationUserType } from 'src/app/shared-app/models'; … … 13 12 14 13 public redirectLoggedInUser(): void { 15 this.auth 16 .signupCallback() 17 .pipe(switchMap(() => this.auth.currentUser())) 18 .subscribe((currentUser) => { 19 if (currentUser) { 20 switch (currentUser.userType) { 21 case ApplicationUserType.Student: 22 break; 23 case ApplicationUserType.Teacher: 24 break; 25 } 26 } 27 }); 14 const currentUser = this.auth.user; 15 16 if (currentUser) { 17 switch (currentUser.userType) { 18 case ApplicationUserType.Student: 19 this.router.navigateByUrl(`questioning/preview`); 20 break; 21 case ApplicationUserType.Teacher: 22 break; 23 } 24 } 28 25 } 29 26 } -
src/Clients/Angular/finki-chattery/src/app/core/services/services.ts
r81e1ed6 r79ae621 1 export const SERVICES: any[] = []; -
src/Clients/Angular/finki-chattery/src/app/core/state/index.ts
r81e1ed6 r79ae621 1 1 import { ActionReducerMap } from '@ngrx/store'; 2 import { QuestionState } from './question-state/question.state'; 3 import { reducer as questionReducer } from './question-state/question.reducers'; 4 import { CategoryState } from './category-state/category.state'; 5 import { reducer as categoryReducer } from './category-state/category.reducers'; 2 6 3 export interface State {} 7 export interface State { 8 question: QuestionState; 9 category: CategoryState; 10 } 4 11 5 export const reducers: ActionReducerMap<State, any> = {}; 12 export const reducers: ActionReducerMap<State, any> = { 13 question: questionReducer, 14 category: categoryReducer 15 }; -
src/Clients/Angular/finki-chattery/src/app/modules/questioning/components/questioning-components.ts
r81e1ed6 r79ae621 1 import { QuestionPreviewGeneralComponent } from './question-preview-general/question-preview-general.component'; 2 import { QuestioningGeneralComponent } from './questioning-general/questioning-general.component'; 3 import { QuestionsPreviewGeneralComponent } from './questions-preview-general/questions-preview-general.component'; 4 import { QuestionsSearchComponent } from './questions-search/questions-search.component'; 1 5 import { AskQuestionComponent } from './ask-question/ask-question.component'; 2 6 3 export const QUESTIONING_COMPONENTS: any[] = [AskQuestionComponent]; 7 export const QUESTIONING_COMPONENTS: any[] = [ 8 QuestionPreviewGeneralComponent, 9 QuestionsPreviewGeneralComponent, 10 QuestioningGeneralComponent, 11 QuestionsSearchComponent, 12 AskQuestionComponent 13 ]; -
src/Clients/Angular/finki-chattery/src/app/modules/questioning/questioning.module.ts
r81e1ed6 r79ae621 1 1 import { NgModule } from '@angular/core'; 2 2 3 import { QuestioningRoutingModule } from './questioning.routes'; 3 4 import { QUESTIONING_COMPONENTS } from './components/questioning-components'; 4 5 import { SharedAppModule } from 'src/app/shared-app/shared-app.module'; 5 import { QuestioningRoutingModule } from './questioning.routes';6 7 6 @NgModule({ 8 7 declarations: [QUESTIONING_COMPONENTS], -
src/Clients/Angular/finki-chattery/src/app/modules/questioning/questioning.routes.ts
r81e1ed6 r79ae621 1 1 import { NgModule } from '@angular/core'; 2 2 import { Routes, RouterModule } from '@angular/router'; 3 import { QuestionPreviewGeneralComponent } from './components/question-preview-general/question-preview-general.component'; 4 import { QuestioningGeneralComponent } from './components/questioning-general/questioning-general.component'; 5 import { QuestionsPreviewGeneralComponent } from './components/questions-preview-general/questions-preview-general.component'; 6 import { QuestionsSearchComponent } from './components/questions-search/questions-search.component'; 3 7 import { AuthorizedStudentGuard } from 'src/app/core/guards/authorized-student.guard'; 4 8 import { AskQuestionComponent } from './components/ask-question/ask-question.component'; … … 6 10 const routes: Routes = [ 7 11 { 8 path: 'ask', 9 component: AskQuestionComponent, 10 canActivate: [AuthorizedStudentGuard] 12 component: QuestioningGeneralComponent, 13 path: '', 14 children: [ 15 { 16 path: 'preview', 17 pathMatch: 'full', 18 component: QuestionsPreviewGeneralComponent 19 }, 20 { 21 path: 'search', 22 pathMatch: 'full', 23 component: QuestionsSearchComponent 24 }, 25 { 26 path: 'ask', 27 pathMatch: 'full', 28 component: AskQuestionComponent, 29 canActivate: [AuthorizedStudentGuard] 30 } 31 { 32 path: ':questionUid', 33 component: QuestionPreviewGeneralComponent 34 } 35 ] 11 36 } 12 37 ]; -
src/Clients/Angular/finki-chattery/src/app/shared-app/directives/directives.ts
r81e1ed6 r79ae621 1 import { HandleInputFormErrorsDirective, HoverElevationDirective, LoaderDirective, HandleSelectFormErrorsDirective } from '.'; 1 import { 2 HandleInputFormErrorsDirective, 3 HoverElevationDirective, 4 LoaderDirective, 5 HandleSelectFormErrorsDirective, 6 ShareLinkDirective 7 } from '.'; 2 8 3 9 export const DIRECTIVES: any[] = [ … … 5 11 LoaderDirective, 6 12 HoverElevationDirective, 7 HandleSelectFormErrorsDirective 13 HandleSelectFormErrorsDirective, 14 ShareLinkDirective 8 15 ]; -
src/Clients/Angular/finki-chattery/src/app/shared-app/directives/index.ts
r81e1ed6 r79ae621 3 3 export * from './hover-elevation.directive'; 4 4 export * from './handle-select-form-errors.directive'; 5 export * from './share-link.directive'; -
src/Clients/Angular/finki-chattery/src/app/shared-app/models/index.ts
r81e1ed6 r79ae621 1 1 export * from './error.models'; 2 2 export * from './user.models'; 3 export * from './question-state-view-models.models'; 4 export * from './category-state-view-models.models'; 5 export * from './question-state-enums.models'; 3 6 export * from './categories.models'; -
src/Clients/Angular/finki-chattery/src/app/shared-app/pipes/moment-date.pipe.ts
r81e1ed6 r79ae621 6 6 }) 7 7 export class MomentDatePipe implements PipeTransform { 8 transform(value: moment.Moment , dateFormat: string): any {8 transform(value: moment.Moment | undefined | null, dateFormat: string): any { 9 9 return moment(value).format(dateFormat); 10 10 } -
src/Clients/Angular/finki-chattery/src/app/shared-app/services/translate-from-json.service.ts
r81e1ed6 r79ae621 43 43 } 44 44 45 public instant(key?: string): string | undefined { 46 if (key) { 47 return this.translateService.instant(key); 48 } 49 return undefined; 45 public instant(key: string): string { 46 return this.translateService.instant(key); 50 47 } 51 48 } -
src/Clients/Angular/finki-chattery/src/app/shared-app/shared-app.module.ts
r81e1ed6 r79ae621 9 9 import { EditorModule } from '@tinymce/tinymce-angular'; 10 10 11 import { COMPONENTS } from './components/ generic/components';11 import { COMPONENTS } from './components/components'; 12 12 import { SharedMaterialModule } from '../shared-material/shared-material.module'; 13 13 import { DIRECTIVES } from './directives/directives'; 14 14 import { SERVICES } from './services/services'; 15 15 import { PIPES } from './pipes/pipes'; 16 import { FileUploadComponent } from './components/generic/file-upload/file-upload.component';17 import { HandleSelectFormErrorsDirective } from './directives/handle-select-form-errors.directive';18 16 19 17 @NgModule({ 20 declarations: [COMPONENTS, DIRECTIVES, PIPES , FileUploadComponent, HandleSelectFormErrorsDirective],18 declarations: [COMPONENTS, DIRECTIVES, PIPES], 21 19 providers: [SERVICES], 22 20 imports: [ -
src/Clients/Angular/finki-chattery/src/app/shared-material/shared-material.module.ts
r81e1ed6 r79ae621 20 20 import { MatDatepickerModule } from '@angular/material/datepicker'; 21 21 import { MatNativeDateModule } from '@angular/material/core'; 22 import { MatChipsModule } from '@angular/material/chips'; 23 import { MatTooltipModule } from '@angular/material/tooltip'; 24 import { MatButtonToggleModule } from '@angular/material/button-toggle'; 25 import { MatBadgeModule } from '@angular/material/badge'; 26 22 27 @NgModule({ 23 28 imports: [ … … 40 45 MatTableModule, 41 46 MatDatepickerModule, 42 MatNativeDateModule 47 MatNativeDateModule, 48 MatChipsModule, 49 MatTooltipModule, 50 MatButtonToggleModule, 51 MatBadgeModule 43 52 ], 44 53 exports: [ … … 60 69 MatTableModule, 61 70 MatDatepickerModule, 62 MatNativeDateModule 71 MatNativeDateModule, 72 MatChipsModule, 73 MatTooltipModule, 74 MatButtonToggleModule, 75 MatBadgeModule 63 76 ] 64 77 }) -
src/Clients/Angular/finki-chattery/src/assets/translations/en.json
r81e1ed6 r79ae621 14 14 "password-not-match": "Passwords don't match", 15 15 "code-date-passed": "The code date has passed", 16 "not-found": "Not found" 16 "not-found": "Not found", 17 "question-preview-subtitle": "Asked <b>{{createdOn}}</b>, Last active <b>{{lastActive}}</b>, Viewed <b>{{views}}</b> times", 18 "share-link": "Share", 19 "share-link-success": "Successfully copied link for sharing", 20 "question-asked-by-subtitle": "Asked on: {{date}}", 21 "question-answers": "{{answerCount}} Answers", 22 "question-answered-by-subtitle": "Answered on: {{date}}", 23 "student-reputation": "{{reputation}} reputation", 24 "vote-correct-answer": "This has been accepted as the correct answer by the owner of the question", 25 "answer-sort-oldest": "Oldest", 26 "answer-sort-votes": "Votes", 27 "internet-techologies": "Internet technologies", 28 "software-engineering": "Software engineering", 29 "visual-programming": "Visual programming", 30 "operating-systems": "Operating systems", 31 "internet-programming": "Internet programming", 32 "object-oriented-programming": "Object oriented programming", 33 "calculus": "Calculus", 34 "discrete-mathematics": "Discrete mathematics", 35 "web-programming": "Web programming", 36 "advanced-programming": "Advanced programming", 37 "questions-preview-find-question": "Search for a question", 38 "questions-preview-find-question-categories": "Search in categories", 39 "questions-search": "Search", 40 "questions-preview": "Preview questions", 41 "question-sort-newest": "Newest", 42 "question-sort-popular": "Most popular", 43 "questions-preview-question-subtitle": "Asked on: {{date}}", 44 "questions-preview-question-answers": "Answers", 45 "questions-preview-question-views": "Views", 46 "questions-search-title": "Search results for: {{searchQuery}}" 17 47 } -
src/Clients/Angular/finki-chattery/src/styles.scss
r81e1ed6 r79ae621 264 264 265 265 .avatar-image { 266 width: 100px;267 height: 100px;266 width: 80px; 267 height: 80px; 268 268 display: block; 269 269 border-radius: 50%; … … 285 285 z-index: 1100 !important; 286 286 } 287 288 .full-width { 289 width: 100%; 290 }
Note:
See TracChangeset
for help on using the changeset viewer.