Skip to content

Commit

Permalink
feat(Authoring): Implement add button next to lessons and steps (#1675)
Browse files Browse the repository at this point in the history
  • Loading branch information
geoffreykwan authored Mar 7, 2024
1 parent 5b5a951 commit 67dd348
Show file tree
Hide file tree
Showing 17 changed files with 576 additions and 30 deletions.
2 changes: 2 additions & 0 deletions src/app/teacher/authoring-tool.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,12 @@ import { CopyComponentButtonComponent } from '../../assets/wise5/authoringTool/n
import { SaveIndicatorComponent } from '../../assets/wise5/common/save-indicator/save-indicator.component';
import { ProjectAuthoringLessonComponent } from '../../assets/wise5/authoringTool/project-authoring-lesson/project-authoring-lesson.component';
import { ProjectAuthoringStepComponent } from '../../assets/wise5/authoringTool/project-authoring-step/project-authoring-step.component';
import { AddLessonButtonComponent } from '../../assets/wise5/authoringTool/add-lesson-button/add-lesson-button.component';

@NgModule({
declarations: [
AddComponentButtonComponent,
AddLessonButtonComponent,
AddLessonChooseLocationComponent,
AddLessonChooseTemplateComponent,
AddLessonConfigureComponent,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<button
mat-icon-button
color="primary"
(click)="addLesson()"
[matMenuTriggerFor]="lessonId == null ? null : lessonMenu"
#menuTrigger
matTooltip="Add lesson"
matTooltipPosition="above"
i18n-matTooltip
>
<mat-icon>add_circle</mat-icon>
</button>
<mat-menu #lessonMenu="matMenu">
<button mat-menu-item (click)="addLessonBefore()">
<mat-icon>add_circle</mat-icon><span i18n>Add Lesson Before</span>
</button>
<button mat-menu-item (click)="addLessonAfter()">
<mat-icon>add_circle</mat-icon><span i18n>Add Lesson After</span>
</button>
</mat-menu>
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AddLessonButtonComponent } from './add-lesson-button.component';
import { TeacherProjectService } from '../../services/teacherProjectService';
import { StudentTeacherCommonServicesModule } from '../../../../app/student-teacher-common-services.module';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { MatMenuModule } from '@angular/material/menu';
import { MatIconModule } from '@angular/material/icon';

describe('AddLessonButtonComponent', () => {
let component: AddLessonButtonComponent;
let fixture: ComponentFixture<AddLessonButtonComponent>;

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [AddLessonButtonComponent],
imports: [
HttpClientTestingModule,
StudentTeacherCommonServicesModule,
MatIconModule,
MatMenuModule
],
providers: [TeacherProjectService]
});
fixture = TestBed.createComponent(AddLessonButtonComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Component, Input, ViewChild } from '@angular/core';
import { TeacherProjectService } from '../../services/teacherProjectService';
import { temporarilyHighlightElement } from '../../common/dom/dom';
import { MatMenuTrigger } from '@angular/material/menu';

@Component({
selector: 'add-lesson-button',
templateUrl: './add-lesson-button.component.html',
styleUrls: ['./add-lesson-button.component.scss']
})
export class AddLessonButtonComponent {
@Input() active: boolean;
@Input() lessonId: string;
@ViewChild(MatMenuTrigger) menuTrigger: MatMenuTrigger;

constructor(private projectService: TeacherProjectService) {}

protected addLesson(): void {
if (this.lessonId == null) {
this.addFirstLesson();
} else {
this.menuTrigger.openMenu();
}
}

protected addLessonBefore(): void {
const previousLessonId = this.projectService.getPreviousNodeId(this.lessonId);
if (previousLessonId == null) {
this.addFirstLesson();
} else {
const newLesson = this.createNewLesson();
this.projectService.createNodeAfter(newLesson, previousLessonId);
this.updateProject(newLesson.id);
}
}

private addFirstLesson(): void {
const newLesson = this.createNewLesson();
const insertLocation = this.active ? 'group0' : 'inactiveGroups';
this.projectService.createNodeInside(newLesson, insertLocation);
this.updateProject(newLesson.id);
}

protected addLessonAfter(): void {
const newLesson = this.createNewLesson();
this.projectService.createNodeAfter(newLesson, this.lessonId);
this.updateProject(newLesson.id);
}

private createNewLesson(): any {
return this.projectService.createGroup($localize`New Lesson`);
}

private updateProject(newNodeId: string): void {
this.projectService.checkPotentialStartNodeIdChangeThenSaveProject().then(() => {
this.projectService.refreshProject();
// This timeout is used to allow the lesson to be added to the DOM before we highlight it
setTimeout(() => {
temporarilyHighlightElement(newNodeId);
});
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,56 @@
</div>
</div>
<div *ngIf="expanded" fxLayout="column">
<ng-container *ngFor="let childId of lesson.ids">
<div
*ngFor="let childId of lesson.ids"
class="step-div"
fxLayout="row wrap"
fxLayoutAlign="start center"
>
<project-authoring-step
[step]="idToNode[childId]"
(selectNodeEvent)="selectNodeEvent.emit($event)"
[showPosition]="showPosition"
[projectId]="projectId"
fxFlex
></project-authoring-step>
</ng-container>
<button
mat-icon-button
color="primary"
[matMenuTriggerFor]="step"
#menuTrigger="matMenuTrigger"
matTooltip="Add step"
matTooltipPosition="above"
i18n-matTooltip
>
<mat-icon>add_circle</mat-icon>
</button>
<mat-menu #step="matMenu">
<button
mat-menu-item
(click)="addStepBefore(childId)"
[disabled]="isFirstNodeInBranchPath(childId)"
i18n
>
<mat-icon>add_circle</mat-icon>Add Step Before
</button>
<button mat-menu-item (click)="addStepAfter(childId)" i18n>
<mat-icon>add_circle</mat-icon>Add Step After
</button>
</mat-menu>
</div>
<div *ngIf="lesson.ids.length === 0" class="no-steps-message" fxLayoutAlign="start center">
This lesson has no steps
<div i18n>This lesson has no steps</div>
<button
mat-icon-button
color="primary"
(click)="addStepInside(lesson.id)"
matTooltip="Add step"
matTooltipPosition="above"
i18n-matTooltip
>
<mat-icon>add_circle</mat-icon>
</button>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { ProjectAuthoringLessonHarness } from './project-authoring-lesson.harnes
import { DeleteNodeService } from '../../services/deleteNodeService';
import { RouterTestingModule } from '@angular/router/testing';
import { CopyNodesService } from '../../services/copyNodesService';
import { MatMenuModule } from '@angular/material/menu';

let component: ProjectAuthoringLessonComponent;
let fixture: ComponentFixture<ProjectAuthoringLessonComponent>;
Expand All @@ -27,6 +28,9 @@ const nodeId1 = 'node1';
const nodeId2 = 'node2';
let teacherProjectService: TeacherProjectService;

const node1 = { id: nodeId1, title: 'Step 1' };
const node2 = { id: nodeId2, title: 'Step 2' };

describe('ProjectAuthoringLessonComponent', () => {
beforeEach(async () => {
TestBed.configureTestingModule({
Expand All @@ -42,6 +46,7 @@ describe('ProjectAuthoringLessonComponent', () => {
MatCheckboxModule,
MatDialogModule,
MatIconModule,
MatMenuModule,
RouterTestingModule,
StudentTeacherCommonServicesModule
],
Expand All @@ -56,15 +61,10 @@ describe('ProjectAuthoringLessonComponent', () => {
});
teacherProjectService = TestBed.inject(TeacherProjectService);
teacherProjectService.idToNode = {
node1: {
id: nodeId1,
title: 'Step 1'
},
node2: {
id: nodeId2,
title: 'Step 2'
}
node1: node1,
node2: node2
};
teacherProjectService.project = { nodes: [node1, node2] };
fixture = TestBed.createComponent(ProjectAuthoringLessonComponent);
component = fixture.componentInstance;
component.lesson = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { NodeTypeSelected } from '../domain/node-type-selected';
import { ExpandEvent } from '../domain/expand-event';
import { DeleteNodeService } from '../../services/deleteNodeService';
import { ActivatedRoute, Router } from '@angular/router';
import { temporarilyHighlightElement } from '../../common/dom/dom';

@Component({
selector: 'project-authoring-lesson',
Expand Down Expand Up @@ -63,6 +64,47 @@ export class ProjectAuthoringLessonComponent {
}
}

protected isFirstNodeInBranchPath(nodeId: string): boolean {
return this.projectService.isFirstNodeInBranchPath(nodeId);
}

protected addStepBefore(nodeId: string): void {
const newStep = this.createNewEmptyStep();
if (this.projectService.isFirstStepInLesson(nodeId)) {
this.projectService.createNodeInside(newStep, this.projectService.getParentGroupId(nodeId));
} else {
this.projectService.createNodeAfter(newStep, this.projectService.getPreviousNodeId(nodeId));
}
this.updateProject(newStep.id);
}

protected addStepAfter(nodeId: string): void {
const newStep = this.createNewEmptyStep();
this.projectService.createNodeAfter(newStep, nodeId);
this.updateProject(newStep.id);
}

protected addStepInside(nodeId: string): void {
const newStep = this.createNewEmptyStep();
this.projectService.createNodeInside(newStep, nodeId);
this.updateProject(newStep.id);
}

private createNewEmptyStep(): any {
return this.projectService.createNode('New Step');
}

private updateProject(newNodeId: string): void {
this.projectService.checkPotentialStartNodeIdChangeThenSaveProject().then(() => {
this.projectService.refreshProject();
// This timeout is used to allow steps to have time to apply background color if they are in a
// branch path
setTimeout(() => {
temporarilyHighlightElement(newNodeId);
});
});
}

private saveAndRefreshProject(): void {
this.projectService.saveProject();
this.projectService.refreshProject();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.step {
height: 50px;
padding: 4px;
margin: 4px 30px;
margin: 4px 10px 4px 30px;
border: 2px solid #dddddd;
border-radius: 6px;
position: relative;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,32 +75,50 @@
</button>
</div>
<div class="all-nodes-div">
<div *ngFor="let lesson of lessons">
<div *ngIf="lessons.length === 0" fxLayout="row" fxLayoutAlign="start center">
<div i18n>There are no lessons</div>
<add-lesson-button [active]="true"></add-lesson-button>
</div>
<div *ngFor="let lesson of lessons" fxLayout="row">
<project-authoring-lesson
[lesson]="lesson"
(selectNodeEvent)="selectNode($event)"
[showPosition]="true"
[projectId]="projectId"
[expanded]="lessonIdToExpanded()[lesson.id]"
(onExpandedChanged)="onExpandedChanged($event)"
fxFlex
></project-authoring-lesson>
<add-lesson-button
class="add-lesson-button-next-to-lesson"
[active]="true"
[lessonId]="lesson.id"
></add-lesson-button>
</div>
<div>
<h6 class="unused-header" i18n>Unused Lessons</h6>
<div *ngIf="inactiveGroupNodes.length === 0" i18n>There are no Unused Lessons</div>
<div *ngFor="let inactiveGroupNode of inactiveGroupNodes">
<div *ngIf="inactiveGroupNodes.length === 0" fxLayout="row" fxLayoutAlign="start center">
<div i18n>There are no unused lessons</div>
<add-lesson-button></add-lesson-button>
</div>
<div *ngFor="let inactiveGroupNode of inactiveGroupNodes" fxLayout="row">
<project-authoring-lesson
[lesson]="inactiveGroupNode"
(selectNodeEvent)="selectNode($event)"
[showPosition]="false"
[projectId]="projectId"
[expanded]="lessonIdToExpanded()[inactiveGroupNode.id]"
(onExpandedChanged)="onExpandedChanged($event)"
fxFlex
></project-authoring-lesson>
<add-lesson-button
class="add-lesson-button-next-to-lesson"
[lessonId]="inactiveGroupNode.id"
></add-lesson-button>
</div>
<div>
<h6 class="unused-header" i18n>Unused Steps</h6>
<div *ngIf="inactiveStepNodes.length === 0" i18n>There are no Unused Steps</div>
<div *ngIf="inactiveStepNodes.length === 0" i18n>There are no unused steps</div>
<ng-container *ngFor="let inactiveStepNode of inactiveStepNodes">
<project-authoring-step
*ngIf="getParentGroup(inactiveStepNode.id) == null"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,7 @@
.mat-icon {
margin: 0px;
}

.add-lesson-button-next-to-lesson {
margin-top: 20px;
}
Loading

0 comments on commit 67dd348

Please sign in to comment.