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 @@ -34,6 +34,7 @@ <h3 class="accent-1 mat-subtitle-2 gray-lightest-bg component-header">
}
@if (component.hasResponsesSummary && component.type === 'MultipleChoice') {
<teacher-summary-display
class="summary-display"
[nodeId]="nodeId"
[componentId]="component.id"
[periodId]="periodId"
Expand All @@ -46,6 +47,7 @@ <h3 class="accent-1 mat-subtitle-2 gray-lightest-bg component-header">
}
@if (component.hasScoresSummary && component.hasScoreAnnotation) {
<teacher-summary-display
class="summary-display"
[nodeId]="nodeId"
[componentId]="component.id"
[periodId]="periodId"
Expand All @@ -55,6 +57,18 @@ <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
class="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
Expand Up @@ -38,3 +38,8 @@
width: auto;
}
}

.summary-display {
display: block;
margin: 16px 0;
}
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
@@ -1,4 +1,4 @@
<mat-card appearance="outlined" class="summary-card">
<mat-card appearance="outlined">
<mat-card-content>
@if (hasWarning) {
<p class="warn center">{{ warningMessage }}</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
.summary-card {
margin: 16px 8px 8px;
}

.highcharts-chart {
display: block;
height: 400px;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<ng-template #ideaTemplate let-idea="idea">
<div class="idea">
<b>{{ idea.id }}.</b> {{ idea.text }} (<mat-icon class="mat-18">person</mat-icon
>{{ idea.count }})
</div>
</ng-template>

<mat-card appearance="outlined">
<mat-card-content>
<h2 class="mat-subhead-1" i18n>Student Ideas Detected</h2>
@if (hasWarning) {
<p class="warn center">{{ warningMessage }}</p>
}
@if (doRender) {
<div class="grid md:grid-cols-2 gap-4 mb-4 max-w-4xl">
<div>
<h3 i18n>Most Common:</h3>
<ul id="most-common-ideas">
@for (idea of mostCommonIdeas; track idea.id) {
<li>
<ng-container
[ngTemplateOutlet]="ideaTemplate"
[ngTemplateOutletContext]="{ idea: idea }"
/>
</li>
}
</ul>
</div>
<div>
<h3 i18n>Least Common:</h3>
<ul id="least-common-ideas">
@for (idea of leastCommonIdeas; track idea.id) {
<li>
<ng-container
[ngTemplateOutlet]="ideaTemplate"
[ngTemplateOutletContext]="{ idea: idea }"
/>
</li>
}
</ul>
</div>
</div>
@if (seeAllIdeas) {
<h3 i18n>All Ideas:</h3>
<ul class="md:columns-2 lg:columns-3 mb-2">
@for (idea of allIdeas; track idea.id) {
<li>
<ng-container
[ngTemplateOutlet]="ideaTemplate"
[ngTemplateOutletContext]="{ idea: idea }"
/>
</li>
}
</ul>
<a href="#" (click)="toggleSeeAllIdeas($event)" i18n>Hide all ideas</a>
} @else {
<a href="#" (click)="toggleSeeAllIdeas($event)" i18n>Show all ideas</a>
}
} @else {
<div class="notice" i18n>
Your students' ideas will show up here as they are detected in the dialog.
</div>
}
</mat-card-content>
</mat-card>
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { AnnotationService } from '../../services/annotationService';
import { ComponentFixture } from '@angular/core/testing';
import { ComponentState } from '../../../../app/domain/componentState';
import { ConfigService } from '../../services/configService';
import { CRaterIdea } from '../../components/common/cRater/CRaterIdea';
import { CRaterRubric } from '../../components/common/cRater/CRaterRubric';
import { CRaterService } from '../../services/cRaterService';
import { DialogGuidanceTeacherSummaryDisplayComponent } from './dialog-guidance-teacher-summary-display.component';
import { MockProviders } from 'ng-mocks';
import { Observable, of } from 'rxjs';
import { SummaryService } from '../../components/summary/summaryService';
import { TeacherDataService } from '../../services/teacherDataService';
import { TeacherProjectService } from '../../services/teacherProjectService';
import { TestBed } from '@angular/core/testing';

let component: DialogGuidanceTeacherSummaryDisplayComponent;
let fixture: ComponentFixture<DialogGuidanceTeacherSummaryDisplayComponent>;
describe('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('.notice').textContent).toContain(
"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('h3').textContent).toEqual('Most Common:');
});
});
}

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 > li').length).toEqual(3);
expect(fixture.nativeElement.querySelectorAll('#least-common-ideas > li').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