Skip to content

Commit f32035e

Browse files
refactor(TeacherProjectService): Extract CreateComponentService (#1911)
1 parent 2560488 commit f32035e

File tree

9 files changed

+123
-95
lines changed

9 files changed

+123
-95
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { TestBed } from '@angular/core/testing';
2+
import { CreateComponentService } from '../../assets/wise5/services/createComponentService';
3+
import { TeacherProjectService } from '../../assets/wise5/services/teacherProjectService';
4+
import { StudentTeacherCommonServicesModule } from '../student-teacher-common-services.module';
5+
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
6+
import { ComponentServiceLookupService } from '../../assets/wise5/services/componentServiceLookupService';
7+
import { Node } from '../../assets/wise5/common/Node';
8+
9+
let componentServiceLookupService: ComponentServiceLookupService;
10+
let projectService: TeacherProjectService;
11+
let service: CreateComponentService;
12+
let node;
13+
describe('CreateComponentService', () => {
14+
beforeEach(() => {
15+
TestBed.configureTestingModule({
16+
imports: [StudentTeacherCommonServicesModule],
17+
providers: [
18+
CreateComponentService,
19+
TeacherProjectService,
20+
provideHttpClient(withInterceptorsFromDi())
21+
]
22+
});
23+
node = new Node();
24+
componentServiceLookupService = TestBed.inject(ComponentServiceLookupService);
25+
projectService = TestBed.inject(TeacherProjectService);
26+
service = TestBed.inject(CreateComponentService);
27+
spyOn(projectService, 'getNode').and.returnValue(node);
28+
});
29+
create_NullInsertAfterComponentId();
30+
create_NonNullInsertAfterComponentId();
31+
});
32+
33+
function create_NullInsertAfterComponentId() {
34+
describe('create() without insertAfterComponentId', () => {
35+
it('should add the new component at the beginning', () => {
36+
const component1 = service.create('node1', 'HTML');
37+
expect(component1.type).toEqual('HTML');
38+
expectNodeComponentTypes(['HTML']);
39+
const component2 = service.create('node1', 'OpenResponse');
40+
expect(component2.type).toEqual('OpenResponse');
41+
expectNodeComponentTypes(['OpenResponse', 'HTML']);
42+
});
43+
});
44+
}
45+
46+
function create_NonNullInsertAfterComponentId() {
47+
describe('create() with insertAfterComponentId', () => {
48+
it('should add the new component after the insertAfterComponentId', () => {
49+
const component1 = service.create('node1', 'HTML');
50+
expect(component1.type).toEqual('HTML');
51+
expectNodeComponentTypes(['HTML']);
52+
const component2 = service.create('node1', 'OpenResponse', component1.id);
53+
expect(component2.type).toEqual('OpenResponse');
54+
expectNodeComponentTypes(['HTML', 'OpenResponse']);
55+
});
56+
});
57+
}
58+
59+
function expectNodeComponentTypes(types: string[]) {
60+
expect(node.components.map((c) => c.type)).toEqual(types);
61+
}

src/app/teacher/teacher-authoring.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { ComponentInfoService } from '../../assets/wise5/services/componentInfoS
3535
import { TeacherProjectTranslationService } from '../../assets/wise5/services/teacherProjectTranslationService';
3636
import { DeleteTranslationsService } from '../../assets/wise5/services/deleteTranslationsService';
3737
import { CopyTranslationsService } from '../../assets/wise5/services/copyTranslationsService';
38+
import { CreateComponentService } from '../../assets/wise5/services/createComponentService';
3839
import { NotifyAuthorService } from '../../assets/wise5/services/notifyAuthorService';
3940
import { RemoveNodeIdFromTransitionsService } from '../../assets/wise5/services/removeNodeIdFromTransitionsService';
4041

@@ -46,6 +47,7 @@ import { RemoveNodeIdFromTransitionsService } from '../../assets/wise5/services/
4647
CopyNodesService,
4748
CopyProjectService,
4849
CopyTranslationsService,
50+
CreateComponentService,
4951
DataExportService,
5052
{ provide: DataService, useExisting: TeacherDataService },
5153
TeacherProjectTranslationService,

src/assets/wise5/authoringTool/addNode/add-your-own-node/add-your-own-node.component.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
ReactiveFormsModule
1010
} from '@angular/forms';
1111
import { ComponentTypeService } from '../../../services/componentTypeService';
12+
import { CreateComponentService } from '../../../services/createComponentService';
1213
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
1314
import { TeacherProjectService } from '../../../services/teacherProjectService';
1415
import { CommonModule } from '@angular/common';
@@ -52,6 +53,7 @@ export class AddYourOwnNodeComponent {
5253

5354
constructor(
5455
private componentTypeService: ComponentTypeService,
56+
private createComponentService: CreateComponentService,
5557
private fb: FormBuilder,
5658
private projectService: TeacherProjectService,
5759
private route: ActivatedRoute,
@@ -97,7 +99,7 @@ export class AddYourOwnNodeComponent {
9799
private addInitialComponents(nodeId: string, components: any[]): void {
98100
components
99101
.reverse()
100-
.forEach((component) => this.projectService.createComponent(nodeId, component.type));
102+
.forEach((component) => this.createComponentService.create(nodeId, component.type));
101103
}
102104

103105
private save(): any {

src/assets/wise5/authoringTool/node/add-component-button/add-component-button.component.spec.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ComponentFixture, TestBed } from '@angular/core/testing';
22
import { AddComponentButtonComponent } from './add-component-button.component';
33
import { MatDialog } from '@angular/material/dialog';
4+
import { CreateComponentService } from '../../../services/createComponentService';
45
import { TeacherProjectService } from '../../../services/teacherProjectService';
56
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
67
import { HarnessLoader } from '@angular/cdk/testing';
@@ -11,9 +12,11 @@ import { Node } from '../../../common/Node';
1112
import { provideRouter } from '@angular/router';
1213

1314
class MockTeacherProjectService {
14-
createComponent() {}
1515
saveProject() {}
1616
}
17+
class MockCreateComponentService {
18+
create() {}
19+
}
1720
let loader: HarnessLoader;
1821
describe('AddComponentButtonComponent', () => {
1922
let component: AddComponentButtonComponent;
@@ -23,6 +26,7 @@ describe('AddComponentButtonComponent', () => {
2326
await TestBed.configureTestingModule({
2427
imports: [AddComponentButtonComponent],
2528
providers: [
29+
{ provide: CreateComponentService, useClass: MockCreateComponentService },
2630
{ provide: TeacherProjectService, useClass: MockTeacherProjectService },
2731
provideRouter([])
2832
]
@@ -40,7 +44,7 @@ describe('AddComponentButtonComponent', () => {
4044
afterClosed: () => of({ action: 'create', componentType: 'OpenResponse' })
4145
} as any);
4246
const projectService = TestBed.inject(TeacherProjectService);
43-
const createComponentSpy = spyOn(projectService, 'createComponent');
47+
const createComponentSpy = spyOn(TestBed.inject(CreateComponentService), 'create');
4448
const saveProjectSpy = spyOn(projectService, 'saveProject');
4549
await (await loader.getHarness(MatButtonHarness)).click();
4650
expect(dialogSpy).toHaveBeenCalledWith(ChooseNewComponent, {

src/assets/wise5/authoringTool/node/add-component-button/add-component-button.component.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Component, EventEmitter, Input, Output } from '@angular/core';
2+
import { CreateComponentService } from '../../../services/createComponentService';
23
import { TeacherProjectService } from '../../../services/teacherProjectService';
34
import { MatDialog } from '@angular/material/dialog';
45
import { ChooseNewComponent } from '../../../../../app/authoring-tool/add-component/choose-new-component/choose-new-component.component';
@@ -21,6 +22,7 @@ export class AddComponentButtonComponent {
2122
@Output() newComponentsEvent: EventEmitter<any> = new EventEmitter<any>();
2223

2324
constructor(
25+
private createComponentService: CreateComponentService,
2426
private dialog: MatDialog,
2527
private projectService: TeacherProjectService,
2628
private route: ActivatedRoute,
@@ -44,7 +46,7 @@ export class AddComponentButtonComponent {
4446
}
4547
});
4648
} else {
47-
const component = this.projectService.createComponent(
49+
const component = this.createComponentService.create(
4850
this.node.id,
4951
componentType,
5052
this.insertAfterComponentId

src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { TranslatableInputComponent } from '../../components/translatable-input/
3232
import { CopyTranslationsService } from '../../../services/copyTranslationsService';
3333
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
3434
import { RouterTestingModule } from '@angular/router/testing';
35+
import { CreateComponentService } from '../../../services/createComponentService';
3536

3637
let component: NodeAuthoringComponent;
3738
let component1: any;
@@ -68,6 +69,7 @@ describe('NodeAuthoringComponent', () => {
6869
],
6970
providers: [
7071
ClassroomStatusService,
72+
CreateComponentService,
7173
CopyTranslationsService,
7274
DeleteTranslationsService,
7375
TeacherProjectTranslationService,
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { Injectable } from '@angular/core';
2+
import { TeacherProjectService } from './teacherProjectService';
3+
import { ComponentServiceLookupService } from './componentServiceLookupService';
4+
import { Node } from '../common/Node';
5+
6+
@Injectable()
7+
export class CreateComponentService {
8+
constructor(
9+
private componentServiceLookupService: ComponentServiceLookupService,
10+
private projectService: TeacherProjectService
11+
) {}
12+
13+
/**
14+
* Create a new component
15+
* @param nodeId the node id to create the component in
16+
* @param componentType the component type
17+
* @param insertAfterComponentId Insert the new component after the given
18+
* component id. If this argument is null, we will place the new component
19+
* in the first position.
20+
*/
21+
create(nodeId: string, componentType: string, insertAfterComponentId: string = null): any {
22+
const node = this.projectService.getNode(nodeId);
23+
const service = this.componentServiceLookupService.getService(componentType);
24+
const component = service.createComponent();
25+
if (service.componentHasWork(component)) {
26+
if (node.showSaveButton == false) {
27+
if (this.projectService.doesAnyComponentInNodeShowSubmitButton(node.id)) {
28+
component.showSaveButton = true;
29+
} else {
30+
node.showSaveButton = true;
31+
}
32+
}
33+
}
34+
this.addComponentToNode(node, component, insertAfterComponentId);
35+
return component;
36+
}
37+
38+
private addComponentToNode(node: Node, component: any, insertAfterComponentId: string): void {
39+
const insertPosition =
40+
insertAfterComponentId == null
41+
? 0
42+
: node.components.findIndex((c) => c.id === insertAfterComponentId) + 1;
43+
node.components.splice(insertPosition, 0, component);
44+
}
45+
}

src/assets/wise5/services/teacherProjectService.ts

Lines changed: 0 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,50 +1164,6 @@ export class TeacherProjectService extends ProjectService {
11641164
}
11651165
}
11661166

1167-
/**
1168-
* Remove the node from the inactive nodes array
1169-
* @param nodeId the node to remove from the inactive nodes array
1170-
*/
1171-
removeNodeIdFromInactiveNodes(nodeId) {
1172-
const inactiveNodes = this.project.inactiveNodes;
1173-
if (inactiveNodes != null) {
1174-
for (let i = 0; i < inactiveNodes.length; i++) {
1175-
const inactiveNode = inactiveNodes[i];
1176-
if (inactiveNode != null) {
1177-
const inactiveNodeId = inactiveNode.id;
1178-
if (inactiveNodeId === nodeId) {
1179-
inactiveNodes.splice(i, 1);
1180-
}
1181-
}
1182-
}
1183-
}
1184-
}
1185-
1186-
/**
1187-
* Create a new component
1188-
* @param nodeId the node id to create the component in
1189-
* @param componentType the component type
1190-
* @param insertAfterComponentId Insert the new compnent after the given
1191-
* component id. If this argument is null, we will place the new component
1192-
* in the first position.
1193-
*/
1194-
createComponent(nodeId, componentType, insertAfterComponentId = null) {
1195-
const node = this.getNodeById(nodeId);
1196-
const service = this.componentServiceLookupService.getService(componentType);
1197-
const component = service.createComponent();
1198-
if (service.componentHasWork(component)) {
1199-
if (node.showSaveButton == false) {
1200-
if (this.doesAnyComponentInNodeShowSubmitButton(node.id)) {
1201-
component.showSaveButton = true;
1202-
} else {
1203-
node.showSaveButton = true;
1204-
}
1205-
}
1206-
}
1207-
this.addComponentToNode(node, component, insertAfterComponentId);
1208-
return component;
1209-
}
1210-
12111167
/**
12121168
* Check if any of the components in the node are showing their submit button.
12131169
* @param nodeId {string} The node id to check.
@@ -1247,52 +1203,6 @@ export class TeacherProjectService extends ProjectService {
12471203
return -1;
12481204
}
12491205

1250-
/**
1251-
* Add the component to the node
1252-
* @param node the node
1253-
* @param component the component
1254-
* @param insertAfterComponentId Insert the component after this given
1255-
* component id. If this argument is null, we will place the new component
1256-
* in the first position.
1257-
*/
1258-
addComponentToNode(node, component, insertAfterComponentId) {
1259-
if (insertAfterComponentId == null) {
1260-
node.components.splice(0, 0, component);
1261-
} else {
1262-
// place the new component after the insertAfterComponentId
1263-
1264-
// boolean flag for whether we have added the component yet
1265-
let added = false;
1266-
1267-
const components = node.components;
1268-
for (let c = 0; c < components.length; c++) {
1269-
const tempComponent = components[c];
1270-
if (
1271-
tempComponent != null &&
1272-
tempComponent.id != null &&
1273-
tempComponent.id == insertAfterComponentId
1274-
) {
1275-
/*
1276-
* we have found the component we want to add the new
1277-
* one after
1278-
*/
1279-
1280-
components.splice(c + 1, 0, component);
1281-
added = true;
1282-
break;
1283-
}
1284-
}
1285-
1286-
if (!added) {
1287-
/*
1288-
* the component has not been added yet so we will just add
1289-
* it at the end
1290-
*/
1291-
node.components.push(component);
1292-
}
1293-
}
1294-
}
1295-
12961206
/**
12971207
* Update the transitions so that the fromGroup points to the newToGroup
12981208
*

src/messages.xlf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9644,7 +9644,7 @@ Click &quot;Cancel&quot; to keep the invalid JSON open so you can fix it.</sourc
96449644
<source>New Step</source>
96459645
<context-group purpose="location">
96469646
<context context-type="sourcefile">src/assets/wise5/authoringTool/addNode/add-your-own-node/add-your-own-node.component.ts</context>
9647-
<context context-type="linenumber">46</context>
9647+
<context context-type="linenumber">47</context>
96489648
</context-group>
96499649
</trans-unit>
96509650
<trans-unit id="909afacc2d9d62ea57b1ba4b1e70b6c4314f668d" datatype="html">

0 commit comments

Comments
 (0)