Skip to content

Commit 7b87b7a

Browse files
committed
Extract grading view from the Label component. #2943
1 parent f97e0e1 commit 7b87b7a

13 files changed

Lines changed: 923 additions & 620 deletions

File tree

src/main/webapp/site/src/app/services/labelService.spec.ts

Lines changed: 186 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,29 @@ let service: LabelService;
1515
let utilService: UtilService;
1616
let label1: any;
1717
let label2: any;
18+
let label1Text: any = 'Label 1';
19+
let label2Text: any = 'Label 2';
20+
let label1PointX: number = 1;
21+
let label1PointY: number = 11;
22+
let label1TextX: number = 111;
23+
let label1TextY: number = 1111;
24+
let label2PointX: number = 2;
25+
let label2PointY: number = 22;
26+
let label2TextX: number = 222;
27+
let label2TextY: number = 2222;
28+
let color1: string = 'blue';
29+
let color2: string = 'red';
30+
let width: number = 400;
31+
let height: number = 400;
32+
let pointSize: number = 5;
33+
let fontSize: number = 12;
34+
let labelWidth: number = 20;
35+
let enableCircles: boolean = true;
36+
let studentDataVersion: number = 2;
37+
let canEditBoolean: boolean = true;
38+
let canDeleteBoolean: boolean = true;
1839

19-
describe('LabelServiceService', () => {
40+
describe('LabelService', () => {
2041
beforeEach(() => {
2142
TestBed.configureTestingModule({
2243
imports: [HttpClientTestingModule, UpgradeModule],
@@ -34,8 +55,8 @@ describe('LabelServiceService', () => {
3455
});
3556
service = TestBed.get(LabelService);
3657
utilService = TestBed.get(UtilService);
37-
label1 = createLabel('Label 1', 1, 11, 111, 1111, 'blue');
38-
label2 = createLabel('Label 2', 2, 22, 222, 2222, 'red');
58+
label1 = createLabel(label1Text, label1PointX, label1PointY, label1TextX, label1TextY, color1);
59+
label2 = createLabel(label2Text, label2PointX, label2PointY, label2TextX, label2TextY, color2);
3960
});
4061
createComponent();
4162
isCompleted();
@@ -48,6 +69,11 @@ describe('LabelServiceService', () => {
4869
labelsAreTheSame();
4970
getTSpans();
5071
getSVGTextElementString();
72+
initializeCanvas();
73+
addLabelsToCanvas();
74+
addLabelToCanvas();
75+
createLabelServiceFunction();
76+
makeSureValueIsWithinLimit();
5177
});
5278

5379
function createComponentState(labels: any[], isSubmit: boolean = false) {
@@ -68,23 +94,54 @@ function createObjectWithLabels(labels: any[]) {
6894
}
6995

7096
function createLabel(
71-
text: string,
72-
pointX: number,
73-
pointY: number,
74-
textX: number,
75-
textY: number,
76-
color: string
77-
) {
97+
text: string = '',
98+
pointX: number = 100,
99+
pointY: number = 100,
100+
textX: number = 200,
101+
textY: number = 200,
102+
color: string = color1,
103+
canEdit: boolean = true,
104+
canDelete: boolean = true
105+
): any {
78106
return {
79107
text: text,
108+
color: color,
80109
pointX: pointX,
81110
pointY: pointY,
82111
textX: textX,
83112
textY: textY,
84-
color: color
113+
canEdit: canEdit,
114+
canDelete: canDelete
85115
};
86116
}
87117

118+
function createFabricLabel() {
119+
const pointX: number = 100;
120+
const pointY: number = 100;
121+
const textX: number = 200;
122+
const textY: number = 200;
123+
const textString: string = label1Text;
124+
const color: string = color1;
125+
const canEdit: boolean = true;
126+
const canDelete: boolean = true;
127+
return service.createLabel(
128+
pointX,
129+
pointY,
130+
textX,
131+
textY,
132+
textString,
133+
color,
134+
canEdit,
135+
canDelete,
136+
width,
137+
height,
138+
pointSize,
139+
fontSize,
140+
labelWidth,
141+
studentDataVersion
142+
);
143+
}
144+
88145
function createComponent() {
89146
it('should create a label component', () => {
90147
const component: any = service.createComponent();
@@ -127,7 +184,8 @@ function isCompleted() {
127184
componentStates.push(createComponentState([label1]));
128185
expectIsCompleted(component, componentStates, node, true);
129186
});
130-
it(`should check if is completed when submit is required and there are labels but not submitted`, () => {
187+
it(`should check if is completed when submit is required and there are labels but not
188+
submitted`, () => {
131189
node.showSubmitButton = true;
132190
componentStates.push(createComponentState([label1]));
133191
expectIsCompleted(component, componentStates, node, false);
@@ -144,14 +202,17 @@ function componentStateHasSubmitWithLabel() {
144202
beforeEach(() => {
145203
componentState = createComponentState([]);
146204
});
147-
it('should check if a component state has a submit with label when it does not have any labels', () => {
205+
it(`should check if a component state has a submit with label when it does not have any
206+
labels`, () => {
148207
expect(service.componentStateHasSubmitWithLabel(componentState)).toEqual(false);
149208
});
150-
it('should check if a component state has a submit with label when it has a label but no submit', () => {
209+
it(`should check if a component state has a submit with label when it has a label but no
210+
submit`, () => {
151211
componentState.studentData.labels.push(label1);
152212
expect(service.componentStateHasSubmitWithLabel(componentState)).toEqual(false);
153213
});
154-
it('should check if a component state has a submit with label when it has a label and submit', () => {
214+
it(`should check if a component state has a submit with label when it has a label and
215+
submit`, () => {
155216
componentState.studentData.labels.push(label1);
156217
componentState.isSubmit = true;
157218
expect(service.componentStateHasSubmitWithLabel(componentState)).toEqual(true);
@@ -292,11 +353,20 @@ function labelsAreTheSame() {
292353
it('should check if labels are the same when one is null and one is not null', () => {
293354
expectLabelsAreTheSame({}, null, false);
294355
});
295-
it(`should check if labels are the same when both are not null and do not have the same values`, () => {
356+
it(`should check if labels are the same when both are not null and do not have the same
357+
values`, () => {
296358
expectLabelsAreTheSame(label1, label2, false);
297359
});
298-
it(`should check if labels are the same when both are not null and do have the same values`, () => {
299-
const label3 = createLabel('Label 1', 1, 11, 111, 1111, 'blue');
360+
it(`should check if labels are the same when both are not null and do have the same
361+
values`, () => {
362+
const label3 = createLabel(
363+
label1Text,
364+
label1PointX,
365+
label1PointY,
366+
label1TextX,
367+
label1TextY,
368+
color1
369+
);
300370
expectLabelsAreTheSame(label1, label3, true);
301371
});
302372
}
@@ -326,3 +396,101 @@ function getSVGTextElementString() {
326396
expect(textElementString).toEqual(expectedResult);
327397
});
328398
}
399+
400+
function createCanvas() {
401+
return service.initializeCanvas('label-canvas', 400, 300, false);
402+
}
403+
404+
function initializeCanvas() {
405+
it('should initialize the canvas', () => {
406+
const canvas: any = createCanvas();
407+
expect(canvas).not.toBeNull();
408+
});
409+
}
410+
411+
function addLabelsToCanvas() {
412+
it('should add labels to canvas', () => {
413+
const canvas: any = createCanvas();
414+
const labels: any[] = [label1, label2];
415+
const fabricLabels: any = service.addLabelsToCanvas(
416+
canvas,
417+
labels,
418+
width,
419+
height,
420+
pointSize,
421+
fontSize,
422+
labelWidth,
423+
enableCircles,
424+
studentDataVersion
425+
);
426+
const canvasTextObjects = getCanvasTextObjects(canvas);
427+
expect(fabricLabels.length).toEqual(2);
428+
expect(fabricLabels[0].text.text).toEqual(label1Text);
429+
expect(fabricLabels[1].text.text).toEqual(label2Text);
430+
// sort the canvas text objects because their order is not guaranteed to be in the same order
431+
// we added them
432+
canvasTextObjects.sort(sortByTextField);
433+
expect(canvasTextObjects.length).toEqual(2);
434+
expect(canvasTextObjects[0].text).toMatch('Label 1');
435+
expect(canvasTextObjects[1].text).toMatch('Label 2');
436+
});
437+
}
438+
439+
function addLabelToCanvas() {
440+
it('should add label to canvas', () => {
441+
const canvas: any = createCanvas();
442+
const label: any = createFabricLabel();
443+
const enableCircles: boolean = true;
444+
service.addLabelToCanvas(canvas, label, enableCircles);
445+
const canvasTextObjects = getCanvasTextObjects(canvas);
446+
expect(canvasTextObjects.length).toEqual(1);
447+
expect(canvasTextObjects[0].text).toMatch(label1Text);
448+
});
449+
}
450+
451+
function getCanvasTextObjects(canvas: any): any[] {
452+
return canvas.getObjects().filter((obj: any) => {
453+
return typeof obj.text === 'string';
454+
});
455+
}
456+
457+
function sortByTextField(a: any, b: any): number {
458+
const aText: string = a.text;
459+
const bText: string = b.text;
460+
if (aText > bText) {
461+
return 1;
462+
} else if (aText < bText) {
463+
return -1;
464+
} else {
465+
return 0;
466+
}
467+
}
468+
469+
function createLabelServiceFunction() {
470+
it('shoud create a label', () => {
471+
const label: any = createFabricLabel();
472+
expect(label.circle).not.toBeNull();
473+
expect(label.line).not.toBeNull();
474+
expect(label.text).not.toBeNull();
475+
expect(label.text.text).toEqual(label1Text);
476+
expect(label.canEdit).toEqual(canEditBoolean);
477+
expect(label.canDelete).toEqual(canDeleteBoolean);
478+
});
479+
}
480+
481+
function makeSureValueIsWithinLimit() {
482+
const limit: number = 100;
483+
it('should make sure value is within limit when it is negative', () => {
484+
expectMakeSureValueIsWithinLimit(-1, limit, 0);
485+
});
486+
it('should make sure value is within limit when it is between zero and limit', () => {
487+
expectMakeSureValueIsWithinLimit(50, limit, 50);
488+
});
489+
it('should make sure value is within limit when it is greater than limit', () => {
490+
expectMakeSureValueIsWithinLimit(101, limit, 100);
491+
});
492+
}
493+
494+
function expectMakeSureValueIsWithinLimit(x: number, width: number, expectedValue: number) {
495+
expect(service.makeSureValueIsWithinLimit(x, width)).toEqual(expectedValue);
496+
}

src/main/webapp/site/src/app/teacher-hybrid-angular.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import { AnimationAuthoring } from '../../../wise5/components/animation/animatio
6262
import { OpenResponseGrading } from '../../../wise5/components/openResponse/open-response-grading/open-response-grading.component';
6363
import { MultipleChoiceGrading } from '../../../wise5/components/multipleChoice/multiple-choice-grading/multiple-choice-grading.component';
6464
import { MatchGrading } from '../../../wise5/components/match/match-grading/match-grading.component';
65+
import { LabelGrading } from '../../../wise5/components/label/label-grading/label-grading.component';
6566

6667
@NgModule({
6768
declarations: [
@@ -89,6 +90,7 @@ import { MatchGrading } from '../../../wise5/components/match/match-grading/matc
8990
GraphAuthoring,
9091
HtmlAuthoring,
9192
LabelAuthoring,
93+
LabelGrading,
9294
ManageStudentsComponent,
9395
MatchAuthoring,
9496
MatchGrading,

src/main/webapp/wise5/classroomMonitor/classroomMonitorComponents/shared/component-grading.component.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ export abstract class ComponentGrading {
1212
@Input()
1313
componentState: any;
1414

15+
@Input()
16+
isRevision: any = false;
17+
1518
componentContent: any;
1619

1720
constructor(protected ProjectService: ProjectService) {}
@@ -22,5 +25,6 @@ export abstract class ComponentGrading {
2225
this.nodeId,
2326
this.componentId
2427
);
28+
this.isRevision = this.isRevision === 'true';
2529
}
2630
}

src/main/webapp/wise5/classroomMonitor/classroomMonitorComponents/shared/workgroupComponentRevisions/workgroupComponentRevisions.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,16 @@ const WorkgroupComponentRevisions = {
158158
</h3>
159159
<div style="padding: 20px;">
160160
<ng-content ng-switch="item.componentState.componentType">
161-
<div ng-switch-when="Match|MultipleChoice|OpenResponse" ng-switch-when-separator="|" class="component__content" layout="row" layout-wrap>
161+
<div ng-switch-when="Label|Match|MultipleChoice|OpenResponse" ng-switch-when-separator="|" class="component__content" layout="row" layout-wrap>
162162
<div flex="100" flex-gt-sm="66" layout="column" class="component--grading__response">
163+
<label-grading
164+
ng-if="item.componentState.componentType === 'Label'"
165+
node-id="{{::$ctrl.nodeId}}"
166+
component-id="{{::$ctrl.componentId}}"
167+
component-state="{{ item.componentState }}"
168+
workgroup-id="::$ctrl.workgroupId"
169+
is-revision="true">
170+
</label-grading>
163171
<match-grading
164172
ng-if="item.componentState.componentType === 'Match'"
165173
node-id="{{::$ctrl.nodeId}}"

src/main/webapp/wise5/classroomMonitor/classroomMonitorComponents/shared/workgroupNodeGrading/workgroupNodeGrading.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,15 @@ const WorkgroupNodeGrading = {
138138
</h3>
139139
<ng-content ng-switch="::component.type">
140140
{{latestComponentState = $ctrl.getLatestComponentStateByWorkgroupIdAndComponentId($ctrl.workgroupId, component.id); ""}}
141-
<div ng-switch-when="Match|MultipleChoice|OpenResponse" ng-switch-when-separator="|" class="component__content" layout="row" layout-wrap>
141+
<div ng-switch-when="Label|Match|MultipleChoice|OpenResponse" ng-switch-when-separator="|" class="component__content" layout="row" layout-wrap>
142142
<div flex="100" flex-gt-sm="66" layout="column" class="component--grading__response">
143143
<ng-content ng-if="latestComponentState != null && latestComponentState !== ''">
144+
<label-grading
145+
ng-if="component.type === 'Label'"
146+
node-id="{{::$ctrl.nodeId}}"
147+
component-id="{{::component.id}}"
148+
component-state="{{latestComponentState}}">
149+
</label-grading>
144150
<match-grading
145151
ng-if="component.type === 'Match'"
146152
node-id="{{::$ctrl.nodeId}}"

0 commit comments

Comments
 (0)