Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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 @@ -55,6 +55,17 @@ <h3 class="accent-1 mat-subtitle-2 gray-lightest-bg component-header">
[doRender]="true"
/>
}
@if (component.hasResponsesSummary && component.type === 'DialogGuidance') {
<dialog-guidance-teacher-summary-display
[nodeId]="nodeId"
[componentId]="component.id"
[periodId]="periodId"
[studentDataType]="'responses'"
[source]="source"
[chartType]="'column'"
[doRender]="true"
/>
}
</div>
}
</mat-card-content>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
import { Component, Input } from '@angular/core';
import { SummaryService } from '../../../../components/summary/summaryService';
import { AnnotationService } from '../../../../services/annotationService';
import { CommonModule } from '@angular/common';
import { Component, Input } from '@angular/core';
import { ComponentFactory } from '../../../../common/ComponentFactory';
import { ComponentServiceLookupService } from '../../../../services/componentServiceLookupService';
import { ComponentTypeService } from '../../../../services/componentTypeService';
import { TeacherDataService } from '../../../../services/teacherDataService';
import { TeacherProjectService } from '../../../../services/teacherProjectService';
import { ComponentFactory } from '../../../../common/ComponentFactory';
import { DialogGuidanceTeacherSummaryDisplayComponent } from '../../../../directives/teacher-summary-display/dialog-guidance-teacher-summary-display.component';
import { FlexLayoutModule } from '@angular/flex-layout';
import { isMatchingPeriods } from '../../../../common/period/period';
import { Node } from '../../../../common/Node';
import { MatCardModule } from '@angular/material/card';
import { MatIconModule } from '@angular/material/icon';
import { MatDividerModule } from '@angular/material/divider';
import { FlexLayoutModule } from '@angular/flex-layout';
import { MatIconModule } from '@angular/material/icon';
import { Node } from '../../../../common/Node';
import { PreviewComponentComponent } from '../../../../authoringTool/components/preview-component/preview-component.component';
import { SummaryService } from '../../../../components/summary/summaryService';
import { TeacherDataService } from '../../../../services/teacherDataService';
import { TeacherProjectService } from '../../../../services/teacherProjectService';
import { TeacherSummaryDisplayComponent } from '../../../../directives/teacher-summary-display/teacher-summary-display.component';
import { CommonModule } from '@angular/common';

@Component({
imports: [
CommonModule,
MatCardModule,
MatIconModule,
MatDividerModule,
FlexLayoutModule,
PreviewComponentComponent,
TeacherSummaryDisplayComponent
],
selector: 'node-info',
styleUrl: 'node-info.component.scss',
templateUrl: 'node-info.component.html'
imports: [
DialogGuidanceTeacherSummaryDisplayComponent,
CommonModule,
MatCardModule,
MatIconModule,
MatDividerModule,
FlexLayoutModule,
PreviewComponentComponent,
TeacherSummaryDisplayComponent
],
selector: 'node-info',
styleUrl: 'node-info.component.scss',
templateUrl: 'node-info.component.html'
})
export class NodeInfoComponent {
protected node: Node;
Expand Down
4 changes: 4 additions & 0 deletions src/assets/wise5/components/common/cRater/CRaterRubric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ export class CRaterRubric {
getIdea(ideaId: string): CRaterIdea {
return this.ideas.find((idea) => idea.name === ideaId);
}

getIdeas(): CRaterIdea[] {
return this.ideas;
}
}

export function getUniqueIdeas(responses: any[], rubric: CRaterRubric): CRaterIdea[] {
Expand Down
4 changes: 2 additions & 2 deletions src/assets/wise5/components/summary/summaryService.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
'use strict';

import { ComponentService } from '../componentService';
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

@Injectable()
Expand All @@ -26,7 +26,7 @@ export class SummaryService extends ComponentService {
'OpenResponse',
'Table'
];
this.componentsWithResponsesSummary = ['MultipleChoice', 'Table'];
this.componentsWithResponsesSummary = ['DialogGuidance', 'MultipleChoice', 'Table'];
}

getComponentTypeLabel(): string {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<mat-card appearance="outlined" class="summary-card">
<mat-card-content>
@if (hasWarning) {
<p class="warn center">{{ warningMessage }}</p>
}
@if (doRender) {
<div class="wrapper">
<div class="idea-group" id="most-common-ideas">
<h2 i18n>Most Common Ideas Detected:</h2>
@for (idea of mostCommonIdeas; track idea.id) {
<h3>{{ idea.text }} (<mat-icon>person</mat-icon>{{ idea.count }})</h3>
}
</div>
<div class="idea-group" id="least-common-ideas">
<h2 i18n>Least Common Ideas Detected:</h2>
@for (idea of leastCommonIdeas; track idea.id) {
<h3>{{ idea.text }} (<mat-icon>person</mat-icon>{{ idea.count }})</h3>
}
</div>
</div>
<div class="idea-group" id="all-ideas">
@if (seeAllIdeas) {
<h2 i18n>All Ideas:</h2>
@for (idea of allIdeas; track idea.id) {
<h3>{{ idea.text }} (<mat-icon>person</mat-icon>{{ idea.count }})</h3>
}
<a (mouseup)="toggleSeeAllIdeas()" i18n>Hide all ideas</a>
} @else {
<a (mouseup)="toggleSeeAllIdeas()" i18n>Show all ideas</a>
}
</div>
} @else {
<h2 i18n>Your students' ideas will show up here as they are detected in the dialog.</h2>
}
</mat-card-content>
</mat-card>
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import { ComponentFixture } from '@angular/core/testing';
import { DialogGuidanceTeacherSummaryDisplayComponent } from './dialog-guidance-teacher-summary-display.component';
import { TestBed } from '@angular/core/testing';
import { MockProviders } from 'ng-mocks';
import { CRaterService } from '../../services/cRaterService';
import { CRaterRubric } from '../../components/common/cRater/CRaterRubric';
import { CRaterIdea } from '../../components/common/cRater/CRaterIdea';
import { SummaryService } from '../../components/summary/summaryService';
import { Observable, of } from 'rxjs';
import { ComponentState } from '../../../../app/domain/componentState';
import { AnnotationService } from '../../services/annotationService';
import { ConfigService } from '../../services/configService';
import { TeacherDataService } from '../../services/teacherDataService';
import { TeacherProjectService } from '../../services/teacherProjectService';
import { Config } from '../../../../app/domain/config';

let component: DialogGuidanceTeacherSummaryDisplayComponent;
let fixture: ComponentFixture<DialogGuidanceTeacherSummaryDisplayComponent>;
fdescribe('DialogGuidanceTeacherSummaryDisplayComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [DialogGuidanceTeacherSummaryDisplayComponent],
providers: [
MockProviders(
AnnotationService,
ConfigService,
CRaterService,
TeacherDataService,
TeacherProjectService,
SummaryService
)
]
}).compileComponents();

fixture = TestBed.createComponent(DialogGuidanceTeacherSummaryDisplayComponent);
component = fixture.componentInstance;
component.doRender = true;
// Set up component?
});
beforeEach(() => {
spyOn(TestBed.inject(ConfigService), 'isPreview').and.returnValue(false);
spyOn(TestBed.inject(ConfigService), 'isAuthoring').and.returnValue(false);
spyOn(TestBed.inject(ConfigService), 'isStudentRun').and.returnValue(false);
spyOn(TestBed.inject(ConfigService), 'getNumberOfWorkgroupsInPeriod').and.returnValue(1);
});
ngOnInit();
});

function ngOnInit() {
describe('ngOnChanges()', () => {
ngInit_NoIdeasDetected_ShowMessage();
ngInit_IdeasDetected_ShowSummary();
ngInit_ManyIdeasDetected_ShowTopAndBottomThree();
});
}

function ngInit_NoIdeasDetected_ShowMessage() {
describe('no ideas detected', () => {
beforeEach(() => {
spyOn(TestBed.inject(CRaterService), 'getCRaterRubric').and.returnValue(
generateMockRubric(3, 0)
);
spyOn(TestBed.inject(SummaryService), 'getLatestClassmateStudentWork').and.returnValue(
generateMockStudentWork(0)
);
});
it('shows message to teacher', () => {
component.ngOnInit();
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('h2').textContent).toEqual(
"Your students' ideas will show up here as they are detected in the dialog."
);
});
});
}

function ngInit_IdeasDetected_ShowSummary() {
describe('ideas detected', () => {
beforeEach(() => {
spyOn(TestBed.inject(CRaterService), 'getCRaterRubric').and.returnValue(
generateMockRubric(3, 1)
);
spyOn(TestBed.inject(SummaryService), 'getLatestClassmateStudentWork').and.returnValue(
generateMockStudentWork(1)
);
});
it('shows summary display', () => {
component.ngOnInit();
fixture.detectChanges();

expect(fixture.nativeElement.querySelector('h2').textContent).toEqual(
'Most Common Ideas Detected:'
);
});
});
}

function ngInit_ManyIdeasDetected_ShowTopAndBottomThree() {
describe('more than 3 ideas detected', () => {
beforeEach(() => {
spyOn(TestBed.inject(CRaterService), 'getCRaterRubric').and.returnValue(
generateMockRubric(4, 4)
);
spyOn(TestBed.inject(SummaryService), 'getLatestClassmateStudentWork').and.returnValue(
generateMockStudentWork(4)
);
});
it('shows only top and bottom three ideas', () => {
component.ngOnInit();
fixture.detectChanges();
expect(fixture.nativeElement.querySelectorAll('#most-common-ideas > h3').length).toEqual(3);
expect(fixture.nativeElement.querySelectorAll('#least-common-ideas > h3').length).toEqual(3);
});
});
}

function generateMockRubric(numIdeas: number, numDetected: number): CRaterRubric {
const ideas = [];
for (let i = 0; i < numIdeas; i++) {
const idea = new CRaterIdea('idea ' + (i + 1), numDetected > 0 ? true : false);
ideas.push(idea);
numDetected--;
}
return new CRaterRubric({ ideas: ideas });
}

function generateMockStudentWork(numIdeasDetected: number): Observable<ComponentState[]> {
const ideas = [];
for (let i = 0; i < numIdeasDetected; i++) {
ideas.push({ name: 'idea ' + (i + 1), detected: true });
}
return of([
new ComponentState({
workgroupId: 1,
studentData: { responses: [{ ideas: ideas }] }
})
]);
}
Loading