Skip to content

Commit

Permalink
chore(Authoring): Convert choose simulation to Angular
Browse files Browse the repository at this point in the history
  • Loading branch information
geoffreykwan committed Jul 24, 2023
1 parent e784b2a commit 078518f
Show file tree
Hide file tree
Showing 11 changed files with 362 additions and 56 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 @@ -29,6 +29,7 @@ import { NotebookAuthoringComponent } from '../../assets/wise5/authoringTool/not
import { StructureAuthoringModule } from '../../assets/wise5/authoringTool/structure/structure-authoring.module';
import { MilestonesAuthoringComponent } from '../../assets/wise5/authoringTool/milestones-authoring/milestones-authoring.component';
import { ChooseComponentLocationComponent } from '../../assets/wise5/authoringTool/node/chooseComponentLocation/choose-component-location.component';
import { ChooseSimulationComponent } from '../../assets/wise5/authoringTool/addNode/choose-simulation/choose-simulation.component';

@NgModule({
declarations: [
Expand All @@ -43,6 +44,7 @@ import { ChooseComponentLocationComponent } from '../../assets/wise5/authoringTo
ChooseNewComponent,
ChooseNewNodeLocation,
ChooseNewNodeTemplate,
ChooseSimulationComponent,
ConcurrentAuthorsMessageComponent,
MilestonesAuthoringComponent,
NodeAuthoringComponent,
Expand Down
8 changes: 3 additions & 5 deletions src/assets/wise5/authoringTool/addNode/addNodeModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import { ChooseNewNodeLocation } from './choose-new-node-location/choose-new-nod
import { ChooseNewNodeTemplate } from './choose-new-node-template/choose-new-node-template.component';
import AutomatedAssessmentChooseItemController from './automatedAssessment/automatedAssessmentChooseItemController';
import AutomatedAssessmentConfigureController from './automatedAssessment/automatedAssessmentConfigureController';
import SimulationChooseItemController from './simulation/simulationChooseItemController';
import { CardSelectorComponent } from '../components/card-selector/card-selector.component';
import { ChooseSimulationComponent } from './choose-simulation/choose-simulation.component';

export default angular
.module('addNodeModule', ['ui.router'])
.controller('AutomatedAssessmentChooseItemController', AutomatedAssessmentChooseItemController)
.controller('AutomatedAssessmentConfigureController', AutomatedAssessmentConfigureController)
.controller('SimulationChooseItemController', SimulationChooseItemController)
.directive('chooseSimulation', downgradeComponent({ component: ChooseSimulationComponent }))
.directive(
'addYourOwnNode',
downgradeComponent({ component: AddYourOwnNode }) as angular.IDirectiveFactory
Expand Down Expand Up @@ -90,9 +90,7 @@ export default angular
})
.state('root.at.project.add-node.simulation.choose-item', {
url: '/choose-item',
templateUrl: 'assets/wise5/authoringTool/addNode/simulation/choose-item.html',
controller: 'SimulationChooseItemController',
controllerAs: '$ctrl'
component: 'chooseSimulation'
});
}
]);
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<h5 i18n>Interactive Simulation</h5>
<p i18n>
Select from a curated library of interactive simulations addressing various science topics.
</p>
<div fxLayout="row wrap" fxLayoutAlign="start start" fxLayoutGap="10px">
<mat-form-field>
<mat-label i18n>Filter by Topic</mat-label>
<mat-select [(ngModel)]="selectedSubjects" (ngModelChange)="filter()" multiple>
<mat-option [value]="subject" *ngFor="let subject of subjects">{{ subject }}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-label i18n>Search</mat-label>
<input matInput [(ngModel)]="searchText" (ngModelChange)="filter()" />
</mat-form-field>
<button
mat-icon-button
(click)="clearFilters()"
*ngIf="searchText || selectedSubjects.length"
aria-label="Clear All"
i18n-aria-label
matTooltip="Clear All"
matTooltipPosition="above"
i18n-matTooltip
>
<mat-icon>clear</mat-icon>
</button>
<span class="num-items-found-message" i18n> {{ getNumItemsFound() }} Item(s) Found </span>
</div>
<card-selector
*ngIf="project != null"
[items]="filteredNodes"
[previewProjectUrl]="project.previewProjectURL"
(itemSelected)="itemSelected($event)"
>
</card-selector>
<hr />
<div fxLayout="row" fxLayoutGap="20px">
<button mat-raised-button color="primary" (click)="back()" aria-label="Back" i18n-aria-label i18n>
Back
</button>
<span fxFlex></span>
<button
mat-raised-button
color="primary"
(click)="cancel()"
aria-label="Cancel"
i18n-arial-label
i18n
>
Cancel
</button>
<button
mat-raised-button
color="primary"
[disabled]="selectedNode == null"
(click)="next()"
aria-label="Next"
i18n-aria-label
i18n
>
Next
</button>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.num-items-found-message {
margin-top: 14px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ChooseSimulationComponent } from './choose-simulation.component';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { UpgradeModule } from '@angular/upgrade/static';
import { TeacherProjectService } from '../../../services/teacherProjectService';
import { StudentTeacherCommonServicesModule } from '../../../../../app/student-teacher-common-services.module';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select';
import { FormsModule } from '@angular/forms';
import { MatInputModule } from '@angular/material/input';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

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

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ChooseSimulationComponent],
imports: [
BrowserAnimationsModule,
FormsModule,
HttpClientTestingModule,
MatFormFieldModule,
MatInputModule,
MatSelectModule,
StudentTeacherCommonServicesModule,
UpgradeModule
],
providers: [TeacherProjectService]
}).compileComponents();

TestBed.inject(UpgradeModule).$injector = {
get: () => {
return {
go: (route: string, params: any) => {}
};
}
};
TestBed.inject(TeacherProjectService);
fixture = TestBed.createComponent(ChooseSimulationComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { Component } from '@angular/core';
import { ConfigureStructureComponent } from '../../structure/configure-structure.component';
import { TeacherProjectService } from '../../../services/teacherProjectService';
import { HttpClient } from '@angular/common/http';
import { UpgradeModule } from '@angular/upgrade/static';

class SimulationNode {
metadata = {
subjects: []
};
type: string;
constructor(node: any) {
Object.assign(this, node);
}
}

@Component({
selector: 'choose-simulation',
templateUrl: './choose-simulation.component.html',
styleUrls: ['./choose-simulation.component.scss']
})
export class ChooseSimulationComponent extends ConfigureStructureComponent {
allNodes: SimulationNode[] = [];
filteredNodes: SimulationNode[] = [];
project: any;
projectItems: any;
searchText: string = '';
selectedNode: string;
selectedSubjects: string[] = [];
simulationProjectId: number;
subjects: string[] = [];

constructor(
http: HttpClient,
private projectService: TeacherProjectService,
protected upgrade: UpgradeModule
) {
super(http, upgrade);
}

ngOnInit(): void {
this.$state = this.upgrade.$injector.get('$state');
this.simulationProjectId = this.projectService.getSimulationProjectId();
this.showSimulationProject();
}

private showSimulationProject(): void {
this.projectService.retrieveProjectById(this.simulationProjectId).then((projectJSON) => {
this.project = projectJSON;
const nodeOrderOfProject = this.projectService.getNodeOrderOfProject(this.project);
this.projectItems = nodeOrderOfProject.nodes.slice(1); // remove root node from consideration
const allSubjects: string[] = [];
this.projectItems.forEach((item) => {
if (item.node.type !== 'group') {
const simulationNode = new SimulationNode(item.node);
this.allNodes.push(simulationNode);
allSubjects.push(...simulationNode.metadata.subjects);
}
});
this.filteredNodes = this.allNodes;
this.subjects = Array.from(new Set(allSubjects)).sort();
});
}

protected filter(): void {
this.filteredNodes = this.allNodes.filter((node: SimulationNode) => {
const isSearchTextFound = this.isSearchTextFound(this.searchText, JSON.stringify(node));
if (this.isAnySubjectChosen()) {
return isSearchTextFound && this.isSubjectFound(this.selectedSubjects, node);
}
return isSearchTextFound;
});
}

private isSearchTextFound(searchText: string, testText: string): boolean {
return testText.toLowerCase().includes(searchText.toLowerCase());
}

private isAnySubjectChosen(): boolean {
return this.selectedSubjects.length > 0;
}

private isSubjectFound(selectedSubjects: any[], resource: any): boolean {
for (const subject of selectedSubjects) {
if (resource.metadata.subjects.includes(subject)) {
return true;
}
}
return false;
}

protected clearFilters(): void {
this.searchText = '';
this.selectedSubjects = [];
this.filter();
}

protected getNumItemsFound(): number {
return this.filteredNodes.filter((node: SimulationNode) => {
return node.type != 'group';
}).length;
}

protected previewNode(node: any): void {
window.open(`${this.project.previewProjectURL}/${node.id}`);
}

protected back(): void {
this.$state.go('root.at.project.add-node.choose-template');
}

protected next(): void {
this.$state.go('root.at.project.import-step.choose-location', {
importFromProjectId: this.simulationProjectId,
selectedNodes: [this.selectedNode]
});
}

protected itemSelected(item: any): void {
this.selectedNode = item;
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
<div fxLayout="row wrap" fxLayout.xs="column" class="item-cards-container gray-lighter-bg">
<div fxFlex.sm="50" fxFlex.md="33" fxFlex.gt-md="25" *ngFor="let item of items">
<mat-card appearance="outlined" class="item-card" [ngStyle]="isItemSelected(item) && { border: '4px solid #00C853' }">
<mat-card
appearance="outlined"
class="item-card"
[ngStyle]="isItemSelected(item) && { border: '4px solid #00C853' }"
>
<mat-card-title class="item-card-title">
{{ item.title }}
</mat-card-title>
<div class="item-card-image" style="background-image: url('{{ item.thumbnail }}');"></div>
<mat-card-actions fxLayout="row" fxLayoutAlign="start center">
<mat-card-actions
class="item-card-actions"
fxLayout="row"
fxLayoutAlign="start center"
fxLayoutGap="10px"
>
<mat-icon
class="success"
aria-label="Selected"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,21 @@

.item-card-title {
font-size: 14px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding-left: 16px;
padding-right: 16px;
}

.item-card-image {
margin-left: -16px;
margin-right: -16px;
position: relative;
padding-top: 60%;
background-size: cover;
background-position: center;
}

.item-card-actions {
padding: 0px 16px 0px 16px !important;
}

.item-card-actions-spacer {
flex: 1 1 auto;
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';

@Component({
selector: 'app-card-selector',
selector: 'card-selector',
templateUrl: './card-selector.component.html',
styleUrls: ['./card-selector.component.scss']
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export abstract class ConfigureStructureComponent {
structure: any = {};
structureDir: string = 'assets/wise5/authoringTool/structure';

constructor(private http: HttpClient, private upgrade: UpgradeModule) {}
constructor(private http: HttpClient, protected upgrade: UpgradeModule) {}

ngOnInit(): void {
this.$state = this.upgrade.$injector.get('$state');
Expand Down
Loading

0 comments on commit 078518f

Please sign in to comment.