Changeset 8b6791f for src/Clients/Angular
- Timestamp:
- 10/22/21 21:47:17 (3 years ago)
- Branches:
- dev
- Children:
- 466d1ac, 5ad5988
- Parents:
- 81c2e6f (diff), 70e04f1 (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/src
- Files:
-
- 13 added
- 19 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Clients/Angular/finki-chattery/src/app/core/state/question-facade.service.ts
r81c2e6f r8b6791f 5 5 import { catchError, filter, map } from 'rxjs/operators'; 6 6 7 import { QuestionStateViewModel } from 'src/app/shared-app/models'; 8 import { EffectStartedWorking, GetQuestionState } from './question-state/question.actions'; 7 import { PreviewQuestionsOrderEnum, PreviewQuestionViewModel, QuestionStateViewModel } from 'src/app/shared-app/models'; 8 import { 9 EffectStartedWorking, 10 GetPreviewQuestionsLatest, 11 GetPreviewQuestionsPopular, 12 GetQuestionState 13 } from './question-state/question.actions'; 9 14 import { questionStateQuery } from './question-state/question.selectors'; 10 15 import { QuestionState } from './question-state/question.state'; … … 38 43 } 39 44 45 public getPreviewQuestionsLatest(): Observable<PreviewQuestionViewModel[]> { 46 return this.store.select(questionStateQuery.getPreviewQuestionsLatest); 47 } 48 49 public getPreviewQuestionsPopular(): Observable<PreviewQuestionViewModel[]> { 50 return this.store.select(questionStateQuery.getPreviewQuestionsPopular); 51 } 52 53 public fetchPreviewQuestions(orderBy: PreviewQuestionsOrderEnum): void { 54 if (orderBy === PreviewQuestionsOrderEnum.Latest) { 55 this.fetchPreviewQuestionsLatest(); 56 } else if (orderBy === PreviewQuestionsOrderEnum.Popular) { 57 this.fetchPreviewQuestionsPopular(); 58 } 59 } 60 40 61 public fetchQuestion(questionUid: string): void { 41 62 this.dispatchEffect(new GetQuestionState(questionUid)); 63 } 64 65 private fetchPreviewQuestionsLatest(): void { 66 this.dispatchEffect(new GetPreviewQuestionsLatest()); 67 } 68 69 private fetchPreviewQuestionsPopular(): void { 70 this.dispatchEffect(new GetPreviewQuestionsPopular()); 42 71 } 43 72 -
src/Clients/Angular/finki-chattery/src/app/core/state/question-state/question-state.models.ts
r81c2e6f r8b6791f 59 59 public reputation!: number; 60 60 } 61 62 export class PreviewQuestionResponse { 63 public uid!: string; 64 public title!: string; 65 public createdOn!: moment.Moment; 66 public views!: number; 67 public answersCount!: number; 68 public categories!: PreviewQuestionCategoryResponse[]; 69 } 70 71 export class PreviewQuestionCategoryResponse { 72 public uid!: string; 73 public text!: string; 74 } -
src/Clients/Angular/finki-chattery/src/app/core/state/question-state/question.actions.ts
r81c2e6f r8b6791f 2 2 import { Action } from '@ngrx/store'; 3 3 4 import { QuestionStateViewModel } from 'src/app/shared-app/models'; 4 import { PreviewQuestionViewModel, QuestionStateViewModel } from 'src/app/shared-app/models'; 5 import { PreviewQuestionResponse } from './question-state.models'; 5 6 6 7 export enum QuestionActionTypes { 7 8 GetQuestionState = '[Question] Get state', 8 9 GetQuestionStateSuccess = '[Question] Get state success', 10 GetPreviewQuestionsLatest = '[Question] Get preview questions Latest', 11 GetPreviewQuestionsLatestSuccess = '[Question] Get preview questions Latest Success', 12 GetPreviewQuestionsPopular = '[Question] Get preview questions Popular', 13 GetPreviewQuestionsPopularSuccess = '[Question] Get preview questions Popular Success', 9 14 EffectStartedWorking = '[Question] Effect Started Working', 10 15 EffectFinishedWorking = '[Question] Effect Finished Working', … … 22 27 23 28 constructor(public payload: QuestionStateViewModel) {} 29 } 30 31 export class GetPreviewQuestionsLatest implements Action { 32 readonly type = QuestionActionTypes.GetPreviewQuestionsLatest; 33 34 constructor() {} 35 } 36 37 export class GetPreviewQuestionsLatestSuccess implements Action { 38 readonly type = QuestionActionTypes.GetPreviewQuestionsLatestSuccess; 39 40 constructor(public payload: PreviewQuestionViewModel[]) {} 41 } 42 43 export class GetPreviewQuestionsPopular implements Action { 44 readonly type = QuestionActionTypes.GetPreviewQuestionsPopular; 45 46 constructor() {} 47 } 48 49 export class GetPreviewQuestionsPopularSuccess implements Action { 50 readonly type = QuestionActionTypes.GetPreviewQuestionsPopularSuccess; 51 52 constructor(public payload: PreviewQuestionViewModel[]) {} 24 53 } 25 54 … … 42 71 } 43 72 44 export type QuestionAction = GetQuestionStateSuccess | EffectStartedWorking | EffectFinishedWorking | EffectFinishedWorkingError; 73 export type QuestionAction = 74 | GetQuestionStateSuccess 75 | GetPreviewQuestionsLatestSuccess 76 | GetPreviewQuestionsPopularSuccess 77 | EffectStartedWorking 78 | EffectFinishedWorking 79 | EffectFinishedWorkingError; -
src/Clients/Angular/finki-chattery/src/app/core/state/question-state/question.effects.ts
r81c2e6f r8b6791f 1 1 import { Injectable } from '@angular/core'; 2 2 import { Actions, createEffect, ofType } from '@ngrx/effects'; 3 import { catchError, switchMap } from 'rxjs/operators'; 3 import { catchError, filter, switchMap, withLatestFrom } from 'rxjs/operators'; 4 import { PreviewQuestionsOrderEnum } from 'src/app/shared-app/models'; 5 import { TranslateFromJsonService } from 'src/app/shared-app/services'; 4 6 5 7 import { BaseApiService } from 'src/app/shared-app/services/base-api.service'; 6 import { QuestionStateResponse } from './question-state.models'; 8 import { QuestionFacadeService } from '../question-facade.service'; 9 import { PreviewQuestionResponse, QuestionStateResponse } from './question-state.models'; 7 10 import { 8 11 EffectFinishedWorking, 9 12 EffectFinishedWorkingError, 13 GetPreviewQuestionsLatestSuccess, 14 GetPreviewQuestionsPopularSuccess, 10 15 GetQuestionState, 11 16 GetQuestionStateSuccess, … … 18 23 }) 19 24 export class QuestionEffects { 20 constructor(private actions$: Actions, private api: BaseApiService) {} 25 constructor( 26 private actions$: Actions, 27 private api: BaseApiService, 28 private translate: TranslateFromJsonService, 29 private facade: QuestionFacadeService 30 ) {} 21 31 22 32 getQuestionState$ = createEffect(() => { … … 31 41 ); 32 42 }); 43 44 getPreviewQuestionsLatest$ = createEffect(() => { 45 return this.actions$.pipe( 46 ofType<GetQuestionState>(QuestionActionTypes.GetPreviewQuestionsLatest), 47 withLatestFrom(this.facade.getPreviewQuestionsLatest()), 48 filter(([action, questions]) => questions.length === 0), 49 switchMap((action) => { 50 return this.api.get<PreviewQuestionResponse[]>(`v1/questions/preview?order=${PreviewQuestionsOrderEnum.Latest}`).pipe( 51 switchMap((state) => [ 52 new GetPreviewQuestionsLatestSuccess(QuestionMapper.ToPreviwQuestionsViewModel(state, this.translate)), 53 new EffectFinishedWorking() 54 ]), 55 catchError((err) => [new EffectFinishedWorkingError(err)]) 56 ); 57 }) 58 ); 59 }); 60 61 getPreviewQuestionsPopular$ = createEffect(() => { 62 return this.actions$.pipe( 63 ofType<GetQuestionState>(QuestionActionTypes.GetPreviewQuestionsPopular), 64 withLatestFrom(this.facade.getPreviewQuestionsPopular()), 65 filter(([action, questions]) => questions.length === 0), 66 switchMap((action) => { 67 return this.api.get<PreviewQuestionResponse[]>(`v1/questions/preview?order=${PreviewQuestionsOrderEnum.Popular}`).pipe( 68 switchMap((state) => [ 69 new GetPreviewQuestionsPopularSuccess(QuestionMapper.ToPreviwQuestionsViewModel(state, this.translate)), 70 new EffectFinishedWorking() 71 ]), 72 catchError((err) => [new EffectFinishedWorkingError(err)]) 73 ); 74 }) 75 ); 76 }); 33 77 } -
src/Clients/Angular/finki-chattery/src/app/core/state/question-state/question.mapper.ts
r81c2e6f r8b6791f 5 5 AnswerResponseStudentQuestionStateViewModel, 6 6 AnswerStudentQuestionStateViewModel, 7 PreviewQuestionCategoryViewModel, 8 PreviewQuestionViewModel, 7 9 QuestionCategoryQuestionStateViewModel, 8 10 QuestionStateViewModel, … … 10 12 TeamQuestionStateViewModel 11 13 } from 'src/app/shared-app/models'; 12 import { QuestionStateResponse } from './question-state.models'; 14 import { TranslateFromJsonService } from 'src/app/shared-app/services'; 15 import { PreviewQuestionCategoryResponse, PreviewQuestionResponse, QuestionStateResponse } from './question-state.models'; 13 16 14 17 export class QuestionMapper { … … 84 87 ); 85 88 } 89 90 public static ToPreviwQuestionsViewModel( 91 previewQuestionsResponse: PreviewQuestionResponse[], 92 translate: TranslateFromJsonService 93 ): PreviewQuestionViewModel[] { 94 let questions = new Array<PreviewQuestionViewModel>(); 95 96 if (previewQuestionsResponse.length > 0) { 97 questions = previewQuestionsResponse.map((x) => { 98 let categories = new Array<PreviewQuestionCategoryViewModel>(); 99 100 if (x.categories.length > 0) { 101 categories = x.categories.map((y) => new PreviewQuestionCategoryViewModel(y.uid, y.text, translate.instant(y.text))); 102 } 103 104 return new PreviewQuestionViewModel(x.uid, x.title, moment(x.createdOn), x.views, x.answersCount, categories); 105 }); 106 } 107 108 return questions; 109 } 86 110 } -
src/Clients/Angular/finki-chattery/src/app/core/state/question-state/question.reducers.ts
r81c2e6f r8b6791f 8 8 ...state, 9 9 question: action.payload 10 }; 11 case QuestionActionTypes.GetPreviewQuestionsLatestSuccess: 12 return { 13 ...state, 14 previewQuestionsLatest: action.payload 15 }; 16 case QuestionActionTypes.GetPreviewQuestionsPopularSuccess: 17 return { 18 ...state, 19 previewQuestionsPopular: action.payload 10 20 }; 11 21 case QuestionActionTypes.EffectStartedWorking: { -
src/Clients/Angular/finki-chattery/src/app/core/state/question-state/question.selectors.ts
r81c2e6f r8b6791f 5 5 6 6 const getQuestion = createSelector(getQuestionState, (state) => state.question); 7 const getPreviewQuestionsLatest = createSelector(getQuestionState, (state) => state.previewQuestionsLatest); 8 const getPreviewQuestionsPopular = createSelector(getQuestionState, (state) => state.previewQuestionsPopular); 7 9 const effectWorking = createSelector(getQuestionState, (state) => state.effectWorking); 8 10 9 11 export const questionStateQuery = { 10 12 effectWorking, 11 getQuestion 13 getQuestion, 14 getPreviewQuestionsLatest, 15 getPreviewQuestionsPopular 12 16 }; -
src/Clients/Angular/finki-chattery/src/app/core/state/question-state/question.state.ts
r81c2e6f r8b6791f 1 1 import { HttpErrorResponse } from '@angular/common/http'; 2 import { QuestionStateViewModel } from 'src/app/shared-app/models';2 import { PreviewQuestionViewModel, QuestionStateViewModel } from 'src/app/shared-app/models'; 3 3 4 4 export const questionStateKey = 'question'; … … 6 6 export interface QuestionState { 7 7 question: QuestionStateViewModel | null; 8 previewQuestionsLatest: PreviewQuestionViewModel[]; 9 previewQuestionsPopular: PreviewQuestionViewModel[]; 8 10 effectWorking: boolean | HttpErrorResponse; 9 11 } … … 11 13 export const initialState: QuestionState = { 12 14 question: null, 15 previewQuestionsLatest: [], 16 previewQuestionsPopular: [], 13 17 effectWorking: false 14 18 }; -
src/Clients/Angular/finki-chattery/src/app/modules/questioning/components/questioning-components.ts
r81c2e6f r8b6791f 1 1 import { QuestionPreviewGeneralComponent } from './question-preview-general/question-preview-general.component'; 2 import { QuestioningGeneralComponent } from './questioning-general/questioning-general.component'; 2 3 import { QuestionsPreviewGeneralComponent } from './questions-preview-general/questions-preview-general.component'; 3 4 4 export const QUESTIONING_COMPONENTS: any[] = [QuestionPreviewGeneralComponent, QuestionsPreviewGeneralComponent]; 5 export const QUESTIONING_COMPONENTS: any[] = [ 6 QuestionPreviewGeneralComponent, 7 QuestionsPreviewGeneralComponent, 8 QuestioningGeneralComponent 9 ]; -
src/Clients/Angular/finki-chattery/src/app/modules/questioning/components/questions-preview-general/questions-preview-general.component.html
r81c2e6f r8b6791f 1 <p>questions-preview-general works!</p> 1 <app-search-question></app-search-question> 2 <div class="margin-x-lg"> 3 <h1 class="mat-headline">{{ 'questions-preview' | translate }}</h1> 4 <mat-button-toggle-group [formControl]="questionsSortByForm"> 5 <mat-button-toggle [value]="QuestionsSortBy.Latest">{{ 'question-sort-newest' | translate }}</mat-button-toggle> 6 <mat-button-toggle [value]="QuestionsSortBy.Popular">{{ 'question-sort-popular' | translate }}</mat-button-toggle> 7 </mat-button-toggle-group> 8 </div> 9 <app-preview-question-display 10 *ngFor="let question of previewQuestions$ | async" 11 [question]="question" 12 (questionClicked)="goToQuestion(question.uid)" 13 ></app-preview-question-display> -
src/Clients/Angular/finki-chattery/src/app/modules/questioning/components/questions-preview-general/questions-preview-general.component.ts
r81c2e6f r8b6791f 1 1 import { Component, OnInit } from '@angular/core'; 2 import { FormControl } from '@angular/forms'; 3 import { Router } from '@angular/router'; 2 4 import { CategoryFacadeService } from 'src/app/core/state/category-facade.service'; 5 import { QuestionFacadeService } from 'src/app/core/state/question-facade.service'; 6 import { CategoryStateViewModel, PreviewQuestionsOrderEnum } from 'src/app/shared-app/models'; 3 7 4 8 @Component({ … … 8 12 }) 9 13 export class QuestionsPreviewGeneralComponent implements OnInit { 10 constructor(private categoriesFacade: CategoryFacadeService) {} 14 categories?: CategoryStateViewModel[]; 15 previewQuestions$ = this.questionFacade.getPreviewQuestionsLatest(); 16 QuestionsSortBy = PreviewQuestionsOrderEnum; 17 questionsSortByForm = new FormControl(PreviewQuestionsOrderEnum.Latest); 18 19 constructor(private categoriesFacade: CategoryFacadeService, private questionFacade: QuestionFacadeService, private router: Router) {} 11 20 12 21 ngOnInit(): void { 13 22 this.categoriesFacade.fetchCategories(); 23 this.questionFacade.fetchPreviewQuestions(PreviewQuestionsOrderEnum.Latest); 24 this.questionsSortByForm.valueChanges.subscribe((value: PreviewQuestionsOrderEnum) => { 25 this.questionFacade.fetchPreviewQuestions(value); 26 27 if (value === PreviewQuestionsOrderEnum.Latest) { 28 this.previewQuestions$ = this.questionFacade.getPreviewQuestionsLatest(); 29 } else if (value === PreviewQuestionsOrderEnum.Popular) { 30 this.previewQuestions$ = this.questionFacade.getPreviewQuestionsPopular(); 31 } 32 }); 33 } 34 35 goToQuestion(uid: string): void { 36 this.router.navigateByUrl(`questioning/${uid}`); 14 37 } 15 38 } -
src/Clients/Angular/finki-chattery/src/app/modules/questioning/questioning.routes.ts
r81c2e6f r8b6791f 2 2 import { Routes, RouterModule } from '@angular/router'; 3 3 import { QuestionPreviewGeneralComponent } from './components/question-preview-general/question-preview-general.component'; 4 import { QuestioningGeneralComponent } from './components/questioning-general/questioning-general.component'; 4 5 import { QuestionsPreviewGeneralComponent } from './components/questions-preview-general/questions-preview-general.component'; 5 6 6 7 const routes: Routes = [ 7 8 { 8 path: 'preview', 9 pathMatch: 'full', 10 component: QuestionsPreviewGeneralComponent 11 }, 12 { 13 path: ':questionUid', 14 component: QuestionPreviewGeneralComponent 9 component: QuestioningGeneralComponent, 10 path: '', 11 children: [ 12 { 13 path: 'preview', 14 pathMatch: 'full', 15 component: QuestionsPreviewGeneralComponent 16 }, 17 { 18 path: ':questionUid', 19 component: QuestionPreviewGeneralComponent 20 } 21 ] 15 22 } 16 23 ]; -
src/Clients/Angular/finki-chattery/src/app/shared-app/components/components.ts
r81c2e6f r8b6791f 4 4 import { HeaderComponent } from './generic/header/header.component'; 5 5 import { VoteComponent } from './generic/vote/vote.component'; 6 import { PreviewQuestionDisplayComponent } from './question/preview-question-display/preview-question-display.component'; 6 7 import { QuestionPreviewComponent } from './question/question-preview/question-preview.component'; 8 import { SearchQuestionComponent } from './question/search-question/search-question.component'; 7 9 import { StudentCardComponent } from './question/student-card/student-card.component'; 8 10 … … 14 16 VoteComponent, 15 17 StudentCardComponent, 16 HeaderComponent 18 HeaderComponent, 19 SearchQuestionComponent, 20 PreviewQuestionDisplayComponent 17 21 ]; -
src/Clients/Angular/finki-chattery/src/app/shared-app/models/index.ts
r81c2e6f r8b6791f 3 3 export * from './question-state-view-models.models'; 4 4 export * from './category-state-view-models.models'; 5 export * from './question-state-enums.models'; -
src/Clients/Angular/finki-chattery/src/app/shared-app/models/question-state-view-models.models.ts
r81c2e6f r8b6791f 54 54 constructor(public uid: string, public index: string, public imageUrl: string, public reputation: number) {} 55 55 } 56 57 export class PreviewQuestionViewModel { 58 constructor( 59 public uid: string, 60 public title: string, 61 public createdOn: moment.Moment, 62 public views: number, 63 public answersCount: number, 64 public categories: PreviewQuestionCategoryViewModel[] 65 ) {} 66 } 67 68 export class PreviewQuestionCategoryViewModel { 69 constructor(public uid: string, public text: string, public nameTranslated: string) {} 70 } -
src/Clients/Angular/finki-chattery/src/app/shared-app/pipes/moment-date.pipe.ts
r81c2e6f r8b6791f 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-material/shared-material.module.ts
r81c2e6f r8b6791f 23 23 import { MatTooltipModule } from '@angular/material/tooltip'; 24 24 import { MatButtonToggleModule } from '@angular/material/button-toggle'; 25 import { MatBadgeModule } from '@angular/material/badge'; 25 26 26 27 @NgModule({ … … 47 48 MatChipsModule, 48 49 MatTooltipModule, 49 MatButtonToggleModule 50 MatButtonToggleModule, 51 MatBadgeModule 50 52 ], 51 53 exports: [ … … 70 72 MatChipsModule, 71 73 MatTooltipModule, 72 MatButtonToggleModule 74 MatButtonToggleModule, 75 MatBadgeModule 73 76 ] 74 77 }) -
src/Clients/Angular/finki-chattery/src/assets/translations/en.json
r81c2e6f r8b6791f 28 28 "software-engineering": "Software engineering", 29 29 "visual-programming": "Visual programming", 30 "operating-systems": "Operating systems" 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" 31 46 } -
src/Clients/Angular/finki-chattery/src/styles.scss
r81c2e6f r8b6791f 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.