Changeset 70e04f1
- Timestamp:
- 10/22/21 21:46:23 (3 years ago)
- Branches:
- dev
- Children:
- 8b6791f
- Parents:
- 81c2e6f
- Location:
- src
- Files:
-
- 18 added
- 29 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
src/Clients/Angular/finki-chattery/src/app/core/state/question-facade.service.ts
r81c2e6f r70e04f1 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 r70e04f1 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 r70e04f1 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 r70e04f1 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 r70e04f1 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 r70e04f1 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 r70e04f1 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 r70e04f1 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 r70e04f1 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 r70e04f1 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 r70e04f1 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 r70e04f1 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 r70e04f1 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 r70e04f1 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 r70e04f1 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 r70e04f1 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 r70e04f1 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 r70e04f1 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 r70e04f1 285 285 z-index: 1100 !important; 286 286 } 287 288 .full-width { 289 width: 100%; 290 } -
src/FinkiChattery/FinkiChattery.Api/ApplicationServices/Questioning/Mapper/CategoryMapper.cs
r81c2e6f r70e04f1 1 using FinkiChattery.Contracts.Questioning .GetCategories;1 using FinkiChattery.Contracts.Questioning; 2 2 using FinkiChattery.Persistence.Models; 3 3 using System.Collections.Generic; … … 8 8 public static class CategoryMapper 9 9 { 10 public static List<Category Dto> ToCategoryDtos(this IEnumerable<Category> categories)10 public static List<CategoryResponse> ToCategoryDtos(this IEnumerable<Category> categories) 11 11 { 12 var categoryDtos = new List<Category Dto>();12 var categoryDtos = new List<CategoryResponse>(); 13 13 14 14 if (categories.Any()) 15 15 { 16 categoryDtos = categories.Select(x => new Category Dto(x.Uid, x.Name)).ToList();16 categoryDtos = categories.Select(x => new CategoryResponse(x.Uid, x.Name)).ToList(); 17 17 } 18 18 -
src/FinkiChattery/FinkiChattery.Api/ApplicationServices/Questioning/Mapper/QuestionMapper.cs
r81c2e6f r70e04f1 1 1 #nullable enable 2 2 3 using FinkiChattery.Contracts.Questioning .GetQuestionState;3 using FinkiChattery.Contracts.Questioning; 4 4 using FinkiChattery.Persistence.Repositories.Contracts; 5 5 using System.Collections.Generic; … … 10 10 public static class QuestionMapper 11 11 { 12 public static List<PreviewQuestionResponse> ToPreviewQuestionsResponse(this IEnumerable<QuestionPreviewDto> questions) 13 { 14 var questionsResponse = new List<PreviewQuestionResponse>(); 15 16 if (questions.Any()) 17 { 18 questionsResponse = questions.Select(x => 19 { 20 var questionCategoriesResponse = new List<PreviewQuestionCategoryResponse>(); 21 22 if (x.Categories.Any()) 23 { 24 questionCategoriesResponse = x.Categories.Select(y => new PreviewQuestionCategoryResponse(y.Id, y.Uid, y.Text)).ToList(); 25 } 26 27 return new PreviewQuestionResponse(x.Id, x.Uid, x.Title, x.Views, x.AnswersCount, x.CreatedOn, questionCategoriesResponse); 28 }).ToList(); 29 } 30 31 return questionsResponse; 32 } 33 12 34 public static QuestionStateResponse ToQuestionStateResponse(this QuestionStateDto questionState) 13 35 { -
src/FinkiChattery/FinkiChattery.Api/Controllers/v1/QuestionsController.cs
r81c2e6f r70e04f1 40 40 return Ok(questionDto.ToQuestionStateResponse()); 41 41 } 42 43 [HttpGet("preview")] 44 [Authorize] 45 public async Task<IActionResult> PreviewQuestions([FromQuery] GetPreviewQuestionsOrderEnum order) 46 { 47 var questions = await MediatorService.SendQueryAsync(new GetPreviewQuestionsQuery(order)); 48 return Ok(questions.ToPreviewQuestionsResponse()); 49 } 42 50 } 43 51 } -
src/FinkiChattery/FinkiChattery.Contracts/Questioning/GetCategories/CategoryResponse.cs
r81c2e6f r70e04f1 1 1 using System; 2 2 3 namespace FinkiChattery.Contracts.Questioning .GetCategories3 namespace FinkiChattery.Contracts.Questioning 4 4 { 5 public class Category Dto5 public class CategoryResponse 6 6 { 7 public Category Dto(Guid uid, string name)7 public CategoryResponse(Guid uid, string name) 8 8 { 9 9 Uid = uid; -
src/FinkiChattery/FinkiChattery.Contracts/Questioning/GetQuestionState/QuestionStateResponse.cs
r81c2e6f r70e04f1 5 5 using System.Text.Json.Serialization; 6 6 7 namespace FinkiChattery.Contracts.Questioning .GetQuestionState7 namespace FinkiChattery.Contracts.Questioning 8 8 { 9 9 public class QuestionStateResponse -
src/FinkiChattery/FinkiChattery.Database/dbo/Tables/Question/Question.Debug.Seed.sql
r81c2e6f r70e04f1 9 9 VALUES 10 10 (1, N'aee193c3-9d36-4ed8-81b2-15eb4ff305f1', N'Question 1', 'Question 1 text', 1, GETUTCDATE(), NULL, 0, 11 GETUTCDATE() 11 GETUTCDATE(), 2 12 12 ), 13 13 (2, N'bee193c3-9d36-4ed8-81b2-15eb4ff305f1', N'Question 2', 'Question 2 text', 1, GETUTCDATE(), NULL, 0, 14 GETUTCDATE() 14 GETUTCDATE(), 2 15 15 ) 16 ) AS temp ([ID], [Uid], [Title], [Text], [StudentFk], [CreatedOn], [TeamFk], [Views], [LastActiveOn] )16 ) AS temp ([ID], [Uid], [Title], [Text], [StudentFk], [CreatedOn], [TeamFk], [Views], [LastActiveOn], [AnswersCount]) 17 17 ) AS S 18 18 ON T.[ID] = S.[ID] … … 25 25 T.[TeamFk] = S.[TeamFk], 26 26 T.[Views] = S.[Views], 27 T.[LastActiveOn] = S.[LastActiveOn] 27 T.[LastActiveOn] = S.[LastActiveOn], 28 T.[AnswersCount] = S.[AnswersCount] 28 29 WHEN NOT MATCHED THEN 29 30 INSERT … … 37 38 [TeamFk], 38 39 [Views], 39 [LastActiveOn] 40 [LastActiveOn], 41 [AnswersCount] 40 42 ) 41 43 VALUES 42 (S.[ID], S.[Uid], S.[Title], S.[Text], S.[StudentFk], S.[CreatedOn], S.[TeamFk], S.[Views], S.[LastActiveOn] );44 (S.[ID], S.[Uid], S.[Title], S.[Text], S.[StudentFk], S.[CreatedOn], S.[TeamFk], S.[Views], S.[LastActiveOn], S.[AnswersCount]); 43 45 SET IDENTITY_INSERT [dbo].[Question] OFF 44 46 END -
src/FinkiChattery/FinkiChattery.Database/dbo/Tables/Question/Question.sql
r81c2e6f r70e04f1 10 10 [LastActiveOn] SMALLDATETIME NOT NULL, 11 11 [Search] AS ([Title] + ' ' + [Text]), 12 [AnswersCount] BIGINT NOT NULL DEFAULT 0, 12 13 CONSTRAINT [PK_Question] PRIMARY KEY CLUSTERED ([Id] ASC), 13 14 CONSTRAINT [FK_Question_Student_StudentFk] FOREIGN KEY ([StudentFk]) REFERENCES [dbo].[Student] ([Id]), -
src/FinkiChattery/FinkiChattery.Persistence/Configurations/QuestionConfig.cs
r81c2e6f r70e04f1 25 25 builder.Property(x => x.LastActiveOn).HasColumnName(@"LastActiveOn").HasColumnType("smalldatetime").IsRequired(); 26 26 builder.Property(x => x.Search).HasColumnType(@"Search").HasColumnType("nvarchar").HasMaxLength(4000).IsRequired(); 27 builder.Property(x => x.AnswersCount).HasColumnType(@"AnswersCount").HasColumnType("bigint").IsRequired().HasDefaultValue(0); 27 28 28 29 builder.HasOne(x => x.Student).WithMany(x => x.Questions).HasForeignKey(x => x.StudentFk).OnDelete(DeleteBehavior.NoAction); -
src/FinkiChattery/FinkiChattery.Persistence/Models/Question.cs
r81c2e6f r70e04f1 34 34 public string Search { get; set; } 35 35 36 public long AnswersCount { get; set; } 37 36 38 public virtual ICollection<Answer> Answers { get; set; } 37 39 -
src/FinkiChattery/FinkiChattery.Persistence/Repositories/Contracts/IQuestionRepo.cs
r81c2e6f r70e04f1 2 2 using FinkiChattery.Persistence.Repositories.Contracts; 3 3 using System; 4 using System.Collections.Generic; 4 5 using System.Threading.Tasks; 5 6 … … 9 10 { 10 11 Task<QuestionStateDto> GetQuestionState(Guid questionUid); 12 13 Task<List<QuestionPreviewDto>> GetPreviewQuestionsLatest(); 14 15 Task<List<QuestionPreviewDto>> GetPreviewQuestionsPopular(); 11 16 } 12 17 } -
src/FinkiChattery/FinkiChattery.Persistence/Repositories/Implementations/QuestionRepo.cs
r81c2e6f r70e04f1 4 4 using Microsoft.EntityFrameworkCore; 5 5 using System; 6 using System.Collections.Generic; 6 7 using System.Linq; 8 using System.Linq.Expressions; 7 9 using System.Threading.Tasks; 8 10 … … 13 15 public QuestionRepo(ApplicationDbContext dbContext) : base(dbContext) 14 16 { 17 } 18 19 public async Task<List<QuestionPreviewDto>> GetPreviewQuestionsLatest() 20 { 21 Expression<Func<Question, DateTime>> orderBy = x => x.CreatedOn; 22 return await GetPreviewQuestions(orderBy); 23 } 24 25 public async Task<List<QuestionPreviewDto>> GetPreviewQuestionsPopular() 26 { 27 Expression<Func<Question, long>> orderBy = x => x.Views; 28 return await GetPreviewQuestions(orderBy); 29 } 30 31 private async Task<List<QuestionPreviewDto>> GetPreviewQuestions<T>(Expression<Func<Question, T>> orderBy) 32 { 33 return await DbSet 34 .AsNoTracking() 35 .Include(x => x.QuestionCategories).ThenInclude(x => x.Category) 36 .OrderByDescending(orderBy) 37 .Select(x => new QuestionPreviewDto(x.Id, 38 x.Uid, 39 x.Title, 40 x.Views, 41 x.AnswersCount, 42 x.CreatedOn, 43 x.QuestionCategories.Select(y => new QuestionPreviewCategoryDto(y.Id, y.Uid, y.Category.Name)))) 44 .Skip(0).Take(30) 45 .ToListAsync(); 15 46 } 16 47
Note:
See TracChangeset
for help on using the changeset viewer.