Skip to content

Commit

Permalink
feat(AddStepButton): New add step button menu option behavior (#1997)
Browse files Browse the repository at this point in the history
  • Loading branch information
hirokiterashima authored Nov 20, 2024
1 parent c303da8 commit badf97b
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@
</button>
<mat-menu #lessonMenu="matMenu">
<button mat-menu-item (click)="addFirstLesson()">
<mat-icon>add_circle</mat-icon><span i18n>Add lesson before</span>
<mat-icon class="rotate-180 flip-vertical">subdirectory_arrow_left</mat-icon
><span i18n>Add lesson before</span>
</button>
<button mat-menu-item (click)="goToAddLessonView(lessonId)">
<mat-icon>add_circle</mat-icon><span i18n>Add lesson after</span>
<mat-icon>subdirectory_arrow_left</mat-icon><span i18n>Add lesson after</span>
</button>
</mat-menu>
</ng-container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,20 @@ import { MatTooltipModule } from '@angular/material/tooltip';
import { ActivatedRoute, Router } from '@angular/router';

@Component({
imports: [CommonModule, MatButtonModule, MatIconModule, MatMenuModule, MatTooltipModule],
selector: 'add-lesson-button',
templateUrl: './add-lesson-button.component.html',
standalone: true,
imports: [CommonModule, MatButtonModule, MatIconModule, MatMenuModule, MatTooltipModule]
styles: [
`
.rotate-180 {
transform: rotate(180deg);
}
.flip-vertical {
transform: scaleY(-1);
}
`
],
templateUrl: './add-lesson-button.component.html'
})
export class AddLessonButtonComponent {
@Input() active: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,23 @@
matTooltip="Add step"
matTooltipPosition="above"
i18n-matTooltip
[disabled]="!canAddBefore && !canAddAfter && !canBranch"
>
<mat-icon>add_circle</mat-icon>
</button>
<mat-menu #step="matMenu">
@if (!branchMergePoint) {
@if (canAddBefore) {
<button mat-menu-item (click)="addStepBefore()">
<mat-icon class="rotate-180 flip-vertical">subdirectory_arrow_left</mat-icon
><span i18n>Add step before</span>
</button>
}
@if (!branchPoint) {
@if (canAddAfter) {
<button mat-menu-item (click)="goToAddStepViewForAfter(nodeId)">
<mat-icon>subdirectory_arrow_left</mat-icon><span i18n>Add step after</span>
</button>
}
@if (!branchPoint && !branchPathStep) {
@if (canBranch) {
<button mat-menu-item (click)="goToCreateBranchView()">
<mat-icon class="rotate-180">call_split</mat-icon><span i18n>Branch off this step</span>
</button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,129 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AddStepButtonComponent } from './add-step-button.component';
import { TeacherProjectService } from '../../services/teacherProjectService';
import { StudentTeacherCommonServicesModule } from '../../../../app/student-teacher-common-services.module';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { MatIconModule } from '@angular/material/icon';
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { provideRouter } from '@angular/router';

let teacherProjectService: TeacherProjectService;
import { ActivatedRoute, Router } from '@angular/router';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatButtonHarness } from '@angular/material/button/testing';
import { MatMenuHarness } from '@angular/material/menu/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { AddStepTarget } from '../../../../app/domain/addStepTarget';

describe('AddStepButtonComponent', () => {
let component: AddStepButtonComponent;
let fixture: ComponentFixture<AddStepButtonComponent>;
let loader: HarnessLoader;
let projectServiceSpy: jasmine.SpyObj<TeacherProjectService>;
let routerSpy: jasmine.SpyObj<Router>;
let route: ActivatedRoute;

beforeEach(async () => {
projectServiceSpy = jasmine.createSpyObj('TeacherProjectService', [
'isFirstStepInLesson',
'isBranchPoint',
'isNodeInAnyBranchPath',
'getParentGroupId',
'getNodesByToNodeId',
'isFirstNodeInBranchPath'
]);
routerSpy = jasmine.createSpyObj('Router', ['navigate']);

beforeEach(() => {
TestBed.configureTestingModule({
imports: [AddStepButtonComponent, MatIconModule, StudentTeacherCommonServicesModule],
await TestBed.configureTestingModule({
imports: [AddStepButtonComponent, NoopAnimationsModule],
providers: [
TeacherProjectService,
provideHttpClient(withInterceptorsFromDi()),
provideHttpClientTesting(),
provideRouter([])
{ provide: TeacherProjectService, useValue: projectServiceSpy },
{ provide: Router, useValue: routerSpy },
{ provide: ActivatedRoute, useValue: {} }
]
});
teacherProjectService = TestBed.inject(TeacherProjectService);
spyOn(teacherProjectService, 'isBranchMergePoint').and.returnValue(false);
}).compileComponents();

route = TestBed.inject(ActivatedRoute);
fixture = TestBed.createComponent(AddStepButtonComponent);
component = fixture.componentInstance;
fixture.detectChanges();
loader = TestbedHarnessEnvironment.loader(fixture);
component.nodeId = 'node1';
});

it('should create', () => {
expect(component).toBeTruthy();
});

it('should disable button when no actions are available', async () => {
projectServiceSpy.isFirstStepInLesson.and.returnValue(false);
projectServiceSpy.isBranchPoint.and.returnValue(true);
projectServiceSpy.isNodeInAnyBranchPath.and.returnValue(true);
fixture.detectChanges();

const button = await loader.getHarness(MatButtonHarness);
expect(await button.isDisabled()).toBeTruthy();
});

it('should show all menu items when all actions are available', async () => {
projectServiceSpy.isFirstStepInLesson.and.returnValue(true);
projectServiceSpy.isBranchPoint.and.returnValue(false);
projectServiceSpy.isNodeInAnyBranchPath.and.returnValue(false);
fixture.detectChanges();

const button = await loader.getHarness(MatButtonHarness);
await button.click();

const menu = await loader.getHarness(MatMenuHarness);
const items = await menu.getItems();
expect(items.length).toBe(3);
});

it('should navigate to add step before view when first in lesson', async () => {
projectServiceSpy.isFirstStepInLesson.and.returnValue(true);
projectServiceSpy.getParentGroupId.and.returnValue('group1');
fixture.detectChanges();

const button = await loader.getHarness(MatButtonHarness);
await button.click();
const menu = await loader.getHarness(MatMenuHarness);
const items = await menu.getItems();
expect(items.length).toBe(3);
await items[0].click();

expect(routerSpy.navigate).toHaveBeenCalledWith(['add-node', 'choose-template'], {
relativeTo: route,
state: jasmine.any(AddStepTarget)
});
});

it('should navigate to add step after view', async () => {
projectServiceSpy.isFirstStepInLesson.and.returnValue(false);
projectServiceSpy.isBranchPoint.and.returnValue(false);
fixture.detectChanges();

const button = await loader.getHarness(MatButtonHarness);
await button.click();
const menu = await loader.getHarness(MatMenuHarness);
const items = await menu.getItems();
expect(items.length).toBe(2);
await items[0].click();

expect(routerSpy.navigate).toHaveBeenCalledWith(['add-node', 'choose-template'], {
relativeTo: route,
state: jasmine.any(AddStepTarget)
});
});

it('should navigate to create branch view', async () => {
projectServiceSpy.isFirstStepInLesson.and.returnValue(false);
projectServiceSpy.isBranchPoint.and.returnValue(false);
projectServiceSpy.isNodeInAnyBranchPath.and.returnValue(false);
fixture.detectChanges();

const button = await loader.getHarness(MatButtonHarness);
await button.click();
const menu = await loader.getHarness(MatMenuHarness);
const items = await menu.getItems();
expect(items.length).toBe(2);
await items[1].click();

expect(routerSpy.navigate).toHaveBeenCalledWith(['create-branch'], {
relativeTo: route,
state: { targetId: 'node1' }
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { MatMenuModule } from '@angular/material/menu';
import { AddStepTarget } from '../../../../app/domain/addStepTarget';

@Component({
imports: [CommonModule, MatButtonModule, MatIconModule, MatMenuModule, MatTooltipModule],
selector: 'add-step-button',
templateUrl: './add-step-button.component.html',
standalone: true,
styles: [
`
Expand All @@ -22,12 +22,12 @@ import { AddStepTarget } from '../../../../app/domain/addStepTarget';
}
`
],
imports: [CommonModule, MatButtonModule, MatIconModule, MatMenuModule, MatTooltipModule]
templateUrl: './add-step-button.component.html'
})
export class AddStepButtonComponent {
protected branchMergePoint: boolean;
protected branchPathStep: boolean;
protected branchPoint: boolean;
protected canAddAfter: boolean;
protected canAddBefore: boolean;
protected canBranch: boolean;
@Input() nodeId: string;

constructor(
Expand All @@ -37,9 +37,11 @@ export class AddStepButtonComponent {
) {}

ngOnInit(): void {
this.branchPoint = this.projectService.isBranchPoint(this.nodeId);
this.branchPathStep = this.projectService.isNodeInAnyBranchPath(this.nodeId);
this.branchMergePoint = this.projectService.isBranchMergePoint(this.nodeId);
this.canAddBefore = this.projectService.isFirstStepInLesson(this.nodeId);
const isBranchPoint = this.projectService.isBranchPoint(this.nodeId);
const isBranchPathStep = this.projectService.isNodeInAnyBranchPath(this.nodeId);
this.canAddAfter = !isBranchPoint;
this.canBranch = !(isBranchPoint || isBranchPathStep);
}

protected addStepBefore(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
[projectId]="projectId"
fxFlex
></project-authoring-step>
<add-step-button [nodeId]="childId"></add-step-button>
<add-step-button [nodeId]="childId" />
</div>
<div *ngIf="lesson.ids.length === 0" class="no-steps-message" fxLayoutAlign="start center">
<div i18n>This lesson has no steps</div>
Expand Down
12 changes: 6 additions & 6 deletions src/messages.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -9422,18 +9422,18 @@ Click &quot;Cancel&quot; to keep the invalid JSON open so you can fix it.</sourc
<source>Add lesson before</source>
<context-group purpose="location">
<context context-type="sourcefile">src/assets/wise5/authoringTool/add-lesson-button/add-lesson-button.component.html</context>
<context context-type="linenumber">28</context>
<context context-type="linenumber">29</context>
</context-group>
</trans-unit>
<trans-unit id="7c096031ae7c24c22f80edb62bd25896a4cbd2e6" datatype="html">
<source>Add lesson after</source>
<context-group purpose="location">
<context context-type="sourcefile">src/assets/wise5/authoringTool/add-lesson-button/add-lesson-button.component.html</context>
<context context-type="linenumber">31</context>
<context context-type="linenumber">32</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/assets/wise5/authoringTool/add-lesson-button/add-lesson-button.component.html</context>
<context context-type="linenumber">40</context>
<context context-type="linenumber">41</context>
</context-group>
</trans-unit>
<trans-unit id="372e176e8ed50173e0caa989d8c5b7ff750c4d58" datatype="html">
Expand Down Expand Up @@ -9518,21 +9518,21 @@ Click &quot;Cancel&quot; to keep the invalid JSON open so you can fix it.</sourc
<source>Add step before</source>
<context-group purpose="location">
<context context-type="sourcefile">src/assets/wise5/authoringTool/add-step-button/add-step-button.component.html</context>
<context context-type="linenumber">16</context>
<context context-type="linenumber">17</context>
</context-group>
</trans-unit>
<trans-unit id="d59263511cd8dbe0a1eb9bd829aac8d827d8fd83" datatype="html">
<source>Add step after</source>
<context-group purpose="location">
<context context-type="sourcefile">src/assets/wise5/authoringTool/add-step-button/add-step-button.component.html</context>
<context context-type="linenumber">21</context>
<context context-type="linenumber">22</context>
</context-group>
</trans-unit>
<trans-unit id="66a796ca959149529fa803f5ffa9cad29b5c5c5a" datatype="html">
<source>Branch off this step</source>
<context-group purpose="location">
<context context-type="sourcefile">src/assets/wise5/authoringTool/add-step-button/add-step-button.component.html</context>
<context context-type="linenumber">26</context>
<context context-type="linenumber">27</context>
</context-group>
</trans-unit>
<trans-unit id="8608bcf1ea8ff554000e0ac4337e7afd3cf5c3f3" datatype="html">
Expand Down

0 comments on commit badf97b

Please sign in to comment.