Changeset 9df3069
- Timestamp:
- 11/09/21 16:13:23 (3 years ago)
- Branches:
- dev
- Children:
- 53bebc0
- Parents:
- 74ad056
- Location:
- src
- Files:
-
- 15 added
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Clients/Angular/finki-chattery/src/app/core/state/question-facade.service.ts
r74ad056 r9df3069 15 15 import { 16 16 AnswerQuestion, 17 EditAnswerQuestion, 18 EditAnswerResponse, 17 19 EffectStartedWorking, 18 20 GetPreviewQuestionsLatest, … … 91 93 } 92 94 95 public editAnswerResponse(answerUid: string, questionUid: string, answerResponseUid: string, text: string): void { 96 this.dispatchEffect(new EditAnswerResponse(questionUid, answerUid, answerResponseUid, text)); 97 } 98 99 public editAnswer(answerUid: string, questionUid: string, text: string): void { 100 this.dispatchEffect(new EditAnswerQuestion(questionUid, answerUid, text)); 101 } 102 93 103 public fetchQuestion(questionUid: string): void { 94 104 this.dispatchEffect(new GetQuestionState(questionUid)); -
src/Clients/Angular/finki-chattery/src/app/core/state/question-state/question.actions.ts
r74ad056 r9df3069 29 29 AnswerQuestion = '[Question] AnswerQuestion', 30 30 AnswerQuestionSuccess = '[Question] AnswerQuestion Success', 31 EditAnswerQuestion = '[Question] EditAnswerQuestion', 32 EditAnswerQuestionSuccess = '[Question] EditAnswerQuestion Success', 33 EditAnswerResponse = '[Question] EditAnswerResponse', 34 EditAnswerResponseSuccess = '[Question] EditAnswerResponse Success', 31 35 EffectStartedWorking = '[Question] Effect Started Working', 32 36 EffectFinishedWorking = '[Question] Effect Finished Working', 33 37 EffectFinishedWorkingError = '[Question] Effect Finished Working error' 38 } 39 40 export class EditAnswerQuestion implements Action { 41 readonly type = QuestionActionTypes.EditAnswerQuestion; 42 43 constructor(public questionUid: string, public answerUid: string, public text: string) {} 44 } 45 46 export class EditAnswerQuestionSuccess implements Action { 47 readonly type = QuestionActionTypes.EditAnswerQuestionSuccess; 48 49 constructor(public payload: AnswerQuestionStateViewModel, public answerUid: string) {} 50 } 51 52 export class EditAnswerResponse implements Action { 53 readonly type = QuestionActionTypes.EditAnswerResponse; 54 55 constructor(public questionUid: string, public answerUid: string, public answerResponseUid: string, public text: string) {} 56 } 57 58 export class EditAnswerResponseSuccess implements Action { 59 readonly type = QuestionActionTypes.EditAnswerResponseSuccess; 60 61 constructor(public payload: AnswerResponseQuestionStateViewModel, public answerUid: string, public answerResponseUid: string) {} 34 62 } 35 63 … … 157 185 | RespondToAnswerSuccess 158 186 | AnswerQuestionSuccess 187 | EditAnswerQuestionSuccess 188 | EditAnswerResponseSuccess 159 189 | EffectStartedWorking 160 190 | EffectFinishedWorking -
src/Clients/Angular/finki-chattery/src/app/core/state/question-state/question.effects.ts
r74ad056 r9df3069 19 19 AnswerQuestion, 20 20 AnswerQuestionSuccess, 21 EditAnswerQuestion, 22 EditAnswerQuestionSuccess, 23 EditAnswerResponse, 24 EditAnswerResponseSuccess, 21 25 EffectFinishedWorking, 22 26 EffectFinishedWorkingError, … … 186 190 ); 187 191 }); 192 193 editResponseToAnswer$ = createEffect(() => { 194 return this.actions$.pipe( 195 ofType<EditAnswerResponse>(QuestionActionTypes.EditAnswerResponse), 196 mergeMap((action) => { 197 return this.api 198 .put<AnswerResponseQuestionStateResponse>( 199 `v1/questions/${action.questionUid}/answers/${action.answerUid}/answerresponses/${action.answerResponseUid}`, 200 new RespondToAnswerRequest(action.text) 201 ) 202 .pipe( 203 tap((state) => this.notification.successNotification('success-edit-answer-response')), 204 switchMap((state) => [ 205 new EditAnswerResponseSuccess( 206 QuestionMapper.ToAnswerResponseQuestionStateViewModel(state), 207 action.answerUid, 208 action.answerResponseUid 209 ), 210 new EffectFinishedWorking() 211 ]), 212 catchError((err) => [new EffectFinishedWorkingError(err)]) 213 ); 214 }) 215 ); 216 }); 217 218 editAnswer$ = createEffect(() => { 219 return this.actions$.pipe( 220 ofType<EditAnswerQuestion>(QuestionActionTypes.EditAnswerQuestion), 221 mergeMap((action) => { 222 return this.api 223 .put<AnswerQuestionStateResponse>( 224 `v1/questions/${action.questionUid}/answers/${action.answerUid}`, 225 new AnswerQuestionRequest(action.text) 226 ) 227 .pipe( 228 tap((state) => this.notification.successNotification('success-edit-answer')), 229 switchMap((state) => [ 230 new EditAnswerQuestionSuccess(QuestionMapper.ToAnswerQuestionStateViewModel(state), action.answerUid), 231 new EffectFinishedWorking() 232 ]), 233 catchError((err) => [new EffectFinishedWorkingError(err)]) 234 ); 235 }) 236 ); 237 }); 188 238 } -
src/Clients/Angular/finki-chattery/src/app/core/state/question-state/question.reducers.ts
r74ad056 r9df3069 114 114 }; 115 115 } 116 case QuestionActionTypes.EditAnswerResponseSuccess: { 117 if (state.question) { 118 return { 119 ...state, 120 question: { 121 ...state.question, 122 answers: state.question.answers.map((x) => { 123 if (x.uid === action.answerUid) { 124 return { 125 ...x, 126 answerResponses: [...x.answerResponses.filter((y) => y.uid !== action.answerResponseUid), action.payload] 127 }; 128 } 129 130 return x; 131 }) 132 } 133 }; 134 } 135 136 return { 137 ...state 138 }; 139 } 140 case QuestionActionTypes.EditAnswerQuestionSuccess: { 141 if (state.question) { 142 return { 143 ...state, 144 question: { 145 ...state.question, 146 answers: state.question.answers.map((x) => { 147 if (x.uid === action.answerUid) { 148 return { 149 ...x, 150 text: action.payload.text 151 }; 152 } 153 154 return x; 155 }) 156 } 157 }; 158 } 159 160 return { 161 ...state 162 }; 163 } 116 164 case QuestionActionTypes.AnswerQuestionSuccess: { 117 165 if (state.question) { -
src/Clients/Angular/finki-chattery/src/app/shared-app/components/components.ts
r74ad056 r9df3069 7 7 import { AnswerQuestionComponent } from './question/answer-question/answer-question.component'; 8 8 import { AskQuestionSharedComponent } from './question/ask-question-shared/ask-question-shared.component'; 9 import { EditAnswerDialogComponent } from './question/edit-answer-dialog/edit-answer-dialog.component'; 10 import { EditAnswerResponseDialogComponent } from './question/edit-answer-response-dialog/edit-answer-response-dialog.component'; 9 11 import { PreviewQuestionDisplayComponent } from './question/preview-question-display/preview-question-display.component'; 10 12 import { PreviewQuestionFullComponent } from './question/preview-question-full/preview-question-full.component'; … … 28 30 TextEditorComponent, 29 31 RespondToAnswerDialogComponent, 30 AnswerQuestionComponent 32 AnswerQuestionComponent, 33 EditAnswerDialogComponent, 34 EditAnswerResponseDialogComponent 31 35 ]; -
src/Clients/Angular/finki-chattery/src/app/shared-app/components/question/question-preview/question-preview.component.html
r74ad056 r9df3069 47 47 <mat-chip class="cursor">{{ answerResponse.student.index }}</mat-chip> - 48 48 {{ answerResponse.createdOn | momentDate: 'LL' }} 49 <span 50 class="cursor text-bold" 51 *ngIf="studentQuestion.currentUserCanEditAnswerResponse(answerResponse)" 52 (click)="editAnswerResponse(question.uid, answer.uid, answerResponse.uid, answerResponse.text)" 53 >{{ 'question-preview-edit-answer-response' | translate }}</span 54 > 49 55 <hr /> 50 56 </div> … … 56 62 'question-preview-respond-to-answer-button' | translate 57 63 }}</app-button> 64 <app-button 65 *ngIf="studentQuestion.currentUserCanEditAnswer(answer)" 66 (action)="editAnswer(question.uid, answer.uid, answer.text)" 67 [buttonType]="ButtonType.Basic" 68 >{{ 'question-preview-edit-answer' | translate }}</app-button 69 > 58 70 </mat-card-actions> 59 71 </mat-card> -
src/Clients/Angular/finki-chattery/src/app/shared-app/components/question/question-preview/question-preview.component.ts
r74ad056 r9df3069 2 2 import { Component, OnInit } from '@angular/core'; 3 3 import { NotificationService } from 'src/app/core/services/notification.service'; 4 import { StudentQuestionService } from 'src/app/core/services/student-question.service'; 4 5 import { QuestionFacadeService } from 'src/app/core/state/question-facade.service'; 5 6 … … 21 22 private questionFacade: QuestionFacadeService, 22 23 private notification: NotificationService, 23 private dialog: SharedDialogService 24 private dialog: SharedDialogService, 25 public studentQuestion: StudentQuestionService 24 26 ) {} 25 27 … … 48 50 this.dialog.respondToAnswer(this.question.uid, answerUid); 49 51 } 52 53 editAnswer(questionUid: string, answerUid: string, text: string): void { 54 this.dialog.editAnswer(questionUid, answerUid, text); 55 } 56 57 editAnswerResponse(questionUid: string, answerUid: string, answerResponseUid: string, text: string): void { 58 this.dialog.editResponseToAnswer(questionUid, answerUid, answerResponseUid, text); 59 } 50 60 } -
src/Clients/Angular/finki-chattery/src/app/shared-app/components/question/respond-to-answer-dialog/respond-to-answer-dialog.component.html
r74ad056 r9df3069 13 13 </mat-dialog-content> 14 14 <mat-dialog-actions> 15 <app-button [buttonType]="ButtonType.Basic" (action)="dialogRef.close()">15 <app-button class="margin-right-sm" [buttonType]="ButtonType.Basic" (action)="dialogRef.close()"> 16 16 {{ 'close-button' | translate }} 17 17 </app-button> -
src/Clients/Angular/finki-chattery/src/app/shared-app/services/shared-dialog.service.ts
r74ad056 r9df3069 2 2 import { MatDialog, MatDialogRef } from '@angular/material/dialog'; 3 3 import { Observable } from 'rxjs'; 4 import { EditAnswerDialogComponent } from '../components/question/edit-answer-dialog/edit-answer-dialog.component'; 5 // tslint:disable-next-line: max-line-length 6 import { EditAnswerResponseDialogComponent } from '../components/question/edit-answer-response-dialog/edit-answer-response-dialog.component'; 4 7 import { RespondToAnswerDialogComponent } from '../components/question/respond-to-answer-dialog/respond-to-answer-dialog.component'; 5 8 … … 22 25 return dialogRef.afterClosed(); 23 26 } 27 28 public editResponseToAnswer(questionUid: string, answerUid: string, answerResponseUid: string, text: string): Observable<any> { 29 let dialogRef: MatDialogRef<EditAnswerResponseDialogComponent>; 30 dialogRef = this.dialog.open(EditAnswerResponseDialogComponent, { 31 width: '650px', 32 height: 'auto' 33 }); 34 35 dialogRef.componentInstance.questionUid = questionUid; 36 dialogRef.componentInstance.answerUid = answerUid; 37 dialogRef.componentInstance.answerResponseUid = answerResponseUid; 38 dialogRef.componentInstance.textFieldValue = text; 39 40 return dialogRef.afterClosed(); 41 } 42 43 public editAnswer(questionUid: string, answerUid: string, text: string): Observable<any> { 44 let dialogRef: MatDialogRef<EditAnswerDialogComponent>; 45 dialogRef = this.dialog.open(EditAnswerDialogComponent, { 46 width: '650px', 47 height: 'auto' 48 }); 49 50 dialogRef.componentInstance.questionUid = questionUid; 51 dialogRef.componentInstance.answerUid = answerUid; 52 dialogRef.componentInstance.textFieldValue = text; 53 54 return dialogRef.afterClosed(); 55 } 24 56 } -
src/Clients/Angular/finki-chattery/src/assets/translations/en.json
r74ad056 r9df3069 67 67 "answer-question-title": "Give your answer to the question", 68 68 "answer-question-button": "Answer", 69 "success-edit-answer-response": "Successfully edited response to answer", 70 "success-edit-answer": "Successfully edited answer", 71 "edit-respond-to-answer-title": "Edit answer response", 72 "edit-answer-title": "Edit answer", 73 "question-preview-edit-answer": "Edit answer", 74 "question-preview-edit-answer-response": "Edit response", 69 75 "StudentDoesNotOwnQuestion": "You do not own this question", 70 76 "AnswerAlreadyUpvoted": "You have already upvoted this answer", -
src/FinkiChattery/FinkiChattery.Api/Controllers/v1/AnswerResponsesController.cs
r74ad056 r9df3069 31 31 return Ok(answerResponse.ToAnswerResponseQuestionStateResponse()); 32 32 } 33 34 [HttpPut("{answerResponseUid:Guid}")] 35 [Authorize(AuthenticationSchemes = IdentityServerAuthenticationDefaults.AuthenticationScheme, Policy = AuthenticationPolicy.Student)] 36 public async Task<IActionResult> EditAnswerResponse([FromRoute] Guid questionUid, [FromRoute] Guid answerUid, [FromRoute] Guid answerResponseUid, [FromBody] AnswerResponseRequest request) 37 { 38 var answerResponse = await MediatorService.SendAsync(new EditAnswerResponseCommand(questionUid, answerUid, answerResponseUid, request.Text)); 39 return Ok(answerResponse.ToAnswerResponseQuestionStateResponse()); 40 } 33 41 } 34 42 } -
src/FinkiChattery/FinkiChattery.Api/Controllers/v1/AnswersController.cs
r74ad056 r9df3069 32 32 } 33 33 34 [HttpPut("{answerUid:Guid}")] 35 [Authorize(AuthenticationSchemes = IdentityServerAuthenticationDefaults.AuthenticationScheme, Policy = AuthenticationPolicy.Student)] 36 public async Task<IActionResult> EditAnswer([FromRoute] Guid questionUid, [FromRoute] Guid answerUid, [FromBody] AnswerQuestionRequest request) 37 { 38 var answer = await MediatorService.SendAsync(new EditAnswerCommand(questionUid, answerUid, request.Text)); 39 return Ok(answer.ToAnswerQuestionStateResponse()); 40 } 41 34 42 [HttpPut("{answerUid:Guid}/correct")] 35 43 [Authorize(AuthenticationSchemes = IdentityServerAuthenticationDefaults.AuthenticationScheme, Policy = AuthenticationPolicy.Student)] -
src/FinkiChattery/FinkiChattery.Commands/Questioning/QuestioningErrorCodes.cs
r74ad056 r9df3069 17 17 public const string AnswerInQuestionNotFound = "AnswerInQuestionNotFound"; 18 18 public const string StudentDoesNotOwnQuestion = "StudentDoesNotOwnQuestion"; 19 public const string StudentDoesNotOwnAnswer = "StudentDoesNotOwnAnswer"; 20 public const string StudentDoesNotOwnAnswerResponse = "StudentDoesNotOwnAnswerResponse"; 19 21 public const string AnswerIsAlreadyMarkedAsCorrect = "AnswerIsAlreadyMarkedAsCorrect"; 20 22 } -
src/FinkiChattery/FinkiChattery.Persistence/Repositories/Contracts/IAnswerRepo.cs
r74ad056 r9df3069 8 8 { 9 9 Task<bool> AnswerInQuestionExists(Guid questionUid, Guid answerUid); 10 11 Task<bool> AnswerIsOwnedByStudent(Guid answerUid, long applicationUserId); 10 12 } 11 13 } -
src/FinkiChattery/FinkiChattery.Persistence/Repositories/Contracts/IAnswerResponseRepo.cs
r74ad056 r9df3069 1 1 using FinkiChattery.Persistence.Models; 2 using System; 3 using System.Threading.Tasks; 2 4 3 5 namespace FinkiChattery.Persistence.Repositories … … 5 7 public interface IAnswerResponseRepo : IRepository<AnswerResponse> 6 8 { 9 Task<bool> StudentIsOwnerOfAnswerResponse(Guid answerResponseUid, long applicationUserId); 7 10 } 8 11 } -
src/FinkiChattery/FinkiChattery.Persistence/Repositories/Implementations/AnswerRepo.cs
r74ad056 r9df3069 21 21 .AnyAsync(); 22 22 } 23 24 public async Task<bool> AnswerIsOwnedByStudent(Guid answerUid, long applicationUserId) 25 { 26 return await DbSet 27 .AsNoTracking() 28 .Where(x => x.Uid == answerUid && x.Student.ApplicationUserFk == applicationUserId) 29 .AnyAsync(); 30 } 23 31 } 24 32 } -
src/FinkiChattery/FinkiChattery.Persistence/Repositories/Implementations/AnswerResponseRepo.cs
r74ad056 r9df3069 1 1 using FinkiChattery.Persistence.Context; 2 2 using FinkiChattery.Persistence.Models; 3 using Microsoft.EntityFrameworkCore; 4 using System; 5 using System.Linq; 6 using System.Threading.Tasks; 3 7 4 8 namespace FinkiChattery.Persistence.Repositories … … 9 13 { 10 14 } 15 16 public async Task<bool> StudentIsOwnerOfAnswerResponse(Guid answerResponseUid, long applicationUserId) 17 { 18 return await DbSet 19 .AsNoTracking() 20 .Where(x => x.Uid == answerResponseUid && x.Student.ApplicationUserFk == applicationUserId) 21 .AnyAsync(); 22 } 11 23 } 12 24 }
Note:
See TracChangeset
for help on using the changeset viewer.