-
There are no Unused Steps
+
There are no unused steps
;
let harness: ProjectAuthoringHarness;
+let http: HttpClient;
let projectService: TeacherProjectService;
let route: ActivatedRoute;
let router: Router;
@@ -44,6 +54,7 @@ describe('ProjectAuthoringComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [
+ AddLessonButtonComponent,
ConcurrentAuthorsMessageComponent,
NodeAuthoringComponent,
NodeIconComponent,
@@ -63,6 +74,7 @@ describe('ProjectAuthoringComponent', () => {
MatFormFieldModule,
MatIconModule,
MatInputModule,
+ MatMenuModule,
MatTooltipModule,
RouterTestingModule,
StudentTeacherCommonServicesModule
@@ -79,9 +91,22 @@ describe('ProjectAuthoringComponent', () => {
}).compileComponents();
projectService = TestBed.inject(TeacherProjectService);
projectService.setProject(copy(demoProjectJSON_import));
+ configService = TestBed.inject(ConfigService);
+ http = TestBed.inject(HttpClient);
route = TestBed.inject(ActivatedRoute);
router = TestBed.inject(Router);
window.history.pushState({}, '', '');
+ getConfigParamSpy = spyOn(configService, 'getConfigParam');
+ getConfigParamSpy.withArgs('canEditProject').and.returnValue(true);
+ getConfigParamSpy.withArgs('mode').and.returnValue('author');
+ getConfigParamSpy.withArgs('saveProjectURL').and.returnValue('/api/author/project/save/1');
+ spyOn(configService, 'getMyUserInfo').and.returnValue({
+ userId: 4,
+ firstName: 'Spongebob',
+ lastName: 'Squarepants',
+ username: 'spongebobsquarepants'
+ });
+ spyOn(http, 'post').and.returnValue(of({ status: 'success' }) as any);
fixture = TestBed.createComponent(ProjectAuthoringComponent);
component = fixture.componentInstance;
fixture.detectChanges();
@@ -95,6 +120,8 @@ describe('ProjectAuthoringComponent', () => {
moveSpecificStep();
deleteSpecificLesson();
moveSpecificLesson();
+ addStep();
+ addLesson();
});
function collapseAllButtonClicked() {
@@ -217,3 +244,165 @@ function moveSpecificLesson() {
});
});
}
+
+function addStep() {
+ addStepBefore();
+ addStepBeforeFirstStepInLesson();
+ addStepAfter();
+}
+
+function addStepBefore() {
+ describe('add step button is clicked on a step that is not the first step in a lesson', () => {
+ describe('add step before is chosen on the menu', () => {
+ it('adds a step before the chosen step', async () => {
+ const addStepButtons = await harness.getAddStepButtons();
+ addStepButtons[1].click();
+ const addStepMenu = await harness.getOpenedAddStepMenu();
+ await addStepMenu.clickItem({ text: /Add Step Before/ });
+ const newStep = await harness.getStep('1.2: New Step');
+ expect(newStep).not.toEqual(null);
+ });
+ });
+ });
+}
+
+function addStepBeforeFirstStepInLesson() {
+ describe('add step button is clicked on a step that is the first step in a lesson', () => {
+ describe('add step before is chosen on the menu', () => {
+ it('adds a step before the chosen step', async () => {
+ const addStepButtons = await harness.getAddStepButtons();
+ addStepButtons[0].click();
+ const addStepMenu = await harness.getOpenedAddStepMenu();
+ await addStepMenu.clickItem({ text: /Add Step Before/ });
+ const newStep = await harness.getStep('1.1: New Step');
+ expect(newStep).not.toEqual(null);
+ });
+ });
+ });
+}
+
+function addStepAfter() {
+ describe('add step button is clicked', () => {
+ describe('add step after is chosen on the menu', () => {
+ it('adds a step after the chosen step', async () => {
+ const addStepButtons = await harness.getAddStepButtons();
+ addStepButtons[1].click();
+ const addStepMenu = await harness.getOpenedAddStepMenu();
+ await addStepMenu.clickItem({ text: /Add Step After/ });
+ const newStep = await harness.getStep('1.3: New Step');
+ expect(newStep).not.toEqual(null);
+ });
+ });
+ });
+}
+
+function addLesson() {
+ addLessonBefore();
+ addLessonBeforeFirstLesson();
+ addLessonAfter();
+ addInactiveLessonBefore();
+ addInactiveLessonBeforeFirstLesson();
+ addInactiveLessonAfter();
+}
+
+function addLessonBeforeFirstLesson() {
+ describe('add lesson button is clicked on a lesson that is the first lesson', () => {
+ describe('add lesson before is chosen on the menu', () => {
+ it('adds a lesson before the chosen lesson', async () => {
+ const addLessonButtons = await harness.getAddLessonButtons();
+ addLessonButtons[0].click();
+ const addLessonMenu = await harness.getOpenedAddStepMenu();
+ await addLessonMenu.clickItem({ text: addLessonBeforeRegex });
+ const newLesson = await harness.getLesson('1: New Lesson');
+ expect(newLesson).not.toEqual(null);
+ });
+ });
+ });
+}
+
+function addLessonBefore() {
+ describe('add lesson button is clicked on a lesson that is not the first lesson', () => {
+ describe('add lesson before is chosen on the menu', () => {
+ it('adds a lesson before the chosen lesson', async () => {
+ const addLessonButtons = await harness.getAddLessonButtons();
+ addLessonButtons[1].click();
+ const addLessonMenu = await harness.getOpenedAddStepMenu();
+ await addLessonMenu.clickItem({ text: addLessonBeforeRegex });
+ const newLesson = await harness.getLesson('2: New Lesson');
+ expect(newLesson).not.toEqual(null);
+ });
+ });
+ });
+}
+
+function addLessonAfter() {
+ describe('add lesson button is clicked', () => {
+ describe('add lesson after is chosen on the menu', () => {
+ it('adds a lesson after the chosen lesson', async () => {
+ const addLessonButtons = await harness.getAddLessonButtons();
+ addLessonButtons[0].click();
+ const addLessonMenu = await harness.getOpenedAddStepMenu();
+ await addLessonMenu.clickItem({ text: addLessonAfterRegex });
+ const newLesson = await harness.getLesson('2: New Lesson');
+ expect(newLesson).not.toEqual(null);
+ });
+ });
+ });
+}
+
+function addInactiveLessonBeforeFirstLesson() {
+ describe('add lesson button is clicked on an inactive lesson that is the first inactive lesson', () => {
+ describe('add lesson before is chosen on the menu', () => {
+ it('adds a lesson before the chosen lesson', async () => {
+ const addLessonButtons = await harness.getAddLessonButtons();
+ addLessonButtons[5].click();
+ const addLessonMenu = await harness.getOpenedAddStepMenu();
+ await addLessonMenu.clickItem({ text: addLessonBeforeRegex });
+ const unusedLessonTitles = await harness.getUnusedLessonTitles();
+ expect(unusedLessonTitles).toEqual([
+ 'New Lesson',
+ 'Inactive Lesson One',
+ 'Inactive Lesson Two'
+ ]);
+ });
+ });
+ });
+}
+
+function addInactiveLessonBefore() {
+ describe('add lesson button is clicked on an inactive lesson that is not the first inactive lesson', () => {
+ describe('add lesson before is chosen on the menu', () => {
+ it('adds a lesson before the chosen lesson', async () => {
+ const addLessonButtons = await harness.getAddLessonButtons();
+ addLessonButtons[6].click();
+ const addLessonMenu = await harness.getOpenedAddStepMenu();
+ await addLessonMenu.clickItem({ text: addLessonBeforeRegex });
+ const unusedLessonTitles = await harness.getUnusedLessonTitles();
+ expect(unusedLessonTitles).toEqual([
+ 'Inactive Lesson One',
+ 'New Lesson',
+ 'Inactive Lesson Two'
+ ]);
+ });
+ });
+ });
+}
+
+function addInactiveLessonAfter() {
+ describe('add lesson button is clicked next to an inactive lesson', () => {
+ describe('add lesson after is chosen on the menu', () => {
+ it('adds a lesson after the chosen lesson', async () => {
+ const addLessonButtons = await harness.getAddLessonButtons();
+ addLessonButtons[6].click();
+ const addLessonMenu = await harness.getOpenedAddStepMenu();
+ await addLessonMenu.clickItem({ text: addLessonAfterRegex });
+ const unusedLessonTitles = await harness.getUnusedLessonTitles();
+ expect(unusedLessonTitles).toEqual([
+ 'Inactive Lesson One',
+ 'Inactive Lesson Two',
+ 'New Lesson'
+ ]);
+ });
+ });
+ });
+}
diff --git a/src/assets/wise5/authoringTool/project-authoring/project-authoring.harness.ts b/src/assets/wise5/authoringTool/project-authoring/project-authoring.harness.ts
index 4f0a59c5a5d..8e7d8a6378f 100644
--- a/src/assets/wise5/authoringTool/project-authoring/project-authoring.harness.ts
+++ b/src/assets/wise5/authoringTool/project-authoring/project-authoring.harness.ts
@@ -1,10 +1,18 @@
import { ComponentHarness } from '@angular/cdk/testing';
import { MatButtonHarness } from '@angular/material/button/testing';
+import { MatMenuHarness } from '@angular/material/menu/testing';
import { ProjectAuthoringLessonHarness } from '../project-authoring-lesson/project-authoring-lesson.harness';
import { ProjectAuthoringStepHarness } from '../project-authoring-step/project-authoring-step.harness';
export class ProjectAuthoringHarness extends ComponentHarness {
static hostSelector = 'project-authoring';
+ getAddLessonButtons = this.locatorForAll(
+ MatButtonHarness.with({ selector: '[matTooltip="Add lesson"]' })
+ );
+ getAddStepButtons = this.locatorForAll(
+ MatButtonHarness.with({ selector: '[matTooltip="Add step"]' })
+ );
+ getAddStepMenus = this.locatorForAll(MatMenuHarness);
getCollapseAllButton = this.locatorFor(MatButtonHarness.with({ text: '- Collapse All' }));
getExpandAllButton = this.locatorFor(MatButtonHarness.with({ text: '+ Expand All' }));
getLessons = this.locatorForAll(ProjectAuthoringLessonHarness);
@@ -14,7 +22,29 @@ export class ProjectAuthoringHarness extends ComponentHarness {
return this.locatorForOptional(ProjectAuthoringLessonHarness.with({ title: title }))();
}
+ getUnusedLessons(): Promise {
+ return this.locatorForAll(ProjectAuthoringLessonHarness.with({ title: /^(?!\d*: ).*/ }))();
+ }
+
+ async getUnusedLessonTitles(): Promise {
+ const unusedLessonTitles = [];
+ for (const unusedLesson of await this.getUnusedLessons()) {
+ unusedLessonTitles.push(await unusedLesson.getTitle());
+ }
+ return unusedLessonTitles;
+ }
+
getStep(title: string): Promise {
return this.locatorForOptional(ProjectAuthoringStepHarness.with({ title: title }))();
}
+
+ async getOpenedAddStepMenu(): Promise {
+ const addStepMenus = await this.getAddStepMenus();
+ for (const menu of addStepMenus) {
+ if (await menu.isOpen()) {
+ return menu;
+ }
+ }
+ return null;
+ }
}
diff --git a/src/assets/wise5/common/dom/dom.ts b/src/assets/wise5/common/dom/dom.ts
index 03e8b4ba8bb..cf7406a1262 100644
--- a/src/assets/wise5/common/dom/dom.ts
+++ b/src/assets/wise5/common/dom/dom.ts
@@ -25,8 +25,7 @@ export function temporarilyHighlightElement(id: string, duration: number = 1000)
*/
setTimeout(() => {
element.css({
- transition: '',
- 'background-color': ''
+ transition: ''
});
}, 2000);
}, duration);
diff --git a/src/assets/wise5/services/projectService.ts b/src/assets/wise5/services/projectService.ts
index 83ff6f4f08d..107b2584128 100644
--- a/src/assets/wise5/services/projectService.ts
+++ b/src/assets/wise5/services/projectService.ts
@@ -2002,4 +2002,34 @@ export class ProjectService {
getSpeechToTextSettings(): any {
return this.project.speechToText;
}
+
+ getPreviousNodeId(nodeId: string): string {
+ if (this.isActive(nodeId)) {
+ const parentGroup = this.getParentGroup(nodeId);
+ const childIds = parentGroup.ids;
+ return childIds[childIds.indexOf(nodeId) - 1];
+ } else {
+ const inactiveGroupNodes = this.getInactiveGroupNodes();
+ for (let i = 0; i < inactiveGroupNodes.length; i++) {
+ if (inactiveGroupNodes[i].id === nodeId) {
+ return inactiveGroupNodes[i - 1]?.id;
+ }
+ }
+ }
+ return null;
+ }
+
+ isFirstStepInLesson(nodeId: string): boolean {
+ for (const lesson of this.getGroupNodes()) {
+ if (lesson.startId === nodeId) {
+ return true;
+ }
+ }
+ for (const inactiveLesson of this.getInactiveGroupNodes()) {
+ if (inactiveLesson.startId === nodeId) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/src/assets/wise5/services/teacherProjectService.ts b/src/assets/wise5/services/teacherProjectService.ts
index 7d7c35dcdba..6344e08bd68 100644
--- a/src/assets/wise5/services/teacherProjectService.ts
+++ b/src/assets/wise5/services/teacherProjectService.ts
@@ -2959,7 +2959,7 @@ export class TeacherProjectService extends ProjectService {
*/
isFirstNodeInBranchPath(nodeId) {
for (const node of this.getNodes()) {
- if (node.transitionLogic != null && node.transitionLogic.transitions != null) {
+ if (node.transitionLogic?.transitions?.length > 1) {
for (const transition of node.transitionLogic.transitions) {
if (transition.to === nodeId) {
return true;
diff --git a/src/messages.xlf b/src/messages.xlf
index 01c2f2f5edb..a2f47ffd28d 100644
--- a/src/messages.xlf
+++ b/src/messages.xlf
@@ -9092,6 +9092,34 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.69
+
+
+
+ src/assets/wise5/authoringTool/add-lesson-button/add-lesson-button.component.html
+ 7
+
+
+
+
+
+ src/assets/wise5/authoringTool/add-lesson-button/add-lesson-button.component.html
+ 15
+
+
+
+
+
+ src/assets/wise5/authoringTool/add-lesson-button/add-lesson-button.component.html
+ 18
+
+
+
+
+
+ src/assets/wise5/authoringTool/add-lesson-button/add-lesson-button.component.ts
+ 51
+
+
@@ -9189,7 +9217,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.
src/assets/wise5/authoringTool/project-authoring/project-authoring.component.html
- 89
+ 99
@@ -9752,10 +9780,6 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.src/assets/wise5/authoringTool/choose-node-location/choose-move-node-location/choose-move-node-location.component.html
41
-
- src/assets/wise5/authoringTool/project-authoring/project-authoring.component.html
- 90
-
@@ -9769,7 +9793,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.
src/assets/wise5/authoringTool/project-authoring/project-authoring.component.html
- 102
+ 120
@@ -9782,10 +9806,6 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.src/assets/wise5/authoringTool/choose-node-location/choose-move-node-location/choose-move-node-location.component.html
81
-
- src/assets/wise5/authoringTool/project-authoring/project-authoring.component.html
- 103
-
@@ -12214,11 +12234,43 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.49
+
+
+
+ src/assets/wise5/authoringTool/project-authoring-lesson/project-authoring-lesson.component.html
+ 84
+
+
+ src/assets/wise5/authoringTool/project-authoring-lesson/project-authoring-lesson.component.html
+ 110
+
+
+
+
+
+ src/assets/wise5/authoringTool/project-authoring-lesson/project-authoring-lesson.component.html
+ 97,98
+
+
+
+
+
+ src/assets/wise5/authoringTool/project-authoring-lesson/project-authoring-lesson.component.html
+ 100,101
+
+
+
+
+
+ src/assets/wise5/authoringTool/project-authoring-lesson/project-authoring-lesson.component.html
+ 105
+
+
src/assets/wise5/authoringTool/project-authoring-lesson/project-authoring-lesson.component.ts
- 60
+ 61
@@ -12323,6 +12375,27 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.73,75
+
+
+
+ src/assets/wise5/authoringTool/project-authoring/project-authoring.component.html
+ 79
+
+
+
+
+
+ src/assets/wise5/authoringTool/project-authoring/project-authoring.component.html
+ 101
+
+
+
+
+
+ src/assets/wise5/authoringTool/project-authoring/project-authoring.component.html
+ 121
+
+
@@ -14264,6 +14337,10 @@ Are you sure you want to proceed?
src/assets/wise5/classroomMonitor/dataExport/export-raw-data/export-raw-data.component.html
16
+
+ src/assets/wise5/classroomMonitor/dataExport/export-raw-data/export-raw-data.component.html
+ 16
+