From e691cdb3e4311038d6043084fa0cbaa2d7ef8745 Mon Sep 17 00:00:00 2001 From: Geoffrey Kwan Date: Tue, 20 Feb 2024 16:45:28 -0500 Subject: [PATCH] feat(Authoring): Add delete button to all steps (#1633) --- .../node-icon-and-title.component.html | 3 +- .../node-icon-and-title.harness.ts | 14 +++ ...project-authoring-lesson.component.spec.ts | 4 + .../project-authoring-step.component.html | 87 +++++++++++-------- .../project-authoring-step.component.scss | 29 ++++--- .../project-authoring-step.component.spec.ts | 4 + .../project-authoring-step.component.ts | 15 ++++ .../project-authoring-step.harness.ts | 28 +++++- .../project-authoring.component.spec.ts | 13 +++ .../project-authoring.harness.ts | 6 ++ src/assets/wise5/services/projectService.ts | 4 +- src/messages.xlf | 80 ++++++++++------- 12 files changed, 205 insertions(+), 82 deletions(-) create mode 100644 src/assets/wise5/authoringTool/choose-node-location/node-icon-and-title/node-icon-and-title.harness.ts diff --git a/src/assets/wise5/authoringTool/choose-node-location/node-icon-and-title/node-icon-and-title.component.html b/src/assets/wise5/authoringTool/choose-node-location/node-icon-and-title/node-icon-and-title.component.html index 9044317b0c6..f6e2311ddf7 100644 --- a/src/assets/wise5/authoringTool/choose-node-location/node-icon-and-title/node-icon-and-title.component.html +++ b/src/assets/wise5/authoringTool/choose-node-location/node-icon-and-title/node-icon-and-title.component.html @@ -1,4 +1,5 @@
  - {{ getNodePosition(nodeId) }}: {{ getNodeTitle(nodeId) }} + {{ getNodePosition(nodeId) }}: + {{ getNodeTitle(nodeId) }}
diff --git a/src/assets/wise5/authoringTool/choose-node-location/node-icon-and-title/node-icon-and-title.harness.ts b/src/assets/wise5/authoringTool/choose-node-location/node-icon-and-title/node-icon-and-title.harness.ts new file mode 100644 index 00000000000..231ba208334 --- /dev/null +++ b/src/assets/wise5/authoringTool/choose-node-location/node-icon-and-title/node-icon-and-title.harness.ts @@ -0,0 +1,14 @@ +import { ComponentHarness } from '@angular/cdk/testing'; + +export class NodeIconAndTitleHarness extends ComponentHarness { + static hostSelector = 'node-icon-and-title'; + + getStepPosition = this.locatorForOptional('.step-number'); + getStepTitle = this.locatorFor('.step-title'); + + async getPositionAndTitle(): Promise { + const position = await (await this.getStepPosition())?.text(); + const title = await (await this.getStepTitle()).text(); + return position == null ? title : `${position} ${title}`; + } +} diff --git a/src/assets/wise5/authoringTool/project-authoring-lesson/project-authoring-lesson.component.spec.ts b/src/assets/wise5/authoringTool/project-authoring-lesson/project-authoring-lesson.component.spec.ts index e36d42e3034..834256eebc1 100644 --- a/src/assets/wise5/authoringTool/project-authoring-lesson/project-authoring-lesson.component.spec.ts +++ b/src/assets/wise5/authoringTool/project-authoring-lesson/project-authoring-lesson.component.spec.ts @@ -15,6 +15,8 @@ import { MatIconModule } from '@angular/material/icon'; import { ProjectAuthoringStepComponent } from '../project-authoring-step/project-authoring-step.component'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { ProjectAuthoringLessonHarness } from './project-authoring-lesson.harness'; +import { DeleteNodeService } from '../../services/deleteNodeService'; +import { RouterTestingModule } from '@angular/router/testing'; let component: ProjectAuthoringLessonComponent; let fixture: ComponentFixture; @@ -39,10 +41,12 @@ describe('ProjectAuthoringLessonComponent', () => { MatCheckboxModule, MatDialogModule, MatIconModule, + RouterTestingModule, StudentTeacherCommonServicesModule ], providers: [ ClassroomStatusService, + DeleteNodeService, TeacherDataService, TeacherProjectService, TeacherWebSocketService diff --git a/src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.html b/src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.html index 04632d4b5ba..e69f16450b5 100644 --- a/src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.html +++ b/src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.html @@ -1,57 +1,72 @@
+ +
+ call_split + block + message +
- -

- call_split - block -

+
+
+ +
diff --git a/src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.scss b/src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.scss index 257113c449d..5dc7d9755c3 100644 --- a/src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.scss +++ b/src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.scss @@ -1,8 +1,17 @@ -.stepHeader { - margin-left: 30px !important; +.step { + height: 50px; + padding: 4px; + margin: 4px 30px; + border: 2px solid #dddddd; + border-radius: 6px; + position: relative; } -.branchPathStepHeader { +.step:hover { + background-color: #add8e6 !important; +} + +.branch-path-step { margin-left: 55px !important; } @@ -10,17 +19,17 @@ cursor: pointer; } -.projectItem:hover { - background-color: #add8e6; +.dynamic-step-buttons { + display: none; } -.projectItemTitleDiv:hover { - background-color: #add8e6; +.step:hover .dynamic-step-buttons { + display: block; } -.projectItemTitleDiv { - width: 100%; - font-weight: initial; +.step-click-to-enter-div { + flex-grow: 1; + align-self: stretch; } .rotate-180 { diff --git a/src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.spec.ts b/src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.spec.ts index c26e6c8dfcd..002f52dcf40 100644 --- a/src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.spec.ts +++ b/src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.spec.ts @@ -12,6 +12,8 @@ import { NodeIconAndTitleComponent } from '../choose-node-location/node-icon-and import { NodeIconComponent } from '../../vle/node-icon/node-icon.component'; import { FormsModule } from '@angular/forms'; import { MatIconModule } from '@angular/material/icon'; +import { DeleteNodeService } from '../../services/deleteNodeService'; +import { RouterTestingModule } from '@angular/router/testing'; const nodeId1 = 'nodeId1'; const node = { id: nodeId1 }; @@ -29,10 +31,12 @@ describe('ProjectAuthoringStepComponent', () => { MatCheckboxModule, MatDialogModule, MatIconModule, + RouterTestingModule, StudentTeacherCommonServicesModule ], providers: [ ClassroomStatusService, + DeleteNodeService, TeacherDataService, TeacherProjectService, TeacherWebSocketService diff --git a/src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.ts b/src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.ts index f6553e8c32d..95ca57c7ed2 100644 --- a/src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.ts +++ b/src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.ts @@ -4,6 +4,7 @@ import { TeacherDataService } from '../../services/teacherDataService'; import { Router } from '@angular/router'; import { SelectNodeEvent } from '../domain/select-node-event'; import { NodeTypeSelected } from '../domain/node-type-selected'; +import { DeleteNodeService } from '../../services/deleteNodeService'; @Component({ selector: 'project-authoring-step', @@ -19,6 +20,7 @@ export class ProjectAuthoringStepComponent { constructor( private dataService: TeacherDataService, + private deleteNodeService: DeleteNodeService, private projectService: TeacherProjectService, private router: Router ) {} @@ -90,4 +92,17 @@ export class ProjectAuthoringStepComponent { this.dataService.setCurrentNodeByNodeId(nodeId); this.router.navigate([`/teacher/edit/unit/${this.projectId}/node/${nodeId}/advanced/path`]); } + + protected delete(event: Event): void { + event.stopPropagation(); + if (confirm($localize`Are you sure you want to delete this step?`)) { + this.deleteNodeService.deleteNode(this.step.id); + this.saveAndRefreshProject(); + } + } + + private saveAndRefreshProject(): void { + this.projectService.saveProject(); + this.projectService.refreshProject(); + } } diff --git a/src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.harness.ts b/src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.harness.ts index e680d56f682..68c49f8c904 100644 --- a/src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.harness.ts +++ b/src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.harness.ts @@ -1,5 +1,31 @@ -import { ComponentHarness } from '@angular/cdk/testing'; +import { BaseHarnessFilters, ComponentHarness, HarnessPredicate } from '@angular/cdk/testing'; +import { NodeIconAndTitleHarness } from '../choose-node-location/node-icon-and-title/node-icon-and-title.harness'; +import { MatButtonHarness } from '@angular/material/button/testing'; + +interface ProjectAuthoringStepHarnessFilters extends BaseHarnessFilters { + title?: string | RegExp; +} export class ProjectAuthoringStepHarness extends ComponentHarness { static hostSelector = 'project-authoring-step'; + + getStepTitleElement = this.locatorFor(NodeIconAndTitleHarness); + getDeleteButton = this.locatorFor(MatButtonHarness.with({ selector: '.delete-button' })); + + static with( + options: ProjectAuthoringStepHarnessFilters + ): HarnessPredicate { + return new HarnessPredicate(ProjectAuthoringStepHarness, options).addOption( + 'title', + options.title, + async (harness, title) => { + return HarnessPredicate.stringMatches(harness.getStepTitle(), title); + } + ); + } + + async getStepTitle(): Promise { + const stepTitleElement = await this.getStepTitleElement(); + return await stepTitleElement.getPositionAndTitle(); + } } diff --git a/src/assets/wise5/authoringTool/project-authoring/project-authoring.component.spec.ts b/src/assets/wise5/authoringTool/project-authoring/project-authoring.component.spec.ts index 97291d69ee6..db77ef3b572 100644 --- a/src/assets/wise5/authoringTool/project-authoring/project-authoring.component.spec.ts +++ b/src/assets/wise5/authoringTool/project-authoring/project-authoring.component.spec.ts @@ -85,6 +85,7 @@ describe('ProjectAuthoringComponent', () => { collapseAllButtonClicked(); expandAllButtonClicked(); + deleteSpecificStep(); }); function collapseAllButtonClicked() { @@ -137,3 +138,15 @@ function expandAllButtonClicked() { }); }); } + +function deleteSpecificStep() { + describe('delete step button on a specific step is clicked', () => { + it('deletes the step', async () => { + expect((await harness.getSteps()).length).toEqual(49); + spyOn(window, 'confirm').and.returnValue(true); + const step = await harness.getStep('1.1: HTML Step'); + await (await step.getDeleteButton()).click(); + expect((await harness.getSteps()).length).toEqual(48); + }); + }); +} 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 40a66c6d72a..f550f04cd22 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,16 @@ import { ComponentHarness } from '@angular/cdk/testing'; import { MatButtonHarness } from '@angular/material/button/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'; getExpandAllButton = this.locatorFor(MatButtonHarness.with({ text: '+ Expand All' })); getCollapseAllButton = this.locatorFor(MatButtonHarness.with({ text: '- Collapse All' })); getLessons = this.locatorForAll(ProjectAuthoringLessonHarness); + getSteps = this.locatorForAll(ProjectAuthoringStepHarness); + + getStep(title: string): Promise { + return this.locatorForOptional(ProjectAuthoringStepHarness.with({ title: title }))(); + } } diff --git a/src/assets/wise5/services/projectService.ts b/src/assets/wise5/services/projectService.ts index 9f92c152163..b8bc826efe7 100644 --- a/src/assets/wise5/services/projectService.ts +++ b/src/assets/wise5/services/projectService.ts @@ -64,7 +64,9 @@ export class ProjectService { this.inactiveStepNodes = []; this.inactiveGroupNodes = []; this.groupNodes = []; - this.idToNode = {}; + Object.keys(this.idToNode).forEach((key) => { + delete this.idToNode[key]; + }); this.metadata = {}; this.rootNode = null; this.idToOrder = {}; diff --git a/src/messages.xlf b/src/messages.xlf index af4938987ee..200fb8716da 100644 --- a/src/messages.xlf +++ b/src/messages.xlf @@ -12208,39 +12208,53 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.Select step src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.html - 12 - - - - Click to enter step - - src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.html - 21 + 15 - + Branch point with paths based on + getBranchCriteriaDescription(step.id) + }}"/> src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.html - 31,33 + 25,27 - + Constraint(s) + getConstraintDescriptions(step.id) + }}"/> src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.html - 41,43 + 35,37 Has Rubric src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.html - 50 + 44 + + + + Click to enter step + + src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.html + 52 + + + + Delete step + + src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.html + 64 + + + + Are you sure you want to delete this step? + + src/assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component.ts + 98 @@ -21369,112 +21383,112 @@ If this problem continues, let your teacher know and move on to the next activit Complete <b></b> src/assets/wise5/services/projectService.ts - 1186 + 1188 Visit <b></b> src/assets/wise5/services/projectService.ts - 1192 + 1194 Correctly answer <b></b> src/assets/wise5/services/projectService.ts - 1198 + 1200 Obtain a score of <b></b> on <b></b> src/assets/wise5/services/projectService.ts - 1213 + 1215 You must choose "" on "" src/assets/wise5/services/projectService.ts - 1221 + 1223 Submit <b></b> time on <b></b> src/assets/wise5/services/projectService.ts - 1233 + 1235 Submit <b></b> times on <b></b> src/assets/wise5/services/projectService.ts - 1235 + 1237 Take the branch path from <b></b> to <b></b> src/assets/wise5/services/projectService.ts - 1242 + 1244 Write <b></b> words on <b></b> src/assets/wise5/services/projectService.ts - 1248 + 1250 "" is visible src/assets/wise5/services/projectService.ts - 1254 + 1256 "" is visitable src/assets/wise5/services/projectService.ts - 1260 + 1262 Add <b></b> note on <b></b> src/assets/wise5/services/projectService.ts - 1267 + 1269 Add <b></b> notes on <b></b> src/assets/wise5/services/projectService.ts - 1269 + 1271 You must fill in <b></b> row in the <b>Table</b> on <b></b> src/assets/wise5/services/projectService.ts - 1276 + 1278 You must fill in <b></b> rows in the <b>Table</b> on <b></b> src/assets/wise5/services/projectService.ts - 1278 + 1280 Wait for your teacher to unlock the item src/assets/wise5/services/projectService.ts - 1281 + 1283