Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { StudentAssetsDialogModule } from '../../vle/studentAsset/student-assets
import { AnimationStudentModule } from '../animation/animation-student/animation-student.module';
import { AudioOscillatorStudentModule } from '../audioOscillator/audio-oscillator-student/audio-oscillator.module';
import { ConceptMapStudentModule } from '../conceptMap/concept-map-student/concept-map-student.module';
import { DialogGuidanceStudentModule } from '../dialogGuidance/dialogGuidanceStudentModule';
import { DiscussionStudentModule } from '../discussion/discussion-student/discussion-student.module';
import { DrawStudentModule } from '../draw/draw-student/draw-student-module';
import { EmbeddedStudentModule } from '../embedded/embedded-student/embedded-student.module';
Expand All @@ -26,6 +25,7 @@ import { ComponentComponent } from './component.component';
import { AiChatStudentModule } from '../aiChat/ai-chat-student/ai-chat-student.module';
import { HelpIconComponent } from '../../themes/default/themeComponents/helpIcon/help-icon.component';
import { MultipleChoiceStudentComponent } from '../multipleChoice/multiple-choice-student/multiple-choice-student.component';
import { DialogGuidanceStudentComponent } from '../dialogGuidance/dialog-guidance-student/dialog-guidance-student.component';

@NgModule({
imports: [
Expand All @@ -35,7 +35,7 @@ import { MultipleChoiceStudentComponent } from '../multipleChoice/multiple-choic
CommonModule,
ComponentComponent,
ConceptMapStudentModule,
DialogGuidanceStudentModule,
DialogGuidanceStudentComponent,
DiscussionStudentModule,
DrawStudentModule,
EmbeddedStudentModule,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
<computer-avatar-selector
*ngIf="computerAvatarSelectorVisible"
[computerAvatarSettings]="componentContent.computerAvatarSettings"
(chooseAvatarEvent)="selectComputerAvatar($event)"
/>
<mat-card appearance="outlined" *ngIf="!computerAvatarSelectorVisible" class="mat-elevation-z2">
<component-header [component]="component"></component-header>
<dialog-responses
[responses]="responses"
[isWaitingForComputerResponse]="isWaitingForComputerResponse"
[computerAvatar]="computerAvatar"
>
</dialog-responses>
<chat-input
*ngIf="studentCanRespond"
[submitDisabled]="isWaitingForComputerResponse"
(submitEvent)="submitStudentResponse($event)"
></chat-input>
</mat-card>
@if (computerAvatarSelectorVisible) {
<computer-avatar-selector
[computerAvatarSettings]="componentContent.computerAvatarSettings"
(chooseAvatarEvent)="selectComputerAvatar($event)"
/>
} @else {
<mat-card appearance="outlined" class="mat-elevation-z2">
<component-header [component]="component" />
<dialog-responses
[responses]="responses"
[isWaitingForComputerResponse]="isWaitingForComputerResponse"
[computerAvatar]="computerAvatar"
/>
@if (studentCanRespond) {
<chat-input
[submitDisabled]="isWaitingForComputerResponse"
(submitEvent)="submitStudentResponse($event)"
/>
}
</mat-card>
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsModule } from '@angular/forms';
import { MatCardModule } from '@angular/material/card';
import { MatDialogModule } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { StudentTeacherCommonServicesModule } from '../../../../../app/student-teacher-common-services.module';
import { ComputerAvatar } from '../../../common/computer-avatar/ComputerAvatar';
import { ComponentHeaderComponent } from '../../../directives/component-header/component-header.component';
import { ComputerAvatarService } from '../../../services/computerAvatarService';
import { DialogGuidanceFeedbackService } from '../../../services/dialogGuidanceFeedbackService';
import { ProjectService } from '../../../services/projectService';
Expand All @@ -19,57 +11,24 @@ import { ComputerDialogResponseMultipleScores } from '../ComputerDialogResponseM
import { ComputerDialogResponseSingleScore } from '../ComputerDialogResponseSingleScore';
import { CRaterResponse } from '../../common/cRater/CRaterResponse';
import { CRaterScore } from '../../common/cRater/CRaterScore';
import { DialogResponsesComponent } from '../dialog-responses/dialog-responses.component';
import { DialogGuidanceService } from '../dialogGuidanceService';
import { DialogGuidanceStudentComponent } from './dialog-guidance-student.component';
import { DialogGuidanceComponent } from '../DialogGuidanceComponent';
import { RawCRaterResponse } from '../../common/cRater/RawCRaterResponse';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { ChatInputComponent } from '../../../common/chat-input/chat-input.component';
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';

let component: DialogGuidanceStudentComponent;
let fixture: ComponentFixture<DialogGuidanceStudentComponent>;
const robotAvatar = new ComputerAvatar('robot', 'Robot', 'robot.png');

function initializeComponent(isComputerAvatarEnabled: boolean): void {
fixture = TestBed.createComponent(DialogGuidanceStudentComponent);
component = fixture.componentInstance;
component.component = createDialogGuidanceComponent(isComputerAvatarEnabled);
spyOn(component, 'subscribeToSubscriptions').and.callFake(() => {});
spyOn(component, 'isNotebookEnabled').and.returnValue(false);
fixture.detectChanges();
}

function createDialogGuidanceComponent(isComputerAvatarEnabled: boolean): DialogGuidanceComponent {
const componentContent = TestBed.inject(DialogGuidanceService).createComponent();
componentContent.isComputerAvatarEnabled = isComputerAvatarEnabled;
return new DialogGuidanceComponent(componentContent, null);
}

describe('DialogGuidanceStudentComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [DialogGuidanceStudentComponent],
schemas: [NO_ERRORS_SCHEMA],
imports: [
BrowserAnimationsModule,
ChatInputComponent,
ComponentHeaderComponent,
DialogResponsesComponent,
FormsModule,
MatCardModule,
MatDialogModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
DialogGuidanceStudentComponent,
StudentTeacherCommonServicesModule
],
providers: [
DialogGuidanceFeedbackService,
provideHttpClient(withInterceptorsFromDi()),
provideHttpClientTesting()
]
providers: [DialogGuidanceFeedbackService, provideHttpClient(withInterceptorsFromDi())]
}).compileComponents();
});

Expand Down Expand Up @@ -101,19 +60,19 @@ describe('DialogGuidanceStudentComponent', () => {
);
component.setIsSubmitDirty(true);
const response = createDummyScoringResponse();
expect(component.responses.length).toEqual(0);
expect(component['responses'].length).toEqual(0);
component.cRaterSuccessResponse(response);
expect(broadcastComponentSubmitTriggeredSpy).toHaveBeenCalled();
expect(component.responses.length).toEqual(1);
expect(component['responses'].length).toEqual(1);
});

it('should disable submit button after using all submits', () => {
component.componentContent.maxSubmitCount = 2;
expect(component.studentCanRespond).toEqual(true);
expect(component['studentCanRespond']).toEqual(true);
simulateSubmit(component);
expect(component.studentCanRespond).toEqual(true);
expect(component['studentCanRespond']).toEqual(true);
simulateSubmit(component);
expect(component.studentCanRespond).toEqual(false);
expect(component['studentCanRespond']).toEqual(false);
});

it('should handle crater error response', () => {
Expand All @@ -129,7 +88,7 @@ describe('DialogGuidanceStudentComponent', () => {
it('should initialize computer avatar to default computer avatar', () => {
initializeComponent(false);
expectComputerAvatarSelectorNotToBeShown(component);
expect(component.computerAvatar).not.toBeNull();
expect(component['computerAvatar']).not.toBeNull();
});

it(`should initialize computer avatar when the student has not previously chosen a computer
Expand Down Expand Up @@ -183,7 +142,7 @@ describe('DialogGuidanceStudentComponent', () => {

it('should select computer avatar', () => {
component.selectComputerAvatar(robotAvatar);
expect(component.computerAvatar).toEqual(robotAvatar);
expect(component['computerAvatar']).toEqual(robotAvatar);
expectComputerAvatarSelectorNotToBeShown(component);
});

Expand All @@ -196,19 +155,34 @@ describe('DialogGuidanceStudentComponent', () => {
const defaultComputerAvatar = computerAvatarService.getDefaultAvatar();
spyOn(computerAvatarService, 'getAvatar').and.returnValue(defaultComputerAvatar);
component.initializeComputerAvatar();
expect(component.computerAvatar).toEqual(defaultComputerAvatar);
expect(component['computerAvatar']).toEqual(defaultComputerAvatar);
});

it('should select computer avatar when there is a computer avatar initial response', () => {
const text = 'Hi there, who lives in a pineapple under sea?';
component.componentContent.computerAvatarSettings.initialResponse = text;
expect(component.responses.length).toEqual(0);
expect(component['responses'].length).toEqual(0);
component.selectComputerAvatar(robotAvatar);
expect(component.responses.length).toEqual(1);
expect(component.responses[0].text).toEqual(text);
expect(component['responses'].length).toEqual(1);
expect(component['responses'][0].text).toEqual(text);
});
});

function initializeComponent(isComputerAvatarEnabled: boolean): void {
fixture = TestBed.createComponent(DialogGuidanceStudentComponent);
component = fixture.componentInstance;
component.component = createDialogGuidanceComponent(isComputerAvatarEnabled);
spyOn(component, 'subscribeToSubscriptions').and.callFake(() => {});
spyOn(component, 'isNotebookEnabled').and.returnValue(false);
fixture.detectChanges();
}

function createDialogGuidanceComponent(isComputerAvatarEnabled: boolean): DialogGuidanceComponent {
const componentContent = TestBed.inject(DialogGuidanceService).createComponent();
componentContent.isComputerAvatarEnabled = isComputerAvatarEnabled;
return new DialogGuidanceComponent(componentContent, null);
}

function simulateSubmit(component: DialogGuidanceStudentComponent): void {
const response = createDummyScoringResponse();
component.setIsSubmitDirty(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,36 @@ import { RawCRaterResponse } from '../../common/cRater/RawCRaterResponse';
import { ConstraintService } from '../../../services/constraintService';
import { applyMixins } from '../../../common/apply-mixins';
import { ComputerAvatarInitializer } from '../../../common/computer-avatar/computer-avatar-initializer';
import { ComputerAvatarSelectorComponent } from '../../../vle/computer-avatar-selector/computer-avatar-selector.component';
import { MatCardModule } from '@angular/material/card';
import { ComponentHeaderComponent } from '../../../directives/component-header/component-header.component';
import { DialogResponsesComponent } from '../dialog-responses/dialog-responses.component';
import { ChatInputComponent } from '../../../common/chat-input/chat-input.component';
import { CommonModule } from '@angular/common';

@Component({
selector: 'dialog-guidance-student',
templateUrl: './dialog-guidance-student.component.html',
styleUrls: ['./dialog-guidance-student.component.scss'],
standalone: false
imports: [
ChatInputComponent,
CommonModule,
ComponentHeaderComponent,
ComputerAvatarSelectorComponent,
DialogResponsesComponent,
MatCardModule
],
providers: [DialogGuidanceFeedbackService],
selector: 'dialog-guidance-student',
styleUrl: './dialog-guidance-student.component.scss',
templateUrl: './dialog-guidance-student.component.html'
})
export class DialogGuidanceStudentComponent extends ComponentStudent {
component: DialogGuidanceComponent;
computerAvatar: ComputerAvatar;
protected computerAvatar: ComputerAvatar;
protected computerAvatarSelectorVisible: boolean = false;
cRaterTimeout: number = 40000;
feedbackRuleEvaluator: FeedbackRuleEvaluator<CRaterResponse[]>;
isWaitingForComputerResponse: boolean = false;
responses: DialogResponse[] = [];
studentCanRespond: boolean = true;
private cRaterTimeout: number = 40000;
private feedbackRuleEvaluator: FeedbackRuleEvaluator<CRaterResponse[]>;
protected isWaitingForComputerResponse: boolean = false;
protected responses: DialogResponse[] = [];
protected studentCanRespond: boolean = true;
workgroupId: number;

constructor(
Expand Down Expand Up @@ -126,14 +140,14 @@ export class DialogGuidanceStudentComponent extends ComponentStudent {
this.cRaterService
.makeCRaterScoringRequest(this.component.getItemId(), new Date().getTime(), studentResponse)
.pipe(timeout(this.cRaterTimeout))
.subscribe(
(response: any) => {
.subscribe({
next: (response: any) => {
this.cRaterSuccessResponse(response.responses);
},
() => {
error: () => {
this.cRaterErrorResponse();
}
);
});
}

private showWaitingForComputerResponse(): void {
Expand Down

This file was deleted.

Loading