Skip to content

Commit

Permalink
feat(Show Group Work): Show component work in Grading Tool (#1078)
Browse files Browse the repository at this point in the history
  • Loading branch information
geoffreykwan authored Mar 5, 2023
1 parent e9ef844 commit 1b6e1bd
Show file tree
Hide file tree
Showing 18 changed files with 486 additions and 375 deletions.
3 changes: 3 additions & 0 deletions src/app/teacher/component-grading.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { MatchGradingModule } from '../../assets/wise5/components/match/match-gr
import { MultipleChoiceGradingModule } from '../../assets/wise5/components/multipleChoice/multiple-choice-grading/multiple-choice-grading.module';
import { OpenResponseGradingModule } from '../../assets/wise5/components/openResponse/open-response-grading/open-response-grading.module';
import { PeerChatGradingModule } from '../../assets/wise5/components/peerChat/peer-chat-grading/peer-chat-grading.module';
import { ShowGroupWorkGradingModule } from '../../assets/wise5/components/showGroupWork/show-group-work-grading/show-group-work-grading.module';
import { TableGradingModule } from '../../assets/wise5/components/table/table-grading/table-grading.module';

@NgModule({
Expand All @@ -31,6 +32,7 @@ import { TableGradingModule } from '../../assets/wise5/components/table/table-gr
MultipleChoiceGradingModule,
OpenResponseGradingModule,
PeerChatGradingModule,
ShowGroupWorkGradingModule,
TableGradingModule
],
exports: [
Expand All @@ -48,6 +50,7 @@ import { TableGradingModule } from '../../assets/wise5/components/table/table-gr
MultipleChoiceGradingModule,
OpenResponseGradingModule,
PeerChatGradingModule,
ShowGroupWorkGradingModule,
TableGradingModule
]
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,15 @@
>
</table-grading>
</ng-container>
<show-group-work-grading
*ngIf="component.type === 'ShowGroupWork'"
[nodeId]="nodeId"
[componentId]="component.id"
[workgroupId]="workgroupId"
></show-group-work-grading>
<span fxFlex></span>
<div
*ngIf="componentStates.length === 0"
*ngIf="componentStates.length === 0 && component.type !== 'ShowGroupWork'"
class="component__actions__info component--grading__actions__info md-caption"
i18n
>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<div *ngIf="isPeerGroupRetrieved">
<div *ngIf="peerGroup == null" class="notice mat-body-2" i18n>
You have not been paired with a classmate yet. Please check back later.
</div>
<div [fxLayout]="flexLayout" *ngIf="peerGroup != null">
<div
*ngFor="let member of peerGroup.members"
fxFlex="100"
[fxFlex.gt-sm]="widthMd"
[fxFlex.gt-md]="widthLg"
fxLayout="column"
>
<mat-card class="mat-elevation-z0 notice-bg-bg" fxFlex="100" fxLayout="column">
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<mat-icon class="mat-30" [ngStyle]="{ color: workgroupInfos[member.id].avatarColor }">
account_circle
</mat-icon>
<span class="mat-body-2">{{ workgroupInfos[member.id].displayNames }}</span>
</div>
<mat-card-content class="app-bg-bg" fxFlex="100">
<span class="text-secondary" *ngIf="workgroupIdToWork.get(member.id) == null" i18n>
(Waiting for response...)
</span>
<show-work-student
*ngIf="workgroupIdToWork.get(member.id) != null"
[studentWork]="workgroupIdToWork.get(member.id)"
[componentId]="componentContent.showWorkComponentId"
[nodeId]="componentContent.showWorkNodeId"
>
</show-work-student>
</mat-card-content>
</mat-card>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@import 'style/abstracts/variables';

.mat-card {
margin: 4px;
padding: 8px;
}

.mat-card-content {
margin-top: 8px;
padding: 8px;
border-radius: $button-border-radius;
overflow: auto;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatDialog } from '@angular/material/dialog';
import { of } from 'rxjs';
import { PeerGrouping } from '../../../../../app/domain/peerGrouping';
import { StudentTeacherCommonServicesModule } from '../../../../../app/student-teacher-common-services.module';
import { AnnotationService } from '../../../services/annotationService';
import { ConfigService } from '../../../services/configService';
import { NodeService } from '../../../services/nodeService';
import { NotebookService } from '../../../services/notebookService';
import { PeerGroupService } from '../../../services/peerGroupService';
import { ProjectService } from '../../../services/projectService';
import { PeerGroup } from '../../peerChat/PeerGroup';
import { PeerGroupMember } from '../../peerChat/PeerGroupMember';
import { ShowGroupWorkDisplayComponent } from './show-group-work-display.component';

class MockService {}

class MockNotebookService {
notebookUpdated$: any = of({});

isNotebookEnabled() {
return false;
}
}

class MockConfigService {
getPeriodId() {
return periodId;
}
getRunId() {
return 1;
}
isAuthoring() {
return false;
}
isPreview() {
return false;
}
isSignedInUserATeacher() {
return false;
}
getWorkgroupId() {
return workgroupId;
}
getAvatarColorForWorkgroupId(workgroupId: any) {
return '#000000';
}
getUsernamesStringByWorkgroupId(workgroupId: number) {
return `Student ${workgroupId}`;
}
}

let component: ShowGroupWorkDisplayComponent;
let componentState1;
let componentState2;
let componentState3;
let fixture: ComponentFixture<ShowGroupWorkDisplayComponent>;
const periodId = 100;
const peerGroup = new PeerGroup(
1,
[new PeerGroupMember(1, 1), new PeerGroupMember(2, 1), new PeerGroupMember(3, 1)],
new PeerGrouping()
);
let studentWork;
const workgroupId: number = 1000;

describe('ShowGroupWorkDisplayComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [HttpClientTestingModule, StudentTeacherCommonServicesModule],
declarations: [ShowGroupWorkDisplayComponent],
providers: [
AnnotationService,
{ provide: ConfigService, useClass: MockConfigService },
{ provide: MatDialog, useClass: MockService },
{ provide: NodeService, useClass: MockService },
{ provide: NotebookService, useClass: MockNotebookService },
{ provide: PeerGroupService, useClass: PeerGroupService }
],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();

fixture = TestBed.createComponent(ShowGroupWorkDisplayComponent);
componentState1 = createComponentState(1);
componentState2 = createComponentState(2);
studentWork = [componentState1, componentState2];
component = fixture.componentInstance;
component.componentContent = {
id: 'abc',
prompt: '',
showSaveButton: true,
showSubmitButton: true,
isShowMyWork: true,
layout: 'row',
type: 'ShowGroupWork'
};
spyOn(TestBed.inject(ProjectService), 'injectAssetPaths').and.returnValue({
type: 'OpenResponse'
});
component.peerGroup = peerGroup;
component.setWorkgroupInfos();
fixture.detectChanges();
});

setStudentWorkFromGroupMembers();
setLayout();
setWidths();
showGroupWorkInPreview();
});

function createComponentState(workgroupId: number): any {
return {
workgroupId: workgroupId
};
}

function setStudentWorkFromGroupMembers() {
describe('setStudentWorkFromGroupMembers', () => {
it('should add entry to workgroupIdToWork for each student work', () => {
component.setStudentWorkFromGroupMembers(studentWork);
expect(component.workgroupIdToWork.size).toEqual(2);
});
});
}

function setLayout() {
describe('setLayout', () => {
it('should set row layout for narrow component type', () => {
component.setStudentWorkFromGroupMembers(studentWork);
component.setLayout();
expect(component.flexLayout).toBe('row wrap');
});

it('should set column layout', () => {
component.componentContent.layout = 'column';
component.setStudentWorkFromGroupMembers(studentWork);
component.setLayout();
expect(component.flexLayout).toBe('column');
});
});
}

function setWidths() {
describe('setWidths()', () => {
it('should set widths for narrow component type including my work', () => {
component.setStudentWorkFromGroupMembers(studentWork);
component.setWidths();
expect(component.widthMd).toEqual(50);
expect(component.widthLg).toEqual(33.33);
});

it('should set widths for narrow component type not including my work', () => {
component.componentContent.isShowMyWork = false;
spyOn(TestBed.inject(ConfigService), 'getWorkgroupId').and.returnValue(1);
component.setStudentWorkFromGroupMembers(studentWork);
component.setWidths();
expect(component.widthMd).toEqual(50);
expect(component.widthLg).toEqual(33.33);
});

it('should set widths for narrow component type and more than 2 group members', () => {
componentState3 = createComponentState(3);
studentWork = [componentState1, componentState2, componentState3];
component.setStudentWorkFromGroupMembers(studentWork);
component.setWidths();
expect(component.widthMd).toEqual(50);
expect(component.widthLg).toEqual(33.33);
});
});
}

function showGroupWorkInPreview() {
describe('ngOnInit()', () => {
it('should show group work in preview', () => {
spyOn(TestBed.inject(ConfigService), 'isPreview').and.returnValue(true);
spyOn(TestBed.inject(ConfigService), 'getWorkgroupId').and.returnValue(workgroupId);
spyOn(TestBed.inject(ConfigService), 'getPeriodId').and.returnValue(periodId);
spyOn(TestBed.inject(PeerGroupService), 'retrievePeerGroup').and.returnValue(of(peerGroup));
const latestComponentState = {
id: 100,
studentData: {
response: 'Hello'
},
workgroupId: workgroupId
};
spyOn(TestBed.inject(PeerGroupService), 'retrieveStudentWork').and.returnValue(
of([latestComponentState])
);
component.ngOnInit();
expect(component.workgroupIdToWork.get(workgroupId)).toEqual(latestComponentState);
});
});
}
Loading

0 comments on commit 1b6e1bd

Please sign in to comment.