From 5ceb19503169f56b485b5da3a33d06ab9c730efe Mon Sep 17 00:00:00 2001 From: Hiroki Terashima Date: Mon, 16 Dec 2024 11:03:29 -0800 Subject: [PATCH] feat(NodeAuthoring): Toggle Edit/Preview component (#1994) Co-authored-by: Jonathan Lim-Breitbart --- src/app/student-teacher-common.module.ts | 2 + src/app/teacher/authoring-routing.module.ts | 5 - src/app/teacher/authoring-tool.module.ts | 4 - .../authoring-tool.component.html | 1 + .../component-authoring.component.ts | 88 +++--- .../edit-component.component.spec.ts | 75 +++++ .../edit-component.component.ts | 47 ++++ .../preview-component-button.component.html | 10 - .../preview-component-button.component.ts | 31 -- .../preview-component.component.ts | 15 +- .../concurrent-authors-message.component.html | 8 +- ...ncurrent-authors-message.component.spec.ts | 3 - .../concurrent-authors-message.component.ts | 3 +- .../add-component-button.component.html | 41 ++- .../add-component-button.component.spec.ts | 3 +- .../add-component-button.component.ts | 38 ++- .../choose-component-location.component.html | 51 ---- ...hoose-component-location.component.spec.ts | 57 ---- .../choose-component-location.component.ts | 94 ------- .../node-authoring.component.html | 264 ++++++++---------- .../node-authoring.component.scss | 89 +++--- .../node-authoring.component.spec.ts | 52 +--- .../node-authoring.component.ts | 160 +++-------- .../project-authoring-parent.component.scss | 1 - src/assets/wise5/common/dom/dom.ts | 26 +- .../component/component.component.html | 4 +- .../draw-show-work.component.ts | 1 + .../draw-student/draw-student.component.ts | 8 +- .../wise5/components/draw/drawService.ts | 16 +- src/assets/wise5/vle/node/node.component.scss | 4 + src/messages.xlf | 240 +++++----------- 31 files changed, 552 insertions(+), 889 deletions(-) create mode 100644 src/assets/wise5/authoringTool/components/edit-component/edit-component.component.spec.ts create mode 100644 src/assets/wise5/authoringTool/components/edit-component/edit-component.component.ts delete mode 100644 src/assets/wise5/authoringTool/components/preview-component-button/preview-component-button.component.html delete mode 100644 src/assets/wise5/authoringTool/components/preview-component-button/preview-component-button.component.ts delete mode 100644 src/assets/wise5/authoringTool/node/chooseComponentLocation/choose-component-location.component.html delete mode 100644 src/assets/wise5/authoringTool/node/chooseComponentLocation/choose-component-location.component.spec.ts delete mode 100644 src/assets/wise5/authoringTool/node/chooseComponentLocation/choose-component-location.component.ts diff --git a/src/app/student-teacher-common.module.ts b/src/app/student-teacher-common.module.ts index 4e20d967cdf..a40d3e482b4 100644 --- a/src/app/student-teacher-common.module.ts +++ b/src/app/student-teacher-common.module.ts @@ -39,6 +39,7 @@ import { MathModule } from './math/math.module'; import { MatMenuModule } from '@angular/material/menu'; import { MainMenuComponent } from '../assets/wise5/common/main-menu/main-menu.component'; import { SideMenuComponent } from '../assets/wise5/common/side-menu/side-menu.component'; +import { ScrollingModule } from '@angular/cdk/scrolling'; @NgModule({ declarations: [ @@ -82,6 +83,7 @@ import { SideMenuComponent } from '../assets/wise5/common/side-menu/side-menu.co NodeStatusIconComponent, NotebookModule, ReactiveFormsModule, + ScrollingModule, StudentTeacherCommonServicesModule ], exports: [ diff --git a/src/app/teacher/authoring-routing.module.ts b/src/app/teacher/authoring-routing.module.ts index 01ad5a06775..9390f4f4e99 100644 --- a/src/app/teacher/authoring-routing.module.ts +++ b/src/app/teacher/authoring-routing.module.ts @@ -9,7 +9,6 @@ import { ProjectAuthoringComponent } from '../../assets/wise5/authoringTool/proj import { NodeAuthoringComponent } from '../../assets/wise5/authoringTool/node/node-authoring/node-authoring.component'; import { NodeAdvancedAuthoringComponent } from '../../assets/wise5/authoringTool/node/advanced/node-advanced-authoring/node-advanced-authoring.component'; import { NodeAdvancedConstraintAuthoringComponent } from '../../assets/wise5/authoringTool/node/advanced/constraint/node-advanced-constraint-authoring.component'; -import { ChooseComponentLocationComponent } from '../../assets/wise5/authoringTool/node/chooseComponentLocation/choose-component-location.component'; import { AddLessonConfigureComponent } from '../../assets/wise5/authoringTool/addLesson/add-lesson-configure/add-lesson-configure.component'; import { ChooseNewNodeTemplateComponent } from '../../assets/wise5/authoringTool/addNode/choose-new-node-template/choose-new-node-template.component'; import { AddYourOwnNodeComponent } from '../../assets/wise5/authoringTool/addNode/add-your-own-node/add-your-own-node.component'; @@ -153,10 +152,6 @@ const routes: Routes = [ { path: 'rubric', component: EditNodeRubricComponent } ] }, - { - path: 'choose-component-location', - component: ChooseComponentLocationComponent - }, { path: 'import-component', children: [{ path: 'choose-component', component: ChooseImportComponentComponent }] diff --git a/src/app/teacher/authoring-tool.module.ts b/src/app/teacher/authoring-tool.module.ts index 495cc9c3a2b..3095e1714f5 100644 --- a/src/app/teacher/authoring-tool.module.ts +++ b/src/app/teacher/authoring-tool.module.ts @@ -22,7 +22,6 @@ import { WiseTinymceEditorModule } from '../../assets/wise5/directives/wise-tiny import { NotebookAuthoringComponent } from '../../assets/wise5/authoringTool/notebook-authoring/notebook-authoring.component'; 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 { TopBarComponent } from '../../assets/wise5/authoringTool/components/top-bar/top-bar.component'; import { ProjectAssetAuthoringModule } from '../../assets/wise5/authoringTool/project-asset-authoring/project-asset-authoring.module'; import { ChooseSimulationComponent } from '../../assets/wise5/authoringTool/addNode/choose-simulation/choose-simulation.component'; @@ -57,7 +56,6 @@ import { TranslatableTextareaComponent } from '../../assets/wise5/authoringTool/ import { TranslatableRichTextEditorComponent } from '../../assets/wise5/authoringTool/components/translatable-rich-text-editor/translatable-rich-text-editor.component'; import { AddStepButtonComponent } from '../../assets/wise5/authoringTool/add-step-button/add-step-button.component'; import { CreateBranchComponent } from '../../assets/wise5/authoringTool/create-branch/create-branch.component'; -import { PreviewComponentButtonComponent } from '../../assets/wise5/authoringTool/components/preview-component-button/preview-component-button.component'; import { EditBranchComponent } from '../../assets/wise5/authoringTool/edit-branch/edit-branch.component'; import { ComponentTypeButtonComponent } from '../../assets/wise5/authoringTool/components/component-type-button/component-type-button.component'; import { MatExpansionModule } from '@angular/material/expansion'; @@ -92,7 +90,6 @@ import { MatExpansionModule } from '@angular/material/expansion'; AddYourOwnNodeComponent, AuthoringToolBarComponent, ChooseAutomatedAssessmentComponent, - ChooseComponentLocationComponent, ChooseCopyNodeLocationComponent, ChooseImportStepComponent, ChooseImportUnitComponent, @@ -116,7 +113,6 @@ import { MatExpansionModule } from '@angular/material/expansion'; NodeAdvancedAuthoringModule, NodeIconAndTitleComponent, NodeWithMoveAfterButtonComponent, - PreviewComponentButtonComponent, ProjectAssetAuthoringModule, ProjectListComponent, RouterModule, diff --git a/src/assets/wise5/authoringTool/authoring-tool.component.html b/src/assets/wise5/authoringTool/authoring-tool.component.html index 89fadb859ce..8ba0b3ba39d 100644 --- a/src/assets/wise5/authoringTool/authoring-tool.component.html +++ b/src/assets/wise5/authoringTool/authoring-tool.component.html @@ -23,6 +23,7 @@ class="l-main" [ngClass]="{ 'l-main--with-toolbar': showToolbar }" role="main" + cdkScrollable > diff --git a/src/assets/wise5/authoringTool/components/component-authoring.component.ts b/src/assets/wise5/authoringTool/components/component-authoring.component.ts index 322b7f10a3b..b9c150747d8 100644 --- a/src/assets/wise5/authoringTool/components/component-authoring.component.ts +++ b/src/assets/wise5/authoringTool/components/component-authoring.component.ts @@ -1,45 +1,65 @@ -import { - ApplicationRef, - Component, - ComponentRef, - ElementRef, - EnvironmentInjector, - Input, - ViewChild, - createComponent -} from '@angular/core'; +import { Component, EventEmitter, Input, Output } from '@angular/core'; import { ComponentContent } from '../../common/ComponentContent'; -import { components } from '../../components/Components'; +import { PreviewComponentComponent } from './preview-component/preview-component.component'; +import { EditComponentComponent } from './edit-component/edit-component.component'; +import { ComponentFactory } from '../../common/ComponentFactory'; +import { Component as WISEComponent } from '../../common/Component'; +import { TeacherProjectService } from '../../services/teacherProjectService'; +import { MatTooltipModule } from '@angular/material/tooltip'; @Component({ + imports: [PreviewComponentComponent, EditComponentComponent, MatTooltipModule], selector: 'component-authoring', standalone: true, - template: '
' + styles: [ + ` + preview-component { + display: block; + position: relative; + cursor: pointer; + } + preview-component:hover { + outline: 3px dashed #aaaaaa; + outline-offset: 8px; + } + preview-component:after { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + } + ` + ], + template: `@if (editing) { + + } @else { + + }` }) export class ComponentAuthoringComponent { - @Input() private componentContent: ComponentContent; - @ViewChild('component') private componentElementRef: ElementRef; - private componentRef: ComponentRef; - @Input() private nodeId: string; + protected component: WISEComponent; + @Input() componentContent: ComponentContent; + @Input() editing: boolean; + @Output() editComponentEvent: EventEmitter = new EventEmitter(); + @Input() nodeId: string; - constructor( - private applicationRef: ApplicationRef, - private injector: EnvironmentInjector - ) {} + constructor(private projectService: TeacherProjectService) {} - ngAfterViewInit(): void { - this.componentRef = createComponent(components[this.componentContent.type].authoring, { - hostElement: this.componentElementRef.nativeElement, - environmentInjector: this.injector - }); - Object.assign(this.componentRef.instance, { - componentContent: this.componentContent, - nodeId: this.nodeId - }); - this.applicationRef.attachView(this.componentRef.hostView); - } - - ngOnDestroy(): void { - this.componentRef.destroy(); + ngOnChanges(): void { + this.component = new ComponentFactory().getComponent( + this.projectService.injectAssetPaths(this.componentContent), + this.nodeId + ); } } diff --git a/src/assets/wise5/authoringTool/components/edit-component/edit-component.component.spec.ts b/src/assets/wise5/authoringTool/components/edit-component/edit-component.component.spec.ts new file mode 100644 index 00000000000..ce7bc1a4c36 --- /dev/null +++ b/src/assets/wise5/authoringTool/components/edit-component/edit-component.component.spec.ts @@ -0,0 +1,75 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { EditComponentComponent } from './edit-component.component'; +import { Component } from '@angular/core'; +import { components } from '../../../components/Components'; +import { ComponentContent } from '../../../common/ComponentContent'; + +@Component({ + selector: 'mock-authoring', + template: '
Mock Authoring Component
' +}) +class MockAuthoringComponent { + componentContent: any; + nodeId: string; +} + +describe('EditComponentComponent', () => { + let component: EditComponentComponent; + let fixture: ComponentFixture; + const mockComponentContent = { + type: 'mockComponent' + }; + const mockNodeId = 'node1'; + + beforeEach(async () => { + components['mockComponent'] = { + authoring: MockAuthoringComponent + }; + + await TestBed.configureTestingModule({ + imports: [EditComponentComponent] + }).compileComponents(); + + fixture = TestBed.createComponent(EditComponentComponent); + component = fixture.componentInstance; + component.componentContent = mockComponentContent as ComponentContent; + component.nodeId = mockNodeId; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should create the dynamic component after view init', () => { + component.ngAfterViewInit(); + fixture.detectChanges(); + const componentElement = fixture.nativeElement.querySelector('div'); + expect(componentElement.textContent).toContain('Mock Authoring Component'); + }); + + it('should pass inputs to the dynamic component', () => { + component.ngAfterViewInit(); + fixture.detectChanges(); + const componentInstance = (component as any).componentRef.instance; + expect(componentInstance.componentContent).toBe(mockComponentContent); + expect(componentInstance.nodeId).toBe(mockNodeId); + }); + + it('should destroy the component reference on destroy', () => { + component.ngAfterViewInit(); + const destroySpy = spyOn((component as any).componentRef, 'destroy'); + component.ngOnDestroy(); + expect(destroySpy).toHaveBeenCalled(); + }); + + it('should focus the host element after timeout', (done) => { + component.ngAfterViewInit(); + fixture.detectChanges(); + setTimeout(() => { + const hostElement = fixture.nativeElement.querySelector('div'); + expect(document.activeElement).toBe(hostElement); + done(); + }, 0); + }); +}); diff --git a/src/assets/wise5/authoringTool/components/edit-component/edit-component.component.ts b/src/assets/wise5/authoringTool/components/edit-component/edit-component.component.ts new file mode 100644 index 00000000000..f17d572ce15 --- /dev/null +++ b/src/assets/wise5/authoringTool/components/edit-component/edit-component.component.ts @@ -0,0 +1,47 @@ +import { + ApplicationRef, + Component, + ComponentRef, + ElementRef, + EnvironmentInjector, + Input, + ViewChild, + createComponent +} from '@angular/core'; +import { ComponentContent } from '../../../common/ComponentContent'; +import { components } from '../../../components/Components'; + +@Component({ + selector: 'edit-component', + standalone: true, + template: '
' +}) +export class EditComponentComponent { + @Input() componentContent: ComponentContent; + @ViewChild('component') private componentElementRef: ElementRef; + private componentRef: ComponentRef; + @Input() nodeId: string; + + constructor( + private applicationRef: ApplicationRef, + private injector: EnvironmentInjector + ) {} + + ngAfterViewInit(): void { + const hostElement = this.componentElementRef.nativeElement; + this.componentRef = createComponent(components[this.componentContent.type].authoring, { + hostElement: hostElement, + environmentInjector: this.injector + }); + Object.assign(this.componentRef.instance, { + componentContent: this.componentContent, + nodeId: this.nodeId + }); + this.applicationRef.attachView(this.componentRef.hostView); + setTimeout(() => hostElement.focus()); + } + + ngOnDestroy(): void { + this.componentRef.destroy(); + } +} diff --git a/src/assets/wise5/authoringTool/components/preview-component-button/preview-component-button.component.html b/src/assets/wise5/authoringTool/components/preview-component-button/preview-component-button.component.html deleted file mode 100644 index f454bdaac92..00000000000 --- a/src/assets/wise5/authoringTool/components/preview-component-button/preview-component-button.component.html +++ /dev/null @@ -1,10 +0,0 @@ - diff --git a/src/assets/wise5/authoringTool/components/preview-component-button/preview-component-button.component.ts b/src/assets/wise5/authoringTool/components/preview-component-button/preview-component-button.component.ts deleted file mode 100644 index 7e448c0111b..00000000000 --- a/src/assets/wise5/authoringTool/components/preview-component-button/preview-component-button.component.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Component, Input } from '@angular/core'; -import { MatDialog } from '@angular/material/dialog'; -import { PreviewComponentDialogComponent } from '../preview-component-dialog/preview-component-dialog.component'; -import { ProjectService } from '../../../services/projectService'; -import { ComponentFactory } from '../../../common/ComponentFactory'; -import { MatIconModule } from '@angular/material/icon'; -import { MatTooltipModule } from '@angular/material/tooltip'; -import { MatButtonModule } from '@angular/material/button'; - -@Component({ - imports: [MatButtonModule, MatIconModule, MatTooltipModule], - selector: 'preview-component-button', - standalone: true, - templateUrl: 'preview-component-button.component.html' -}) -export class PreviewComponentButtonComponent { - @Input() componentId: string; - @Input() nodeId: string; - - constructor(private dialog: MatDialog, private projectService: ProjectService) {} - - protected popUpComponentPreview(): void { - const content = this.projectService.injectAssetPaths( - this.projectService.getComponent(this.nodeId, this.componentId) - ); - this.dialog.open(PreviewComponentDialogComponent, { - data: new ComponentFactory().getComponent(content, this.nodeId), - panelClass: 'dialog-lg' - }); - } -} diff --git a/src/assets/wise5/authoringTool/components/preview-component/preview-component.component.ts b/src/assets/wise5/authoringTool/components/preview-component/preview-component.component.ts index afa07216356..d81d120228c 100644 --- a/src/assets/wise5/authoringTool/components/preview-component/preview-component.component.ts +++ b/src/assets/wise5/authoringTool/components/preview-component/preview-component.component.ts @@ -16,16 +16,20 @@ import { components } from '../../../components/Components'; @Component({ selector: 'preview-component', standalone: true, - template: '
' + template: '
' }) export class PreviewComponentComponent { - @Input() protected component: WISEComponent; + @Input() component: WISEComponent; @ViewChild('component') private componentElementRef: ElementRef; private componentRef: ComponentRef; - @Input() protected periodId: number; - @Output() private starterStateChangedEvent: EventEmitter = new EventEmitter(); + @Input() disabled: boolean; + @Input() periodId: number; + @Output() starterStateChangedEvent: EventEmitter = new EventEmitter(); - constructor(private applicationRef: ApplicationRef, private injector: EnvironmentInjector) {} + constructor( + private applicationRef: ApplicationRef, + private injector: EnvironmentInjector + ) {} ngAfterViewInit(): void { this.renderComponent(); @@ -50,6 +54,7 @@ export class PreviewComponentComponent { component: this.component, mode: 'preview', periodId: this.periodId, + isDisabled: this.disabled, starterStateChangedEvent: this.starterStateChangedEvent }); this.applicationRef.attachView(this.componentRef.hostView); diff --git a/src/assets/wise5/authoringTool/concurrent-authors-message/concurrent-authors-message.component.html b/src/assets/wise5/authoringTool/concurrent-authors-message/concurrent-authors-message.component.html index 94957cfaa38..d371844cf07 100644 --- a/src/assets/wise5/authoringTool/concurrent-authors-message/concurrent-authors-message.component.html +++ b/src/assets/wise5/authoringTool/concurrent-authors-message/concurrent-authors-message.component.html @@ -1,3 +1,5 @@ -
- {{ message }} -
+@if (message) { +
+ {{ message }} +
+} diff --git a/src/assets/wise5/authoringTool/concurrent-authors-message/concurrent-authors-message.component.spec.ts b/src/assets/wise5/authoringTool/concurrent-authors-message/concurrent-authors-message.component.spec.ts index 6e3ae833297..189331916b3 100644 --- a/src/assets/wise5/authoringTool/concurrent-authors-message/concurrent-authors-message.component.spec.ts +++ b/src/assets/wise5/authoringTool/concurrent-authors-message/concurrent-authors-message.component.spec.ts @@ -44,9 +44,6 @@ describe('ConcurrentAuthorsMessageComponent', () => { function ngOnInit() { describe('ngOnInit()', () => { - it('set empty message when there are no other authors', () => { - expectMessage('["aa"]', ''); - }); it('set message to author when there is one other author', () => { expectMessage( '["aa","bb"]', diff --git a/src/assets/wise5/authoringTool/concurrent-authors-message/concurrent-authors-message.component.ts b/src/assets/wise5/authoringTool/concurrent-authors-message/concurrent-authors-message.component.ts index 413305c4097..bf3eeeed675 100644 --- a/src/assets/wise5/authoringTool/concurrent-authors-message/concurrent-authors-message.component.ts +++ b/src/assets/wise5/authoringTool/concurrent-authors-message/concurrent-authors-message.component.ts @@ -8,7 +8,8 @@ import { NotifyAuthorService } from '../../services/notifyAuthorService'; @Component({ selector: 'concurrent-authors-message', - templateUrl: 'concurrent-authors-message.component.html' + templateUrl: 'concurrent-authors-message.component.html', + styles: ['.concurrent-authors { padding: 4px; }'] }) export class ConcurrentAuthorsMessageComponent { protected message: string = ''; diff --git a/src/assets/wise5/authoringTool/node/add-component-button/add-component-button.component.html b/src/assets/wise5/authoringTool/node/add-component-button/add-component-button.component.html index 727c499b322..b21aa47227b 100644 --- a/src/assets/wise5/authoringTool/node/add-component-button/add-component-button.component.html +++ b/src/assets/wise5/authoringTool/node/add-component-button/add-component-button.component.html @@ -1,10 +1,31 @@ - +@if (firstComponent) { + + + + + +} @else { + +} diff --git a/src/assets/wise5/authoringTool/node/add-component-button/add-component-button.component.spec.ts b/src/assets/wise5/authoringTool/node/add-component-button/add-component-button.component.spec.ts index 7545cab1030..feefe11c39c 100644 --- a/src/assets/wise5/authoringTool/node/add-component-button/add-component-button.component.spec.ts +++ b/src/assets/wise5/authoringTool/node/add-component-button/add-component-button.component.spec.ts @@ -33,7 +33,8 @@ describe('AddComponentButtonComponent', () => { }); fixture = TestBed.createComponent(AddComponentButtonComponent); component = fixture.componentInstance; - component.node = { id: 'node1' } as Node; + component.node = new Node(); + component.node.id = 'node1'; loader = TestbedHarnessEnvironment.loader(fixture); fixture.detectChanges(); }); diff --git a/src/assets/wise5/authoringTool/node/add-component-button/add-component-button.component.ts b/src/assets/wise5/authoringTool/node/add-component-button/add-component-button.component.ts index 2f00c1ff18f..0ba5b9c0ab9 100644 --- a/src/assets/wise5/authoringTool/node/add-component-button/add-component-button.component.ts +++ b/src/assets/wise5/authoringTool/node/add-component-button/add-component-button.component.ts @@ -9,17 +9,31 @@ import { Node } from '../../../common/Node'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MatTooltipModule } from '@angular/material/tooltip'; +import { MatMenuModule } from '@angular/material/menu'; +import { CommonModule } from '@angular/common'; @Component({ - imports: [MatButtonModule, MatIconModule, MatTooltipModule], + imports: [CommonModule, MatButtonModule, MatIconModule, MatMenuModule, MatTooltipModule], selector: 'add-component-button', standalone: true, + styles: [ + ` + .rotate-180 { + transform: rotate(180deg); + } + .flip-vertical { + transform: scaleY(-1); + } + ` + ], templateUrl: './add-component-button.component.html' }) export class AddComponentButtonComponent { + protected firstComponent = false; @Input() insertAfterComponentId: string = null; - @Input() node: Node; @Output() newComponentsEvent: EventEmitter = new EventEmitter(); + @Input() node: Node; + protected tooltipText = $localize`Add component`; constructor( private createComponentService: CreateComponentService, @@ -29,10 +43,21 @@ export class AddComponentButtonComponent { private router: Router ) {} - protected addComponent(): void { + ngOnInit(): void { + this.updateUI(); + } + + private updateUI(): void { + this.firstComponent = this.node.getComponentPosition(this.insertAfterComponentId) === 0; + if (this.node.components.length > 0 && !this.firstComponent) { + this.tooltipText = $localize`Add component after`; + } + } + + protected addComponent(afterComponent = this.insertAfterComponentId): void { this.dialog .open(ChooseNewComponent, { - data: this.insertAfterComponentId, + data: afterComponent, width: '80%' }) .afterClosed() @@ -42,17 +67,18 @@ export class AddComponentButtonComponent { this.router.navigate(['import-component/choose-component'], { relativeTo: this.route, state: { - insertAfterComponentId: this.insertAfterComponentId + insertAfterComponentId: afterComponent } }); } else { const component = this.createComponentService.create( this.node.id, componentType, - this.insertAfterComponentId + afterComponent ); this.projectService.saveProject(); this.newComponentsEvent.emit([component]); + this.updateUI(); } }); } diff --git a/src/assets/wise5/authoringTool/node/chooseComponentLocation/choose-component-location.component.html b/src/assets/wise5/authoringTool/node/chooseComponentLocation/choose-component-location.component.html deleted file mode 100644 index bb73cd85d0b..00000000000 --- a/src/assets/wise5/authoringTool/node/chooseComponentLocation/choose-component-location.component.html +++ /dev/null @@ -1,51 +0,0 @@ -
-
-
Choose the new location by clicking one of the buttons below
-
-
-
- - Insert As First Component -
-@for (component of components; track component.id; let componentIndex = $index) { -
-
-
- {{ componentIndex + 1 }}. {{ getComponentTypeLabel(component.type) }} -
-
-
- -
-
-} - -
-
- -
diff --git a/src/assets/wise5/authoringTool/node/chooseComponentLocation/choose-component-location.component.spec.ts b/src/assets/wise5/authoringTool/node/chooseComponentLocation/choose-component-location.component.spec.ts deleted file mode 100644 index 10c9e8d6969..00000000000 --- a/src/assets/wise5/authoringTool/node/chooseComponentLocation/choose-component-location.component.spec.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { TestBed } from '@angular/core/testing'; -import { ChooseComponentLocationComponent } from './choose-component-location.component'; -import { ComponentTypeService } from '../../../services/componentTypeService'; -import { ConfigService } from '../../../services/configService'; -import { TeacherDataService } from '../../../services/teacherDataService'; -import { TeacherProjectService } from '../../../services/teacherProjectService'; -import { CopyTranslationsService } from '../../../services/copyTranslationsService'; -import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; - -const nodeId = 'node1'; -const components = [ - { id: 'comp1', type: 'OpenResponse' }, - { id: 'comp2', type: 'MultipleChoice' } -]; - -class MockProjectService { - createComponent(componentType) { - return { id: 'comp3', type: componentType }; - } - - getComponents() { - return components; - } - - saveProject() { - return new Promise(() => {}); - } -} - -class MockTeacherDataService { - getCurrentNodeId() { - return nodeId; - } -} - -class MockComponentTypeService {} -let component: ChooseComponentLocationComponent; -describe('ChooseComponentLocationComponent', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - ChooseComponentLocationComponent, - { provide: ComponentTypeService, useClass: MockComponentTypeService }, - ConfigService, - CopyTranslationsService, - { provide: TeacherProjectService, useClass: MockProjectService }, - { provide: TeacherDataService, useClass: MockTeacherDataService }, - provideHttpClient(withInterceptorsFromDi()) - ] - }); - component = TestBed.inject(ChooseComponentLocationComponent); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/assets/wise5/authoringTool/node/chooseComponentLocation/choose-component-location.component.ts b/src/assets/wise5/authoringTool/node/chooseComponentLocation/choose-component-location.component.ts deleted file mode 100644 index 8972788cdcb..00000000000 --- a/src/assets/wise5/authoringTool/node/chooseComponentLocation/choose-component-location.component.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { Component } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { RouterModule } from '@angular/router'; -import { MatButtonModule } from '@angular/material/button'; -import { MatIconModule } from '@angular/material/icon'; -import { MatTooltipModule } from '@angular/material/tooltip'; -import { ComponentTypeService } from '../../../services/componentTypeService'; -import { ConfigService } from '../../../services/configService'; -import { TeacherDataService } from '../../../services/teacherDataService'; -import { TeacherProjectService } from '../../../services/teacherProjectService'; -import { Node } from '../../../common/Node'; -import { Router } from '@angular/router'; -import { CopyTranslationsService } from '../../../services/copyTranslationsService'; -import { FlexLayoutModule } from '@angular/flex-layout'; - -@Component({ - standalone: true, - imports: [ - CommonModule, - FlexLayoutModule, - MatButtonModule, - MatIconModule, - MatTooltipModule, - RouterModule - ], - templateUrl: 'choose-component-location.component.html' -}) -export class ChooseComponentLocationComponent { - private action: 'copy' | 'move'; - protected components: any; - private node: Node; - private selectedComponents: any[]; - - constructor( - private componentTypeService: ComponentTypeService, - private copyTranslationsService: CopyTranslationsService, - private configService: ConfigService, - private dataService: TeacherDataService, - private projectService: TeacherProjectService, - private router: Router - ) {} - - ngOnInit(): void { - this.action = history.state.action; - const nodeId = this.dataService.getCurrentNodeId(); - this.node = this.projectService.getNode(nodeId); - this.components = this.projectService.getComponents(nodeId); - this.selectedComponents = history.state.selectedComponents; - } - - protected getComponentTypeLabel(componentType: any): string { - return this.componentTypeService.getComponentTypeLabel(componentType); - } - - protected insertComponentAfter(insertAfterComponentId: string = null): void { - const updatedComponents = - this.action === 'copy' - ? this.copyComponents(insertAfterComponentId) - : this.moveComponents(insertAfterComponentId); - this.projectService.saveProject().then(() => { - this.goToNodeAuthoring(updatedComponents); - }); - } - - private copyComponents(insertAfterComponentId: string = null): any[] { - const newComponents = this.node.copyComponents( - this.selectedComponents.map((c) => c.id), - insertAfterComponentId - ); - this.copyTranslationsService.tryCopyComponents(this.node, newComponents); - return newComponents; - } - - private moveComponents(insertAfterComponentId: string = null): any[] { - this.node.moveComponents( - this.selectedComponents.map((c) => c.id), - insertAfterComponentId - ); - return this.selectedComponents; - } - - protected goToNodeAuthoring(components: any[] = []): void { - this.router.navigate( - ['/teacher/edit/unit', this.configService.getProjectId(), 'node', this.node.id], - { - state: { - projectId: this.configService.getProjectId(), - nodeId: this.node.id, - newComponents: components - } - } - ); - } -} diff --git a/src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.html b/src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.html index 558c5e56adb..32193e544ae 100644 --- a/src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.html +++ b/src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.html @@ -1,171 +1,131 @@ -
-
- - -
- -
+
+ + +
+
-
- @if (!isGroupNode) { -
-
Components
+
+@if (components.length === 0 && !isGroupNode) { +

This step does not have any components.

+ +} +
+ @for (component of components; track component.id; let i = $index; let last = $last) { +
+ +
+
+ @if (components.length > 1) { + drag_indicator + } + {{ i + 1 }}. {{ getComponentTypeLabel(component.type) }} +
+ +
+ @if (component.id === editingComponentId) { + + } + + +
+
+ +
+ +
+
+
-
- + @if (i > 0) { + } + @if (!last) { -
- -
- - -
+ }
- } -
- @if (components.length === 0 && !isGroupNode) { -

This step does not have any components. Click the + button to add a component.

- } -
- @for (component of components; track component.id; let i = $index) { -
- + {{ i + 1 }}. {{ getComponentTypeLabel(component.type) }} - - - @if (components.length > 1) { - drag_indicator - } - - {{ i + 1 }}. {{ getComponentTypeLabel(component.type) }} - - - - - - - - - -
- @if (componentsToExpanded[component.id]) { - - } -
-
- -
- } -
+ +
+ }
diff --git a/src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.scss b/src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.scss index b120e0854ff..74ced36e24a 100644 --- a/src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.scss +++ b/src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.scss @@ -1,64 +1,51 @@ -.node-authoring { - .node-authoring-header { - margin: 8px 8px 0; +.node-authoring-header { + margin: 16px 8px 0; } - .node-authoring-controls { - padding: 8px 16px; - background-color: white; - position: sticky; - top: 0; - z-index: 2; - } - - .component { - flex: 1; - - .mat-expansion-panel-header { - padding-inline-start: 8px; - } +.component { + flex: 1; - .mat-expansion-panel-header-title { - flex-grow: 100; - } + &.component-editing { + border-inline-start: 4px solid; - .mat-expansion-panel-body { - padding-left: 16px; - padding-right: 16px; + edit-component-advanced-button { + display: block; } + } +} - &:hover, &:focus-within, &.mat-expanded { - .component-action { - display: block; - } - } +edit-component-advanced-button { + display: none; +} - &.mat-expanded { - edit-component-advanced-button { - display: block; - } - } - } +.component-header { + padding: 0 8px; +} - edit-component-advanced-button { - display: none; - } +component-authoring { + display: block; + margin: 16px; +} - .component-action { - display: none; - } +.mat-divider-horizontal { + margin: 0; +} - .drag-handle { - cursor: move; - margin-right: 4px; - margin-left: 4px; - } +.drag-handle { + cursor: move; + margin-right: 4px; + margin-left: 4px; +} - .cdk-drag-placeholder { - opacity: .4; - } +.cdk-drag-placeholder { + opacity: .4; + background: #ccc; + border: dotted 3px #999; + min-height: 40px; + min-width: 360px; + transition: transform 250ms cubic-bezier(0, 0, 0.2, 1); +} - .mat-icon { - margin: 0; - } +.mat-icon { + margin: 0; } diff --git a/src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.spec.ts b/src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.spec.ts index 058b125aa94..5beae635f7f 100644 --- a/src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.spec.ts +++ b/src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.spec.ts @@ -27,12 +27,12 @@ import { ProjectLocale } from '../../../../../app/domain/projectLocale'; import { TeacherProjectTranslationService } from '../../../services/teacherProjectTranslationService'; import { ComponentTypeServiceModule } from '../../../services/componentTypeService.module'; import { DeleteTranslationsService } from '../../../services/deleteTranslationsService'; -import { PreviewComponentButtonComponent } from '../../components/preview-component-button/preview-component-button.component'; import { CopyTranslationsService } from '../../../services/copyTranslationsService'; import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; -import { RouterTestingModule } from '@angular/router/testing'; import { CreateComponentService } from '../../../services/createComponentService'; -import { MatExpansionModule } from '@angular/material/expansion'; +import { VLEProjectService } from '../../../vle/vleProjectService'; +import { NotebookService } from '../../../services/notebookService'; +import { MatDividerModule } from '@angular/material/divider'; let component: NodeAuthoringComponent; let component1: any; @@ -60,11 +60,9 @@ describe('NodeAuthoringComponent', () => { EditNodeTitleComponent, FormsModule, MatCheckboxModule, - MatExpansionModule, + MatDividerModule, MatIconModule, MatInputModule, - PreviewComponentButtonComponent, - RouterTestingModule, StudentTeacherCommonServicesModule, TeacherNodeIconComponent ], @@ -107,8 +105,8 @@ describe('NodeAuthoringComponent', () => { spyOn(document, 'getElementById').and.returnValue(document.createElement('div')); confirmSpy = spyOn(window, 'confirm'); component1 = { id: 'component1', type: 'OpenResponse', showSubmitButton: true }; - component2 = { id: 'component2', type: 'MultipleChoice', showSubmitButton: true }; - component3 = { id: 'component3', type: 'Match', showSubmitButton: true }; + component2 = { id: 'component2', type: 'MultipleChoice', showSubmitButton: true, choices: [] }; + component3 = { id: 'component3', type: 'HTML', showSubmitButton: true, html: '' }; node1Components = [component1, component2, component3]; teacherProjectService = TestBed.inject(TeacherProjectService); const node1 = { components: node1Components }; @@ -127,6 +125,10 @@ describe('NodeAuthoringComponent', () => { new ProjectLocale({ default: 'en-US', supported: ['es'] }) ); spyOn(TestBed.inject(TeacherProjectService), 'isDefaultLocale').and.returnValue(true); + const vleProjectService = TestBed.inject(VLEProjectService); + vleProjectService.project = teacherProjectService.project; + spyOn(TestBed.inject(VLEProjectService), 'getSpeechToTextSettings').and.returnValue(null); + spyOn(TestBed.inject(NotebookService), 'isNotebookEnabled').and.returnValue(false); saveProjectSpy = spyOn(teacherProjectService, 'saveProject').and.returnValue(Promise.resolve()); fixture = TestBed.createComponent(NodeAuthoringComponent); component = fixture.componentInstance; @@ -137,7 +139,6 @@ describe('NodeAuthoringComponent', () => { copyComponent(); deleteComponent(); - deleteComponents(); }); function copyComponent() { @@ -166,7 +167,7 @@ function deleteComponent() { confirmSpy.and.returnValue(true); clickComponentDeleteButton(component2.id); expect(confirmSpy).toHaveBeenCalledWith( - `Are you sure you want to delete this component?\n2. MultipleChoice` + `Are you sure you want to delete this component?\n\n2. MultipleChoice` ); expect(saveProjectSpy).toHaveBeenCalled(); expect(teacherProjectService.idToNode[nodeId1].components).toEqual([component1, component3]); @@ -174,33 +175,6 @@ function deleteComponent() { }); } -function deleteComponents() { - describe('deleteComponents()', () => { - it('should delete components', () => { - clickComponentCheckbox(component1.id); - clickComponentCheckbox(component3.id); - fixture.detectChanges(); - expect(component.components).toEqual(node1Components); - confirmSpy.and.returnValue(true); - clickDeleteComponentsButton(); - expect(confirmSpy).toHaveBeenCalledWith( - `Are you sure you want to delete these components?\n1. OpenResponse\n3. Match` - ); - expect(component.components).toEqual([component2]); - expect(expectCheckboxValue(component1.id)).toBeFalsy(); - expect(expectCheckboxValue(component3.id)).toBeFalsy(); - }); - }); -} - -function expectCheckboxValue(componentId: string): void { - return fixture.debugElement.query(By.css(`#${componentId} mat-checkbox`)).nativeElement.checked; -} - -function clickComponentCheckbox(componentId: string): void { - queryByCssAndClick(`#${componentId} mat-checkbox label`); -} - function clickComponent(componentId: string): void { queryByCssAndClick(`#${componentId}`); } @@ -221,10 +195,6 @@ function clickComponentDeleteButton(componentId: string): void { queryByCssAndClickDelete(`#${componentId} button`); } -function clickDeleteComponentsButton(): void { - queryByCssAndClickDelete('button'); -} - function queryByCssAndClickDelete(css: string): void { clickNativeElement(queryByCssAndInnerText(css, 'delete')); } diff --git a/src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.ts b/src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.ts index 77114eeff08..03fd7bb9f1d 100644 --- a/src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.ts +++ b/src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.ts @@ -1,13 +1,4 @@ -import { - Component, - Input, - OnInit, - Signal, - ViewEncapsulation, - WritableSignal, - computed, - signal -} from '@angular/core'; +import { Component, Input, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; import { Subscription } from 'rxjs'; import { TeacherDataService } from '../../../services/teacherDataService'; import { TeacherProjectService } from '../../../services/teacherProjectService'; @@ -17,29 +8,22 @@ import { Node } from '../../../common/Node'; import { ComponentContent } from '../../../common/ComponentContent'; import { scrollToTopOfPage, temporarilyHighlightElement } from '../../../common/dom/dom'; import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'; -import { ActivatedRoute, Router } from '@angular/router'; import { TeacherNodeService } from '../../../services/teacherNodeService'; import { DeleteTranslationsService } from '../../../services/deleteTranslationsService'; -import { copy } from '../../../common/object/object'; @Component({ selector: 'node-authoring', templateUrl: './node-authoring.component.html', - styleUrls: ['./node-authoring.component.scss'], - encapsulation: ViewEncapsulation.None + styleUrls: ['./node-authoring.component.scss'] }) export class NodeAuthoringComponent implements OnInit { components: ComponentContent[] = []; - protected componentsToChecked: WritableSignal<{ [key: string]: boolean }> = signal({}); - componentsToExpanded = {}; - protected isAnyComponentSelected: Signal = computed(() => - Object.values(this.componentsToChecked()).some((value) => value) - ); + protected editingComponentId: string; isGroupNode: boolean; node: Node; nodeJson: any; @Input() nodeId?: string; - subscriptions: Subscription = new Subscription(); + private subscriptions: Subscription = new Subscription(); constructor( private componentServiceLookupService: ComponentServiceLookupService, @@ -47,9 +31,7 @@ export class NodeAuthoringComponent implements OnInit { private nodeService: TeacherNodeService, private projectService: TeacherProjectService, private dataService: TeacherDataService, - private deleteTranslationsService: DeleteTranslationsService, - private route: ActivatedRoute, - private router: Router + private deleteTranslationsService: DeleteTranslationsService ) {} ngOnInit(): void { @@ -66,11 +48,10 @@ export class NodeAuthoringComponent implements OnInit { this.isGroupNode = this.projectService.isGroupNode(this.nodeId); this.nodeJson = this.projectService.getNodeById(this.nodeId); this.components = this.projectService.getComponents(this.nodeId); - this.componentsToChecked.set({}); - this.componentsToExpanded = {}; + this.editingComponentId = null; if (history.state.newComponents && history.state.newComponents.length > 0) { - this.highlightAndExpandComponents(history.state.newComponents); + this.highlightComponents(history.state.newComponents); } else { scrollToTopOfPage(); } @@ -140,82 +121,24 @@ export class NodeAuthoringComponent implements OnInit { return this.projectService.saveProject(); } - protected getSelectedComponents(): ComponentContent[] { - return this.components.filter( - (component: ComponentContent) => this.componentsToChecked()[component.id] - ); - } - - /** - * Get the component numbers and component types that have been selected - * @return an array of strings - * example - * [ - * "1. OpenResponse", - * "3. MultipleChoice" - * ] - */ - private getSelectedComponentNumbersAndTypes(): string[] { - const selectedComponents = []; - for (let c = 0; c < this.components.length; c++) { - const component = this.components[c]; - if (this.componentsToChecked()[component.id]) { - const componentNumberAndType = c + 1 + '. ' + component.type; - selectedComponents.push(componentNumberAndType); - } - } - return selectedComponents; - } - - protected chooseComponentLocation(action: string): void { - this.router.navigate(['choose-component-location'], { - relativeTo: this.route, - state: { - action: action, - selectedComponents: this.getSelectedComponents() - } - }); - } - - protected deleteComponents(): void { - scrollToTopOfPage(); - if (this.confirmDeleteComponent(this.getSelectedComponentNumbersAndTypes())) { - this.deleteComponentsOnServer( - this.getSelectedComponents().map((component) => this.node.deleteComponent(component.id)) - ); - } - } - protected deleteComponent( event: any, componentNumber: number, component: ComponentContent ): void { event.stopPropagation(); - if (this.confirmDeleteComponent([`${componentNumber}. ${component.type}`])) { + if ( + confirm( + $localize`Are you sure you want to delete this component?\n\n${componentNumber}. ${component.type}` + ) + ) { this.deleteComponentsOnServer([this.node.deleteComponent(component.id)]); } } - private confirmDeleteComponent(componentLabels: string[]): boolean { - let confirmMessage = - componentLabels.length === 1 - ? $localize`Are you sure you want to delete this component?\n` - : $localize`Are you sure you want to delete these components?\n`; - confirmMessage += `${componentLabels.join('\n')}`; - return confirm(confirmMessage); - } - private deleteComponentsOnServer(components: ComponentContent[]): void { this.checkIfNeedToShowNodeSaveOrNodeSubmitButtons(); this.projectService.saveProject().then(() => { - for (const component of components) { - this.componentsToChecked.update((obj) => { - delete obj[component.id]; - return copy(obj); - }); - delete this.componentsToExpanded[component.id]; - } this.deleteTranslationsService.tryDeleteComponents(components); }); } @@ -240,22 +163,15 @@ export class NodeAuthoringComponent implements OnInit { } /** - * Temporarily highlight the specified components and show the component - * authoring views. Used to bring user's attention to new changes. - * @param components an array of components to highlight and expand + * Temporarily highlight the specified components + * @param components an array of components to highlight */ - protected highlightAndExpandComponents(components: any = []): void { - this.componentsToChecked.set({}); - - // wait for the UI to update and then scroll to the first new component + protected highlightComponents(components: any = []): void { + // wait for the UI to update and then highlight the first component setTimeout(() => { if (components.length > 0) { - const componentElement = $('#' + components[0].id); - $('#content').scrollTop(componentElement.offset().top - 200); - for (const component of components) { - temporarilyHighlightElement(component.id); - this.componentsToExpanded[component.id] = true; - } + document.getElementById(components[0].id).scrollIntoView(); + components.forEach((component) => temporarilyHighlightElement(component.id)); } }, 100); } @@ -264,29 +180,6 @@ export class NodeAuthoringComponent implements OnInit { return this.componentTypeService.getComponentTypeLabel(componentType); } - protected componentCheckboxChanged(componentId: string, checked: boolean): void { - this.componentsToChecked.update((componentsToChecked) => { - componentsToChecked[componentId] = checked; - return copy(componentsToChecked); - }); - } - - protected toggleComponent(componentId: string, expanded: boolean = true): void { - this.componentsToExpanded[componentId] = expanded; - this.projectService.uiChanged(); - } - - protected setAllComponentsIsExpanded(isExpanded: boolean): void { - this.components.forEach((component) => { - this.componentsToExpanded[component.id] = isExpanded; - }); - this.projectService.uiChanged(); - } - - protected getNumberOfComponentsExpanded(): number { - return Object.values(this.componentsToExpanded).filter((value) => value).length; - } - private setShowSaveButtonForAllComponents(node: Node, showSaveButton: boolean): void { node.components .filter((component) => @@ -296,7 +189,22 @@ export class NodeAuthoringComponent implements OnInit { } protected dropComponent(event: CdkDragDrop): void { - moveItemInArray(this.components, event.previousIndex, event.currentIndex); + this.moveComponent(event.previousIndex, event.currentIndex); + } + + protected moveComponent( + previousIndex: number, + currentIndex: number, + scroll: boolean = false + ): void { + moveItemInArray(this.components, previousIndex, currentIndex); + if (scroll) { + this.highlightComponents([this.components[currentIndex]]); + } this.projectService.saveProject(); } + + protected editComponent(componentId: string): void { + this.editingComponentId = componentId; + } } diff --git a/src/assets/wise5/authoringTool/project-authoring-parent/project-authoring-parent.component.scss b/src/assets/wise5/authoringTool/project-authoring-parent/project-authoring-parent.component.scss index 7155e961a66..7e5bae93d20 100644 --- a/src/assets/wise5/authoringTool/project-authoring-parent/project-authoring-parent.component.scss +++ b/src/assets/wise5/authoringTool/project-authoring-parent/project-authoring-parent.component.scss @@ -11,7 +11,6 @@ .concurrent-authors-message { position: sticky; top: 1px; - padding: 4px 0; display: block; z-index: 3; } diff --git a/src/assets/wise5/common/dom/dom.ts b/src/assets/wise5/common/dom/dom.ts index cf7406a1262..f743309bf38 100644 --- a/src/assets/wise5/common/dom/dom.ts +++ b/src/assets/wise5/common/dom/dom.ts @@ -4,29 +4,13 @@ * @param duration The number of milliseconds to keep the element highlighted */ export function temporarilyHighlightElement(id: string, duration: number = 1000): void { - const element = $('#' + id); - const originalBackgroundColor = element.css('backgroundColor'); - element.css('background-color', '#FFFF9C'); - - /* - * Use a timeout before starting to transition back to the original background color. For some - * reason the element won't get highlighted in the first place unless this timeout is used. - */ + const element = document.getElementById(id); + element.classList.add('highlighted-bg'); setTimeout(() => { - // slowly fade back to the original background color - element.css({ - transition: 'background-color 2s ease-in-out', - 'background-color': originalBackgroundColor - }); - - /* - * remove these styling fields after we perform the fade otherwise the regular mouseover - * background color change will not work - */ + element.style.transition = 'background-color 2s ease-in-out'; + element.classList.remove('highlighted-bg'); setTimeout(() => { - element.css({ - transition: '' - }); + element.style.transition = ''; }, 2000); }, duration); } diff --git a/src/assets/wise5/components/component/component.component.html b/src/assets/wise5/components/component/component.component.html index 3239c2c6487..543945f8252 100644 --- a/src/assets/wise5/components/component/component.component.html +++ b/src/assets/wise5/components/component/component.component.html @@ -3,6 +3,4 @@
} -
-
-
+
diff --git a/src/assets/wise5/components/draw/draw-show-work/draw-show-work.component.ts b/src/assets/wise5/components/draw/draw-show-work/draw-show-work.component.ts index 393da29c4f9..0db867fcf10 100644 --- a/src/assets/wise5/components/draw/draw-show-work/draw-show-work.component.ts +++ b/src/assets/wise5/components/draw/draw-show-work/draw-show-work.component.ts @@ -51,6 +51,7 @@ export class DrawShowWorkComponent extends ComponentShowWorkDirective { this.componentContent.height ); this.DrawService.setUpTools(this.drawingToolId, this.componentContent.tools, false); + this.drawingTool.canvasOnly(); this.drawingTool.canvas.removeListeners(); } diff --git a/src/assets/wise5/components/draw/draw-student/draw-student.component.ts b/src/assets/wise5/components/draw/draw-student/draw-student.component.ts index 8b39604f972..fae6e847c14 100644 --- a/src/assets/wise5/components/draw/draw-student/draw-student.component.ts +++ b/src/assets/wise5/components/draw/draw-student/draw-student.component.ts @@ -96,6 +96,7 @@ export class DrawStudent extends ComponentStudent { this.disableSubmitButton(); } if (this.isDisabled) { + this.drawingTool.canvasOnly(); this.drawingTool.canvas.removeListeners(); } @@ -323,14 +324,13 @@ export class DrawStudent extends ComponentStudent { addToNotebook(): void { if (this.isDirty) { - const studentWorkSavedToServerSubscription = this.StudentDataService.studentWorkSavedToServer$.subscribe( - (componentState: any) => { + const studentWorkSavedToServerSubscription = + this.StudentDataService.studentWorkSavedToServer$.subscribe((componentState: any) => { if (this.isForThisComponent(componentState)) { this.addNoteWithImage(componentState.id); studentWorkSavedToServerSubscription.unsubscribe(); } - } - ); + }); this.saveButtonClicked(); } else { const componentState = this.StudentDataService.getLatestComponentStateByNodeIdAndComponentId( diff --git a/src/assets/wise5/components/draw/drawService.ts b/src/assets/wise5/components/draw/drawService.ts index 21e50887e0f..8d1d99ed0cb 100644 --- a/src/assets/wise5/components/draw/drawService.ts +++ b/src/assets/wise5/components/draw/drawService.ts @@ -182,14 +182,10 @@ export class DrawService extends ComponentService { } setUpTools(drawingToolId: string, tools: any, isDisabled: boolean): void { - if (isDisabled) { - this.hideAllTools(drawingToolId); - } else { - const drawingTool = $(`#${drawingToolId}`); - for (const toolName of Object.keys(tools)) { - const isShowTool = tools[toolName]; - this.toggleToolVisibility(drawingTool, isShowTool, this.toolFieldToLabel[toolName]); - } + const drawingTool = $(`#${drawingToolId}`); + for (const toolName of Object.keys(tools)) { + const isShowTool = tools[toolName]; + this.toggleToolVisibility(drawingTool, isShowTool, this.toolFieldToLabel[toolName]); } } @@ -200,8 +196,4 @@ export class DrawService extends ComponentService { drawingTool.find(`[title="${title}"]`).hide(); } } - - hideAllTools(drawingToolId: string): void { - $(`#${drawingToolId}`).find('.dt-tools').hide(); - } } diff --git a/src/assets/wise5/vle/node/node.component.scss b/src/assets/wise5/vle/node/node.component.scss index 3cdd27a463d..136612cd066 100644 --- a/src/assets/wise5/vle/node/node.component.scss +++ b/src/assets/wise5/vle/node/node.component.scss @@ -1,3 +1,7 @@ .mat-mdc-button { min-width: 88px; +} + +.component { + padding: 24px 24px 0; } \ No newline at end of file diff --git a/src/messages.xlf b/src/messages.xlf index 5624a21d708..25a51cd1a97 100644 --- a/src/messages.xlf +++ b/src/messages.xlf @@ -297,10 +297,6 @@ src/assets/wise5/authoringTool/components/component-info-dialog/component-info-dialog.component.html 29 - - src/assets/wise5/authoringTool/components/preview-component-dialog/preview-component-dialog.component.html - 19 - src/assets/wise5/authoringTool/peer-grouping/select-peer-grouping-dialog/select-peer-grouping-dialog.component.html 26 @@ -1175,7 +1171,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.html - 114 + 54 src/assets/wise5/components/common/feedbackRule/edit-feedback-rules/edit-feedback-rules.component.html @@ -1222,6 +1218,10 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.src/app/authoring-tool/edit-question-bank-rules/edit-question-bank-rules.component.html 138 + + src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.html + 103 + src/assets/wise5/components/common/feedbackRule/edit-feedback-rules/edit-feedback-rules.component.html 129 @@ -1237,6 +1237,10 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.src/app/authoring-tool/edit-question-bank-rules/edit-question-bank-rules.component.html 148 + + src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.html + 115 + src/assets/wise5/components/common/feedbackRule/edit-feedback-rules/edit-feedback-rules.component.html 139 @@ -9173,10 +9177,6 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.src/app/teacher/share-run-dialog/share-run-dialog.component.html 152,154 - - src/assets/wise5/authoringTool/node/chooseComponentLocation/choose-component-location.component.html - 48,50 - src/assets/wise5/classroomMonitor/classroomMonitorComponents/peer-group/peer-group-move-workgroup-confirm-dialog/peer-group-move-workgroup-confirm-dialog.component.html 27,29 @@ -10192,6 +10192,13 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.98 + + Edit content + + src/assets/wise5/authoringTool/components/component-authoring.component.ts + 45 + + Component Info @@ -10249,46 +10256,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.html - 16 - - - - Preview component - - src/assets/wise5/authoringTool/components/preview-component-button/preview-component-button.component.html - 3 - - - - Preview Component - - src/assets/wise5/authoringTool/components/preview-component-dialog/preview-component-dialog.component.html - 1 - - - src/assets/wise5/authoringTool/importComponent/choose-import-component/choose-import-component.component.html - 108 - - - - To set a starter state, edit the content below and save: - - src/assets/wise5/authoringTool/components/save-starter-state/save-starter-state.component.html - 2 - - - - Are you sure you want to save the starter state? - - src/assets/wise5/authoringTool/components/save-starter-state/save-starter-state.component.ts - 28 - - - - Are you sure you want to delete the starter state? This will also close this preview window. - - src/assets/wise5/authoringTool/components/save-starter-state/save-starter-state.component.ts - 41 + 15 @@ -10418,7 +10386,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.. Be careful not to overwrite each other's work! src/assets/wise5/authoringTool/concurrent-authors-message/concurrent-authors-message.component.ts - 45,47 + 46,48 @@ -11046,6 +11014,13 @@ The branches will be removed but the steps will remain in the unit. 62 + + Preview Component + + src/assets/wise5/authoringTool/importComponent/choose-import-component/choose-import-component.component.html + 108 + + Please select a component to import. @@ -11694,11 +11669,32 @@ The branches will be removed but the steps will remain in the unit. 129 - - Add a new component + + Add component before src/assets/wise5/authoringTool/node/add-component-button/add-component-button.component.html - 4 + 15 + + + + Add component after + + src/assets/wise5/authoringTool/node/add-component-button/add-component-button.component.html + 18 + + + + Add component + + src/assets/wise5/authoringTool/node/add-component-button/add-component-button.component.ts + 36 + + + + Add component after + + src/assets/wise5/authoringTool/node/add-component-button/add-component-button.component.ts + 53 @@ -12026,31 +12022,6 @@ The branches will be removed but the steps will remain in the unit. 206 - - Choose the new location by clicking one of the buttons below - - src/assets/wise5/authoringTool/node/chooseComponentLocation/choose-component-location.component.html - 3 - - - - Insert As First Component - - src/assets/wise5/authoringTool/node/chooseComponentLocation/choose-component-location.component.html - 12 - - - src/assets/wise5/authoringTool/node/chooseComponentLocation/choose-component-location.component.html - 18 - - - - Insert After - - src/assets/wise5/authoringTool/node/chooseComponentLocation/choose-component-location.component.html - 35 - - Copy component @@ -12072,102 +12043,27 @@ The branches will be removed but the steps will remain in the unit. 23 - - Components + + This step does not have any components. src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.html - 27 - - - - Move Components - - src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.html - 37 - - - - Copy Components - - src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.html - 47 - - - - Delete Components - - src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.html - 57 - - - - + Expand All - - src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.html - 73,75 - - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html - 22,24 - - - src/assets/wise5/classroomMonitor/student-grading/student-grading.component.html - 34,36 - - - - - Collapse All - - src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.html - 83,85 - - - src/assets/wise5/classroomMonitor/student-grading/student-grading.component.html - 45,47 - - - - This step does not have any components. Click the + button to add a component. - - src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.html - 91 - - - - Expand/collapse component - - src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.html - 111 - - - - Select component - - src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.html - 124 + 24 Delete Component src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.html - 148 + 74 - + Are you sure you want to delete this component? - - - src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.ts - 203 - - - - Are you sure you want to delete these components? - + +. src/assets/wise5/authoringTool/node/node-authoring/node-authoring.component.ts - 204 + 132 @@ -13962,6 +13858,17 @@ The branches will be removed but the steps will remain in the unit. 18 + + + Expand All + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html + 22,24 + + + src/assets/wise5/classroomMonitor/student-grading/student-grading.component.html + 34,36 + + Collapse All @@ -15458,6 +15365,13 @@ Are you sure you want to proceed? 40 + + - Collapse All + + src/assets/wise5/classroomMonitor/student-grading/student-grading.component.html + 45,47 + + Sort by step @@ -18124,14 +18038,14 @@ Category Name: Are you sure you want to clear your drawing? src/assets/wise5/components/draw/draw-student/draw-student.component.ts - 198 + 199 Do you want to update the connected drawing? src/assets/wise5/components/draw/draw-student/draw-student.component.ts - 285 + 286