From 21b10552fc6809c92a3b871ce17d8cf652c4c1f2 Mon Sep 17 00:00:00 2001 From: Geoffrey Kwan Date: Mon, 18 Sep 2023 18:03:16 -0400 Subject: [PATCH] feat(Question Bank): Click question to add to student response input (#1416) Co-authored-by: Jonathan Lim-Breitbart --- .../edit-question-bank-rules.component.html | 26 +++++-- ...edit-question-bank-rules.component.spec.ts | 36 +++++++-- .../edit-question-bank-rules.component.ts | 13 +++- .../edit-question-bank.component.html | 29 ++++++- .../edit-question-bank.component.scss | 2 +- .../edit-question-bank.component.ts | 20 ++++- .../peer-chat-chat-box.component.html | 4 +- .../peer-chat-chat-box.component.ts | 39 +++++----- .../peer-chat-grading.component.html | 2 + .../peer-chat-message-input.component.html | 1 + .../peer-chat-message-input.component.ts | 34 +++++--- .../peer-chat-question-bank/Question.ts | 10 +++ .../peer-chat-question-bank/QuestionBank.ts | 3 + .../QuestionBankRule.ts | 3 +- .../peer-chat-question-bank.component.html | 64 +++++++++++++-- .../peer-chat-question-bank.component.scss | 16 +++- .../peer-chat-question-bank.component.spec.ts | 4 +- .../peer-chat-question-bank.component.ts | 20 ++++- .../question-bank-helper.ts | 8 ++ .../questionBank.service.ts | 13 ++++ .../peer-chat-show-work.component.html | 2 + .../peer-chat-show-work.component.ts | 40 ++++++---- .../peer-chat-student.component.html | 4 + .../peer-chat-student.component.ts | 34 +++++++- .../components/peerChat/peer-chat.module.ts | 4 +- .../components/peerChat/peerChatService.ts | 2 +- src/messages.xlf | 77 ++++++++++++++----- 27 files changed, 407 insertions(+), 103 deletions(-) create mode 100644 src/assets/wise5/components/peerChat/peer-chat-question-bank/Question.ts create mode 100644 src/assets/wise5/components/peerChat/peer-chat-question-bank/question-bank-helper.ts create mode 100644 src/assets/wise5/components/peerChat/peer-chat-question-bank/questionBank.service.ts diff --git a/src/app/authoring-tool/edit-question-bank-rules/edit-question-bank-rules.component.html b/src/app/authoring-tool/edit-question-bank-rules/edit-question-bank-rules.component.html index b09cbbb79d..ee4bac274c 100644 --- a/src/app/authoring-tool/edit-question-bank-rules/edit-question-bank-rules.component.html +++ b/src/app/authoring-tool/edit-question-bank-rules/edit-question-bank-rules.component.html @@ -63,13 +63,25 @@
Question #{{ questionIndex + 1 }} - + + + + + + + +
+ + check_circle + Used in chat + +
+ + + + {{ question.text }} + + + + {{ question }} + - + diff --git a/src/assets/wise5/components/peerChat/peer-chat-question-bank/peer-chat-question-bank.component.scss b/src/assets/wise5/components/peerChat/peer-chat-question-bank/peer-chat-question-bank.component.scss index d259810936..6f1fee0760 100644 --- a/src/assets/wise5/components/peerChat/peer-chat-question-bank/peer-chat-question-bank.component.scss +++ b/src/assets/wise5/components/peerChat/peer-chat-question-bank/peer-chat-question-bank.component.scss @@ -4,19 +4,22 @@ padding: 8px; } -/* TODO(mdc-migration): The following rule targets internal classes of card that may no longer apply for the MDC version. */ -mat-card-content { +.questions { margin-top: 8px; padding: 8px; border-radius: $button-border-radius; overflow: auto; } -.question { - font-style: italic; +.question-button { + text-transform: none; + text-align: start; + min-height: 36px; + height: auto; } ul { + margin: 0; padding: 0; list-style-type: none; } @@ -28,3 +31,8 @@ li { margin-bottom: 0; } } + +.question-used-indicator { + width: 40px; + height: 24px; +} \ No newline at end of file diff --git a/src/assets/wise5/components/peerChat/peer-chat-question-bank/peer-chat-question-bank.component.spec.ts b/src/assets/wise5/components/peerChat/peer-chat-question-bank/peer-chat-question-bank.component.spec.ts index 5a6831226c..109573dc5d 100644 --- a/src/assets/wise5/components/peerChat/peer-chat-question-bank/peer-chat-question-bank.component.spec.ts +++ b/src/assets/wise5/components/peerChat/peer-chat-question-bank/peer-chat-question-bank.component.spec.ts @@ -12,6 +12,7 @@ import { of } from 'rxjs'; import { MatDialogModule } from '@angular/material/dialog'; import { MatCardModule } from '@angular/material/card'; import { MatIconModule } from '@angular/material/icon'; +import { QuestionBankService } from './questionBank.service'; let component: PeerChatQuestionBankComponent; let fixture: ComponentFixture; @@ -32,7 +33,8 @@ describe('PeerChatQuestionBankComponent', () => { MatIconModule, StudentTeacherCommonServicesModule ], - declarations: [PeerChatQuestionBankComponent] + declarations: [PeerChatQuestionBankComponent], + providers: [QuestionBankService] }).compileComponents(); fixture = TestBed.createComponent(PeerChatQuestionBankComponent); peerGroupService = TestBed.inject(PeerGroupService); diff --git a/src/assets/wise5/components/peerChat/peer-chat-question-bank/peer-chat-question-bank.component.ts b/src/assets/wise5/components/peerChat/peer-chat-question-bank/peer-chat-question-bank.component.ts index a816d8d082..0a502bc9a6 100644 --- a/src/assets/wise5/components/peerChat/peer-chat-question-bank/peer-chat-question-bank.component.ts +++ b/src/assets/wise5/components/peerChat/peer-chat-question-bank/peer-chat-question-bank.component.ts @@ -13,6 +13,8 @@ import { concatMap, map } from 'rxjs/operators'; import { PeerGroup } from '../PeerGroup'; import { QuestionBankContent } from './QuestionBankContent'; import { copy } from '../../../common/object/object'; +import { Question } from './Question'; +import { QuestionBankService } from './questionBank.service'; import { ConstraintService } from '../../../services/constraintService'; @Component({ @@ -24,12 +26,15 @@ export class PeerChatQuestionBankComponent implements OnInit { @Input() content: QuestionBankContent; @Input() displayedQuestionBankRules: QuestionBankRule[]; @Output() displayedQuestionBankRulesChange = new EventEmitter(); - questions: string[]; + @Input() questionIdsUsed: string[] = []; + questions: (string | Question)[]; + @Output() useQuestionEvent = new EventEmitter(); constructor( private constraintService: ConstraintService, private peerGroupService: PeerGroupService, - private projectService: ProjectService + private projectService: ProjectService, + private questionBankService: QuestionBankService ) {} ngOnInit(): void { @@ -46,6 +51,13 @@ export class PeerChatQuestionBankComponent implements OnInit { } else { this.setQuestions(this.displayedQuestionBankRules); } + this.subscribeToQuestionUsed(); + } + + private subscribeToQuestionUsed(): void { + this.questionBankService.questionUsed$.subscribe((question: Question) => { + this.questionIdsUsed.push(question.id); + }); } private evaluatePeerGroup(referenceComponent: WISEComponent): void { @@ -133,4 +145,8 @@ export class PeerChatQuestionBankComponent implements OnInit { private setQuestions(rules: QuestionBankRule[]): void { this.questions = rules.flatMap((rule) => rule.questions); } + + protected useQuestion(question: string): void { + this.useQuestionEvent.emit(question); + } } diff --git a/src/assets/wise5/components/peerChat/peer-chat-question-bank/question-bank-helper.ts b/src/assets/wise5/components/peerChat/peer-chat-question-bank/question-bank-helper.ts new file mode 100644 index 0000000000..0ecbdf3f6f --- /dev/null +++ b/src/assets/wise5/components/peerChat/peer-chat-question-bank/question-bank-helper.ts @@ -0,0 +1,8 @@ +export function getQuestionIdsUsed(componentStates: any[], workgroupId: number): string[] { + return componentStates + .filter( + (componentState) => + componentState.workgroupId === workgroupId && componentState.studentData.questionId != null + ) + .map((componentState) => componentState.studentData.questionId); +} diff --git a/src/assets/wise5/components/peerChat/peer-chat-question-bank/questionBank.service.ts b/src/assets/wise5/components/peerChat/peer-chat-question-bank/questionBank.service.ts new file mode 100644 index 0000000000..8a3f233ce1 --- /dev/null +++ b/src/assets/wise5/components/peerChat/peer-chat-question-bank/questionBank.service.ts @@ -0,0 +1,13 @@ +import { Injectable } from '@angular/core'; +import { Observable, Subject } from 'rxjs'; +import { Question } from './Question'; + +@Injectable() +export class QuestionBankService { + private questionUsedSource: Subject = new Subject(); + public questionUsed$: Observable = this.questionUsedSource.asObservable(); + + questionUsed(question: Question): void { + this.questionUsedSource.next(question); + } +} diff --git a/src/assets/wise5/components/peerChat/peer-chat-show-work/peer-chat-show-work.component.html b/src/assets/wise5/components/peerChat/peer-chat-show-work/peer-chat-show-work.component.html index 75f8c1ebe6..3d9722efad 100644 --- a/src/assets/wise5/components/peerChat/peer-chat-show-work/peer-chat-show-work.component.html +++ b/src/assets/wise5/components/peerChat/peer-chat-show-work/peer-chat-show-work.component.html @@ -9,7 +9,9 @@ >
diff --git a/src/assets/wise5/components/peerChat/peer-chat-show-work/peer-chat-show-work.component.ts b/src/assets/wise5/components/peerChat/peer-chat-show-work/peer-chat-show-work.component.ts index b0ccdb3629..b8aada63f2 100644 --- a/src/assets/wise5/components/peerChat/peer-chat-show-work/peer-chat-show-work.component.ts +++ b/src/assets/wise5/components/peerChat/peer-chat-show-work/peer-chat-show-work.component.ts @@ -12,6 +12,7 @@ import { NodeService } from '../../../services/nodeService'; import { FeedbackRule } from '../../common/feedbackRule/FeedbackRule'; import { QuestionBankRule } from '../peer-chat-question-bank/QuestionBankRule'; import { forkJoin, Observable } from 'rxjs'; +import { getQuestionIdsUsed } from '../peer-chat-question-bank/question-bank-helper'; @Component({ selector: 'peer-chat-show-work', @@ -25,6 +26,7 @@ export class PeerChatShowWorkComponent extends ComponentShowWorkDirective { peerChatWorkgroupInfos: any = {}; peerGroup: PeerGroup; questionBankRules: QuestionBankRule[]; + questionIdsUsed: string[] = []; requestTimeout: number = 10000; @Input() workgroupId: number; @@ -99,25 +101,35 @@ export class PeerChatShowWorkComponent extends ComponentShowWorkDirective { private setPeerChatMessages(componentStates: any[]): void { this.peerChatMessages = []; this.peerChatService.setPeerChatMessages(this.peerChatMessages, componentStates); - this.dynamicPrompt = this.getDynamicPrompt(componentStates); - this.questionBankRules = this.getQuestionBankRule(componentStates); + this.dynamicPrompt = this.getDynamicPrompt(componentStates, this.workgroupId); + this.questionBankRules = this.getQuestionBankRule(componentStates, this.workgroupId); + this.questionIdsUsed = getQuestionIdsUsed(componentStates, this.workgroupId); } - private getDynamicPrompt(componentStates: any[]): FeedbackRule { - for (let c = componentStates.length - 1; c >= 0; c--) { - const dynamicPrompt = componentStates[c].studentData.dynamicPrompt; - if (dynamicPrompt != null) { - return dynamicPrompt; - } - } - return null; + private getDynamicPrompt(componentStates: any[], workgroupId: number): FeedbackRule { + return this.getLatestStudentDataFieldForWorkgroup( + componentStates, + workgroupId, + 'dynamicPrompt' + ); + } + + private getQuestionBankRule(componentStates: any[], workgroupId: number): QuestionBankRule[] { + return this.getLatestStudentDataFieldForWorkgroup(componentStates, workgroupId, 'questionBank'); } - private getQuestionBankRule(componentStates: any[]): QuestionBankRule[] { + private getLatestStudentDataFieldForWorkgroup( + componentStates: any[], + workgroupId: number, + fieldName: string + ): any { for (let c = componentStates.length - 1; c >= 0; c--) { - const questionBank = componentStates[c].studentData.questionBank; - if (questionBank != null) { - return questionBank; + const componentState = componentStates[c]; + if ( + componentState.workgroupId === workgroupId && + componentState.studentData[fieldName] != null + ) { + return componentState.studentData[fieldName]; } } return null; diff --git a/src/assets/wise5/components/peerChat/peer-chat-student/peer-chat-student.component.html b/src/assets/wise5/components/peerChat/peer-chat-student/peer-chat-student.component.html index fe2d3afaa8..db585e5f0e 100644 --- a/src/assets/wise5/components/peerChat/peer-chat-student/peer-chat-student.component.html +++ b/src/assets/wise5/components/peerChat/peer-chat-student/peer-chat-student.component.html @@ -22,14 +22,18 @@ *ngIf="questionBankContent.questionBank?.enabled" [content]="questionBankContent" [(displayedQuestionBankRules)]="displayedQuestionBankRules" + (useQuestionEvent)="useQuestion($event)" + [questionIdsUsed]="questionIdsUsed" >
diff --git a/src/assets/wise5/components/peerChat/peer-chat-student/peer-chat-student.component.ts b/src/assets/wise5/components/peerChat/peer-chat-student/peer-chat-student.component.ts index b02bab5d04..c8f610ec3c 100644 --- a/src/assets/wise5/components/peerChat/peer-chat-student/peer-chat-student.component.ts +++ b/src/assets/wise5/components/peerChat/peer-chat-student/peer-chat-student.component.ts @@ -20,6 +20,9 @@ import { PeerChatComponent } from '../PeerChatComponent'; import { PeerChatMessage } from '../PeerChatMessage'; import { PeerChatService } from '../peerChatService'; import { PeerGroup } from '../PeerGroup'; +import { Question } from '../peer-chat-question-bank/Question'; +import { QuestionBankService } from '../peer-chat-question-bank/questionBank.service'; +import { getQuestionIdsUsed } from '../peer-chat-question-bank/question-bank-helper'; @Component({ selector: 'peer-chat-student', @@ -37,9 +40,11 @@ export class PeerChatStudentComponent extends ComponentStudent { peerChatWorkgroupIds: number[] = []; peerChatWorkgroupInfos: any = {}; peerGroup: PeerGroup; + question: Question; questionBankContent: QuestionBankContent; + questionIdsUsed: string[] = []; requestTimeout: number = 10000; - response: string; + response: string = ''; constructor( protected annotationService: AnnotationService, @@ -52,6 +57,7 @@ export class PeerChatStudentComponent extends ComponentStudent { private notificationService: NotificationService, private peerChatService: PeerChatService, private peerGroupService: PeerGroupService, + private questionBankService: QuestionBankService, protected studentAssetService: StudentAssetService, protected studentDataService: StudentDataService, private studentWebSocketService: StudentWebSocketService @@ -118,6 +124,7 @@ export class PeerChatStudentComponent extends ComponentStudent { ]).subscribe(([componentStates, annotations]) => { this.setPeerChatMessages(componentStates); this.peerChatService.processIsDeletedAnnotations(annotations, this.peerChatMessages); + this.questionIdsUsed = getQuestionIdsUsed(componentStates, this.myWorkgroupId); }); } }, @@ -176,6 +183,10 @@ export class PeerChatStudentComponent extends ComponentStudent { response: this.response, submitCounter: this.submitCounter }; + if (this.question != null) { + componentState.studentData.questionId = this.question.id; + this.questionBankService.questionUsed(this.question); + } if (this.dynamicPrompt != null) { componentState.studentData.dynamicPrompt = this.dynamicPrompt; } @@ -197,6 +208,8 @@ export class PeerChatStudentComponent extends ComponentStudent { action ); }); + this.response = ''; + this.question = null; return promise; } @@ -270,4 +283,23 @@ export class PeerChatStudentComponent extends ComponentStudent { onDynamicPromptChanged(feedbackRule: FeedbackRule): void { this.dynamicPrompt = feedbackRule; } + + protected useQuestion(question: Question): void { + if ( + this.response === '' || + confirm( + $localize`Are you sure you want to replace the current text in your response input box with this text?` + ) + ) { + this.question = question; + this.response = question.text; + } + } + + protected responseChanged(response: string): void { + this.response = response; + if (response.length < 2) { + this.question = null; + } + } } diff --git a/src/assets/wise5/components/peerChat/peer-chat.module.ts b/src/assets/wise5/components/peerChat/peer-chat.module.ts index c0740bbedb..54e3490a9c 100644 --- a/src/assets/wise5/components/peerChat/peer-chat.module.ts +++ b/src/assets/wise5/components/peerChat/peer-chat.module.ts @@ -6,6 +6,7 @@ import { PeerChatMessagesComponent } from './peer-chat-messages/peer-chat-messag import { PeerChatQuestionBankComponent } from './peer-chat-question-bank/peer-chat-question-bank.component'; import { PeerChatMembersComponent } from './peer-chat-members/peer-chat-members.component'; import { StudentTeacherCommonModule } from '../../../../app/student-teacher-common.module'; +import { QuestionBankService } from './peer-chat-question-bank/questionBank.service'; @NgModule({ declarations: [ @@ -24,6 +25,7 @@ import { StudentTeacherCommonModule } from '../../../../app/student-teacher-comm PeerChatMessageInputComponent, PeerChatMessagesComponent, PeerChatQuestionBankComponent - ] + ], + providers: [QuestionBankService] }) export class PeerChatModule {} diff --git a/src/assets/wise5/components/peerChat/peerChatService.ts b/src/assets/wise5/components/peerChat/peerChatService.ts index 15c6fe7af9..82547b04a7 100644 --- a/src/assets/wise5/components/peerChat/peerChatService.ts +++ b/src/assets/wise5/components/peerChat/peerChatService.ts @@ -1,4 +1,4 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { ConfigService } from '../../services/configService'; diff --git a/src/messages.xlf b/src/messages.xlf index 8670db27dc..d59f9cbd0e 100644 --- a/src/messages.xlf +++ b/src/messages.xlf @@ -1184,7 +1184,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/app/authoring-tool/edit-question-bank-rules/edit-question-bank-rules.component.html - 102 + 114 src/assets/wise5/components/common/feedbackRule/edit-feedback-rules/edit-feedback-rules.component.html @@ -1199,7 +1199,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/app/authoring-tool/edit-question-bank-rules/edit-question-bank-rules.component.html - 113 + 125 src/assets/wise5/components/common/feedbackRule/edit-feedback-rules/edit-feedback-rules.component.html @@ -1214,7 +1214,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/app/authoring-tool/edit-question-bank-rules/edit-question-bank-rules.component.html - 123 + 135 src/assets/wise5/components/common/feedbackRule/edit-feedback-rules/edit-feedback-rules.component.html @@ -1229,7 +1229,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/app/authoring-tool/edit-question-bank-rules/edit-question-bank-rules.component.html - 138 + 150 @@ -1254,7 +1254,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/app/authoring-tool/edit-question-bank/edit-question-bank.component.html - 30 + 52 @@ -1310,35 +1310,35 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.Delete question src/app/authoring-tool/edit-question-bank-rules/edit-question-bank-rules.component.html - 77 + 89 Add new question src/app/authoring-tool/edit-question-bank-rules/edit-question-bank-rules.component.html - 88 + 100 add_circle src/app/authoring-tool/edit-question-bank-rules/edit-question-bank-rules.component.html - 94 + 106 Are you sure you want to delete this question rule? src/app/authoring-tool/edit-question-bank-rules/edit-question-bank-rules.component.ts - 27 + 32 Are you sure you want to delete this question? src/app/authoring-tool/edit-question-bank-rules/edit-question-bank-rules.component.ts - 39 + 48 @@ -1348,11 +1348,36 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.8,10 + + Custom Label + + src/app/authoring-tool/edit-question-bank/edit-question-bank.component.html + 15 + + + + Question Bank + + src/app/authoring-tool/edit-question-bank/edit-question-bank.component.html + 20 + + + src/assets/wise5/components/peerChat/peer-chat-question-bank/peer-chat-question-bank.component.html + 19 + + + + Student can select questions to use in Peer Chat + + src/app/authoring-tool/edit-question-bank/edit-question-bank.component.html + 31,33 + + Max Number of Questions src/app/authoring-tool/edit-question-bank/edit-question-bank.component.html - 15 + 37 @@ -9885,7 +9910,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.. Be careful not to overwrite each other's work! src/assets/wise5/authoringTool/concurrent-authors-message/concurrent-authors-message.component.ts - 36,38 + 37,39 @@ -19713,11 +19738,11 @@ If this problem continues, let your teacher know and move on to the next activit This Peer Chat activity is not yet available. Please check back later or wait for a notification to return. src/assets/wise5/components/peerChat/peer-chat-grading/peer-chat-grading.component.html - 38,41 + 40,43 src/assets/wise5/components/peerChat/peer-chat-show-work/peer-chat-show-work.component.html - 25,28 + 27,30 src/assets/wise5/components/peerChat/peer-chat-student/peer-chat-student.component.html @@ -19735,7 +19760,7 @@ If this problem continues, let your teacher know and move on to the next activit Send src/assets/wise5/components/peerChat/peer-chat-message-input/peer-chat-message-input.component.html - 20,22 + 21,23 @@ -19752,18 +19777,32 @@ If this problem continues, let your teacher know and move on to the next activit 38 - - Question Bank + + Add to chat src/assets/wise5/components/peerChat/peer-chat-question-bank/peer-chat-question-bank.component.html - 4 + 41 + + + + Used in chat + + src/assets/wise5/components/peerChat/peer-chat-question-bank/peer-chat-question-bank.component.html + 50 You have new chat messages src/assets/wise5/components/peerChat/peer-chat-student/peer-chat-student.component.ts - 228 + 241 + + + + Are you sure you want to replace the current text in your response input box with this text? + + src/assets/wise5/components/peerChat/peer-chat-student/peer-chat-student.component.ts + 291