diff --git a/src/app/student/vle/student-vle.module.ts b/src/app/student/vle/student-vle.module.ts index 0a2bef0785c..d8d362121fd 100644 --- a/src/app/student/vle/student-vle.module.ts +++ b/src/app/student/vle/student-vle.module.ts @@ -14,7 +14,6 @@ import { ProjectService } from '../../../assets/wise5/services/projectService'; import { StudentDataService } from '../../../assets/wise5/services/studentDataService'; import { NavigationComponent } from '../../../assets/wise5/themes/default/navigation/navigation.component'; import { StepToolsComponent } from '../../../assets/wise5/themes/default/themeComponents/stepTools/step-tools.component'; -import { NodeModule } from '../../../assets/wise5/vle/node/node.module'; import { StudentAssetsDialogModule } from '../../../assets/wise5/vle/studentAsset/student-assets-dialog/student-assets-dialog.module'; import { VLEComponent } from '../../../assets/wise5/vle/vle.component'; import { VLEProjectService } from '../../../assets/wise5/vle/vleProjectService'; @@ -34,6 +33,7 @@ import { StudentPeerGroupService } from '../../../assets/wise5/services/studentP import { PeerGroupService } from '../../../assets/wise5/services/peerGroupService'; import { TopBarComponent } from '../top-bar/top-bar.component'; import { NodeStatusIconComponent } from '../../../assets/wise5/themes/default/themeComponents/nodeStatusIcon/node-status-icon.component'; +import { NodeComponent } from '../../../assets/wise5/vle/node/node.component'; @NgModule({ declarations: [ @@ -50,7 +50,7 @@ import { NodeStatusIconComponent } from '../../../assets/wise5/themes/default/th ComponentStudentModule, MatDialogModule, NavigationComponent, - NodeModule, + NodeComponent, NodeStatusIconComponent, RunEndedAndLockedMessageComponent, SimpleDialogModule, diff --git a/src/assets/wise5/vle/node/node.component.html b/src/assets/wise5/vle/node/node.component.html index 964a9dc845e..41f475c6b68 100644 --- a/src/assets/wise5/vle/node/node.component.html +++ b/src/assets/wise5/vle/node/node.component.html @@ -4,64 +4,64 @@ style="border-color: {{ nodeStatus?.icon?.color }}; position: relative;" fxLayout="row wrap" > -
- -
-
- -
+ @if (showRubric) { +
+ +
+ } + @for (component of components; track component.id) { +
+ @if (componentToVisible[component.id]) { + + } +
+ }
- - - + @if (node.showSaveButton) { + + } + @if (node.showSubmitButton) { + + } + @if (latestComponentState && (node.showSaveButton || node.showSubmitButton)) { + + }
diff --git a/src/assets/wise5/vle/node/node.component.spec.ts b/src/assets/wise5/vle/node/node.component.spec.ts index e2c417e2754..870427abb14 100644 --- a/src/assets/wise5/vle/node/node.component.spec.ts +++ b/src/assets/wise5/vle/node/node.component.spec.ts @@ -1,6 +1,4 @@ -import { provideHttpClientTesting } from '@angular/common/http/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { MatDialogModule } from '@angular/material/dialog'; import { ConfigService } from '../../services/configService'; import { StudentDataService } from '../../services/studentDataService'; import { VLEProjectService } from '../vleProjectService'; @@ -15,9 +13,8 @@ let fixture: ComponentFixture; describe('NodeComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [NodeComponent], - imports: [MatDialogModule, StudentTeacherCommonServicesModule], - providers: [provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()] + imports: [NodeComponent, StudentTeacherCommonServicesModule], + providers: [provideHttpClient(withInterceptorsFromDi())] }).compileComponents(); }); diff --git a/src/assets/wise5/vle/node/node.component.ts b/src/assets/wise5/vle/node/node.component.ts index 73527ab00df..cc4e3beef94 100644 --- a/src/assets/wise5/vle/node/node.component.ts +++ b/src/assets/wise5/vle/node/node.component.ts @@ -13,29 +13,41 @@ import { SessionService } from '../../services/sessionService'; import { StudentDataService } from '../../services/studentDataService'; import { VLEProjectService } from '../vleProjectService'; import { copy } from '../../common/object/object'; +import { CommonModule } from '@angular/common'; +import { FlexLayoutModule } from '@angular/flex-layout'; +import { ComponentComponent } from '../../components/component/component.component'; +import { MatButtonModule } from '@angular/material/button'; +import { ComponentStateInfoComponent } from '../../common/component-state-info/component-state-info.component'; +import { HelpIconComponent } from '../../themes/default/themeComponents/helpIcon/help-icon.component'; @Component({ + imports: [ + CommonModule, + ComponentComponent, + ComponentStateInfoComponent, + FlexLayoutModule, + HelpIconComponent, + MatButtonModule + ], selector: 'node', - templateUrl: './node.component.html', - styleUrls: ['./node.component.scss'] + standalone: true, + styleUrl: './node.component.scss', + templateUrl: './node.component.html' }) export class NodeComponent implements OnInit { - autoSaveInterval: number = 60000; // in milliseconds; - autoSaveIntervalId: any; - components: any[]; - componentToVisible = {}; - dirtyComponentIds: any = []; - dirtySubmitComponentIds: any = []; - isDisabled: boolean; + private autoSaveInterval: number = 60000; // in milliseconds; + private autoSaveIntervalId: any; + protected components: any[]; + protected componentToVisible = {}; + protected dirtyComponentIds: any = []; + protected dirtySubmitComponentIds: any = []; + protected disabled: boolean; + protected latestComponentState: ComponentState; @Input() node: Node; - nodeContent: any; - nodeStatus: any; - latestComponentState: ComponentState; - showRubric: boolean; - submit: boolean = false; - subscriptions: Subscription = new Subscription(); - teacherWorkgroupId: number; - workComponents: string[] = [ + protected nodeStatus: any; + protected showRubric: boolean; + private subscriptions: Subscription = new Subscription(); + private workComponents: string[] = [ 'Animation', 'AudioOscillator', 'ConceptMap', @@ -52,7 +64,7 @@ export class NodeComponent implements OnInit { 'Summary', 'Table' ]; - workgroupId: number; + protected workgroupId: number; constructor( private componentService: ComponentService, @@ -72,8 +84,7 @@ export class NodeComponent implements OnInit { ngOnInit(): void { this.workgroupId = this.configService.getWorkgroupId(); - this.teacherWorkgroupId = this.configService.getTeacherWorkgroupId(); - this.isDisabled = !this.configService.isRunActive(); + this.disabled = !this.configService.isRunActive(); this.initializeNode(); this.startAutoSaveInterval(); @@ -82,8 +93,7 @@ export class NodeComponent implements OnInit { this.subscriptions.add( this.studentDataService.componentSaveTriggered$.subscribe(({ nodeId, componentId }) => { if (nodeId == this.node.id && this.node.hasComponent(componentId)) { - const isAutoSave = false; - this.createAndSaveComponentData(isAutoSave, componentId); + this.createAndSaveComponentData(false, componentId); } }) ); @@ -91,9 +101,7 @@ export class NodeComponent implements OnInit { this.subscriptions.add( this.studentDataService.componentSubmitTriggered$.subscribe(({ nodeId, componentId }) => { if (nodeId == this.node.id && this.node.hasComponent(componentId)) { - const isAutoSave = false; - const isSubmit = true; - this.createAndSaveComponentData(isAutoSave, componentId, isSubmit); + this.createAndSaveComponentData(false, componentId, true); } }) ); @@ -155,9 +163,8 @@ export class NodeComponent implements OnInit { ); } - initializeNode(): void { + private initializeNode(): void { this.clearLatestComponentState(); - this.nodeContent = this.projectService.getNodeById(this.node.id); this.components = this.getComponents(); this.nodeStatus = this.nodeStatusService.getNodeStatusByNodeId(this.node.id); this.dirtyComponentIds = []; @@ -178,7 +185,8 @@ export class NodeComponent implements OnInit { this.showRubric = this.node.rubric != null && this.node.rubric != ''; } - const script = this.nodeContent.script; + const nodeContent = this.projectService.getNodeById(this.node.id); + const script = nodeContent.script; if (script != null) { this.projectService.retrieveScript(script).then((script: string) => { new Function(script).call(this); @@ -198,21 +206,18 @@ export class NodeComponent implements OnInit { this.subscriptions.unsubscribe(); } - saveButtonClicked(): void { - const isAutoSave = false; - this.createAndSaveComponentData(isAutoSave); + protected save(): void { + this.createAndSaveComponentData(false); } - submitButtonClicked(): void { + protected submit(): void { this.nodeService.broadcastNodeSubmitClicked({ nodeId: this.node.id }); - const isAutoSave = false; - const isSubmit = true; - this.createAndSaveComponentData(isAutoSave, null, isSubmit); + this.createAndSaveComponentData(false, null, true); } private getComponents(): any[] { return this.node.components.map((component) => { - if (this.isDisabled) { + if (this.disabled) { component.isDisabled = true; } return component; @@ -226,8 +231,7 @@ export class NodeComponent implements OnInit { private startAutoSaveInterval(): void { this.autoSaveIntervalId = setInterval(() => { if (this.dirtyComponentIds.length) { - const isAutoSave = true; - this.createAndSaveComponentData(isAutoSave); + this.createAndSaveComponentData(true); } }, this.autoSaveInterval); } @@ -247,7 +251,7 @@ export class NodeComponent implements OnInit { * that needs saving */ private createAndSaveComponentData( - isAutoSave, + isAutoSave: boolean, componentId = null, isSubmit = null ): Promise { @@ -256,7 +260,11 @@ export class NodeComponent implements OnInit { ); } - private createComponentStatesResponseHandler(isAutoSave, componentId = null, isSubmit = null) { + private createComponentStatesResponseHandler( + isAutoSave: boolean, + componentId: string = null, + isSubmit: boolean = null + ) { return (componentStates) => { const componentAnnotations = this.getAnnotationsFromComponentStates(componentStates); componentStates.forEach((componentState: any) => { @@ -400,7 +408,7 @@ export class NodeComponent implements OnInit { ): any { componentState.runId = this.configService.getRunId(); componentState.periodId = this.configService.getPeriodId(); - componentState.workgroupId = this.configService.getWorkgroupId(); + componentState.workgroupId = this.workgroupId; componentState.isAutoSave = isAutoSave === true; componentState.isSubmit ??= isSubmit; } @@ -429,7 +437,7 @@ export class NodeComponent implements OnInit { } } - getComponentStateByComponentId(componentId: string): any { + protected getComponentStateByComponentId(componentId: string): any { return this.studentDataService.getLatestComponentStateByNodeIdAndComponentId( this.node.id, componentId @@ -444,7 +452,7 @@ export class NodeComponent implements OnInit { ); } - saveComponentState($event: any): Promise { + protected saveComponentState($event: any): Promise { return Promise.all([$event.componentStatePromise]).then( this.createComponentStatesResponseHandler(true) ); diff --git a/src/assets/wise5/vle/node/node.module.ts b/src/assets/wise5/vle/node/node.module.ts deleted file mode 100644 index 595ca836fbc..00000000000 --- a/src/assets/wise5/vle/node/node.module.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { FlexLayoutModule } from '@angular/flex-layout'; -import { MatButtonModule } from '@angular/material/button'; -import { MatIconModule } from '@angular/material/icon'; -import { NodeComponent } from './node.component'; -import { HelpIconComponent } from '../../themes/default/themeComponents/helpIcon/help-icon.component'; -import { ComponentStudentModule } from '../../components/component/component-student.module'; -import { MatTooltipModule } from '@angular/material/tooltip'; -import { ComponentStateInfoComponent } from '../../common/component-state-info/component-state-info.component'; - -@NgModule({ - declarations: [NodeComponent], - imports: [ - CommonModule, - ComponentStateInfoComponent, - ComponentStudentModule, - FlexLayoutModule, - HelpIconComponent, - MatButtonModule, - MatIconModule, - MatTooltipModule - ], - exports: [NodeComponent] -}) -export class NodeModule {} diff --git a/src/assets/wise5/vle/vle.component.html b/src/assets/wise5/vle/vle.component.html index 95c1b0256b5..865e1e64429 100644 --- a/src/assets/wise5/vle/vle.component.html +++ b/src/assets/wise5/vle/vle.component.html @@ -28,7 +28,9 @@ [ngClass]="{ 'nav-view': layoutState === 'nav', 'node-view': layoutState === 'node' }" > - + @if (layoutState === 'node') { + + } @@ -42,7 +44,9 @@
- + @if (layoutState === 'node') { + + }
diff --git a/src/assets/wise5/vle/vle.component.spec.ts b/src/assets/wise5/vle/vle.component.spec.ts index b619474760e..fd2cdcfde55 100644 --- a/src/assets/wise5/vle/vle.component.spec.ts +++ b/src/assets/wise5/vle/vle.component.spec.ts @@ -39,7 +39,7 @@ let saveVLEEventSpy: jasmine.Spy; describe('VLEComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [NodeComponent, NotebookNotesComponent, SafeUrl, VLEComponent], + declarations: [NotebookNotesComponent, SafeUrl, VLEComponent], imports: [ BrowserAnimationsModule, FormsModule, @@ -53,6 +53,7 @@ describe('VLEComponent', () => { MatSelectModule, MatSidenavModule, NavigationComponent, + NodeComponent, NodeIconComponent, NodeStatusIconComponent, StepToolsComponent, diff --git a/src/messages.xlf b/src/messages.xlf index 59982d2fe1d..4c0f0dc2329 100644 --- a/src/messages.xlf +++ b/src/messages.xlf @@ -6489,10 +6489,6 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.src/assets/wise5/themes/default/notebook/edit-notebook-item-dialog/edit-notebook-item-dialog.component.html 80,82 - - src/assets/wise5/vle/node/node.component.html - 46,48 - Team hasn't worked on yet. @@ -13589,7 +13585,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/assets/wise5/vle/node/node.component.html - 13 + 9 @@ -15372,7 +15368,7 @@ Are you sure you want to proceed? src/assets/wise5/vle/node/node.component.html - 43 + 42 @@ -22258,7 +22254,14 @@ If this problem continues, let your teacher know and move on to the next activit 20 - + + Save + + src/assets/wise5/vle/node/node.component.html + 45,47 + + + Submit src/assets/wise5/vle/node/node.component.html