From a13ad2308c98741e1fcf213eeeb7e8d5a944df0d Mon Sep 17 00:00:00 2001 From: Hiroki Terashima Date: Wed, 28 Oct 2020 13:15:37 -0700 Subject: [PATCH 01/11] Upgraded NodeAdvancedGeneralAuthoring component to Angular. #2773 --- src/main/webapp/site/src/app/hybrid-module.ts | 2 ++ src/main/webapp/site/src/messages.xlf | 14 ++++++++++++ ...-advanced-general-authoring.component.html | 22 ++++++++++--------- ...de-advanced-general-authoring.component.ts | 15 +++++-------- .../teacher/teacher-angular-js-module.ts | 3 ++- 5 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/main/webapp/site/src/app/hybrid-module.ts b/src/main/webapp/site/src/app/hybrid-module.ts index 7c3fbd847a..e17b5e60b1 100644 --- a/src/main/webapp/site/src/app/hybrid-module.ts +++ b/src/main/webapp/site/src/app/hybrid-module.ts @@ -71,6 +71,7 @@ import { ChooseImportStepComponent } from './authoring-tool/import-step/choose-i import { ChooseImportStepLocationComponent } from './authoring-tool/import-step/choose-import-step-location/choose-import-step-location.component'; import { ComponentNewWorkBadgeComponent } from './classroom-monitor/component-new-work-badge/component-new-work-badge.component'; import { StatusIconComponent } from './classroom-monitor/status-icon/status-icon.component'; +import { NodeAdvancedGeneralAuthoringComponent } from '../../../wise5/authoringTool/node/advanced/general/node-advanced-general-authoring.component'; @Component({template: ``}) export class EmptyComponent {} @@ -201,6 +202,7 @@ export class PreviewAngularJSModule { @NgModule({ declarations: [ + NodeAdvancedGeneralAuthoringComponent, AdvancedProjectAuthoringComponent, ChooseImportStepComponent, ChooseImportStepLocationComponent, diff --git a/src/main/webapp/site/src/messages.xlf b/src/main/webapp/site/src/messages.xlf index f858445afa..5555a174f3 100644 --- a/src/main/webapp/site/src/messages.xlf +++ b/src/main/webapp/site/src/messages.xlf @@ -5102,6 +5102,20 @@ 3 + + Show Save Button + + ../../wise5/authoringTool/node/advanced/general/node-advanced-general-authoring.component.html + 6 + + + + Show Submit Button + + ../../wise5/authoringTool/node/advanced/general/node-advanced-general-authoring.component.html + 14 + + Back to Unit Plan diff --git a/src/main/webapp/wise5/authoringTool/node/advanced/general/node-advanced-general-authoring.component.html b/src/main/webapp/wise5/authoringTool/node/advanced/general/node-advanced-general-authoring.component.html index 0d2ee67ca0..0a2e80e644 100644 --- a/src/main/webapp/wise5/authoringTool/node/advanced/general/node-advanced-general-authoring.component.html +++ b/src/main/webapp/wise5/authoringTool/node/advanced/general/node-advanced-general-authoring.component.html @@ -1,16 +1,18 @@
- - {{ ::"SHOW_SAVE_BUTTON" | translate }} - + + Show Save Button +
- - {{ ::"SHOW_SUBMIT_BUTTON" | translate }} - + + Show Submit Button +
diff --git a/src/main/webapp/wise5/authoringTool/node/advanced/general/node-advanced-general-authoring.component.ts b/src/main/webapp/wise5/authoringTool/node/advanced/general/node-advanced-general-authoring.component.ts index 6ebf66ac44..b40910b171 100644 --- a/src/main/webapp/wise5/authoringTool/node/advanced/general/node-advanced-general-authoring.component.ts +++ b/src/main/webapp/wise5/authoringTool/node/advanced/general/node-advanced-general-authoring.component.ts @@ -1,17 +1,19 @@ +import { Component } from "@angular/core"; import { TeacherDataService } from "../../../../services/teacherDataService"; import { TeacherProjectService } from "../../../../services/teacherProjectService"; -class NodeAdvancedGeneralAuthoringController { +@Component({ + templateUrl: 'node-advanced-general-authoring.component.html' +}) +export class NodeAdvancedGeneralAuthoringComponent { node: any; - static $inject = ['ProjectService', 'TeacherDataService']; - constructor(private ProjectService: TeacherProjectService, private TeacherDataService: TeacherDataService) { } - $onInit() { + ngOnInit() { const nodeId = this.TeacherDataService.getCurrentNodeId(); this.node = this.ProjectService.getNodeById(nodeId); } @@ -20,8 +22,3 @@ class NodeAdvancedGeneralAuthoringController { return this.ProjectService.saveProject(); } } - -export const NodeAdvancedGeneralAuthoringComponent = { - templateUrl: `/wise5/authoringTool/node/advanced/general/node-advanced-general-authoring.component.html`, - controller: NodeAdvancedGeneralAuthoringController -} diff --git a/src/main/webapp/wise5/teacher/teacher-angular-js-module.ts b/src/main/webapp/wise5/teacher/teacher-angular-js-module.ts index fcd2790da1..26f8c4d9fb 100644 --- a/src/main/webapp/wise5/teacher/teacher-angular-js-module.ts +++ b/src/main/webapp/wise5/teacher/teacher-angular-js-module.ts @@ -103,7 +103,8 @@ export function createTeacherAngularJSModule() { .component('nodeAdvancedAuthoringComponent', NodeAdvancedAuthoringComponent) .component('nodeAdvancedBranchAuthoringComponent', NodeAdvancedBranchAuthoringComponent) .component('nodeAdvancedConstraintAuthoringComponent', NodeAdvancedConstraintAuthoringComponent) - .component('nodeAdvancedGeneralAuthoringComponent', NodeAdvancedGeneralAuthoringComponent) + .directive('nodeAdvancedGeneralAuthoringComponent', downgradeComponent( + { component: NodeAdvancedGeneralAuthoringComponent }) as angular.IDirectiveFactory) .component('nodeAdvancedJsonAuthoringComponent', NodeAdvancedJsonAuthoringComponent) .component('nodeAdvancedPathAuthoringComponent', NodeAdvancedPathAuthoringComponent) .directive('advancedProjectAuthoringComponent', downgradeComponent( From 2393f6edec523c43f6b7eac8e025baf0e4d6e0f6 Mon Sep 17 00:00:00 2001 From: breity Date: Mon, 9 Nov 2020 12:14:48 -0800 Subject: [PATCH 02/11] Changed share run text in RunMenu and ShareRunDialog title; Added explanation text and option to copy unit to share run dialog. #2787 --- .../library-project-menu.component.ts | 7 +- .../teacher/run-menu/run-menu.component.html | 4 +- .../share-run-dialog.component.html | 9 +- .../share-run-dialog.component.scss | 4 - .../share-run-dialog.component.ts | 4 + .../src/app/teacher/teacher.service.spec.ts | 6 +- .../site/src/app/teacher/teacher.service.ts | 11 +- src/main/webapp/site/src/messages.xlf | 265 ++++++++++-------- .../site/src/style/components/_dialog.scss | 3 +- .../site/src/style/components/_menu.scss | 6 +- 10 files changed, 181 insertions(+), 138 deletions(-) diff --git a/src/main/webapp/site/src/app/modules/library/library-project-menu/library-project-menu.component.ts b/src/main/webapp/site/src/app/modules/library/library-project-menu/library-project-menu.component.ts index 974f7ba9e6..4b6f9801a3 100644 --- a/src/main/webapp/site/src/app/modules/library/library-project-menu/library-project-menu.component.ts +++ b/src/main/webapp/site/src/app/modules/library/library-project-menu/library-project-menu.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core'; +import { Component, Input, OnInit } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { Project } from '../../../domain/project'; import { TeacherService } from '../../../teacher/teacher.service'; @@ -59,10 +59,7 @@ export class LibraryProjectMenuComponent implements OnInit { } copyProject() { - this.dialog.open(CopyProjectDialogComponent, { - data: { project: this.project }, - panelClass: 'mat-dialog--sm' - }); + this.teacherService.copyProject(this.project); } editProject() { diff --git a/src/main/webapp/site/src/app/teacher/run-menu/run-menu.component.html b/src/main/webapp/site/src/app/teacher/run-menu/run-menu.component.html index ae8ba6dbb4..8b9b323cf6 100644 --- a/src/main/webapp/site/src/app/teacher/run-menu/run-menu.component.html +++ b/src/main/webapp/site/src/app/teacher/run-menu/run-menu.component.html @@ -18,8 +18,8 @@ Unit Info - share - Share + supervised_user_circle + Share Access diff --git a/src/main/webapp/site/src/app/teacher/share-run-dialog/share-run-dialog.component.html b/src/main/webapp/site/src/app/teacher/share-run-dialog/share-run-dialog.component.html index 50caa14ea4..a1335c2bdd 100644 --- a/src/main/webapp/site/src/app/teacher/share-run-dialog/share-run-dialog.component.html +++ b/src/main/webapp/site/src/app/teacher/share-run-dialog/share-run-dialog.component.html @@ -1,4 +1,4 @@ -

Share Classroom Unit

+

Share Classroom Access

Share Classroom Unit

{{ run.name }} (Run ID: {{ run.id }})

+ +

Sharing access allows other WISE teachers to view student work and optionally view student names, grade, manage teams, and edit unit content.

+

If you have customized the content in this unit and want to share so other teachers can use with their students, make a copy of the unit.

+ + - Enter teacher username + Find a teacher search { beforeEach(() => { TestBed.configureTestingModule({ imports: [ HttpClientTestingModule ], - providers: [ TeacherService ] + providers: [ + TeacherService, + { provide: MatDialog, useValue: {}} + ] }); }); diff --git a/src/main/webapp/site/src/app/teacher/teacher.service.ts b/src/main/webapp/site/src/app/teacher/teacher.service.ts index 7b96cde044..a5d0d36449 100644 --- a/src/main/webapp/site/src/app/teacher/teacher.service.ts +++ b/src/main/webapp/site/src/app/teacher/teacher.service.ts @@ -1,10 +1,12 @@ import { Injectable } from '@angular/core'; import { Observable, Subject } from 'rxjs'; import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; +import { MatDialog } from '@angular/material/dialog'; import { Project } from '../domain/project'; import { Teacher } from '../domain/teacher'; import { Run } from '../domain/run'; import { Course } from '../domain/course'; +import { CopyProjectDialogComponent } from '../modules/library/copy-project-dialog/copy-project-dialog.component'; @Injectable() export class TeacherService { @@ -39,8 +41,15 @@ export class TeacherService { public newRunSource$ = this.newRunSource.asObservable(); private updateProfileUrl = '/api/teacher/profile/update'; - constructor(private http: HttpClient) { } + constructor(private http: HttpClient, public dialog: MatDialog) { } + copyProject(project: Project) { + this.dialog.open(CopyProjectDialogComponent, { + data: { project: project }, + panelClass: 'mat-dialog--sm' + }); + } + getRuns(): Observable { const headers = new HttpHeaders({ 'Cache-Control': 'no-cache' }); return this.http.get(this.runsUrl, { headers: headers }); diff --git a/src/main/webapp/site/src/messages.xlf b/src/main/webapp/site/src/messages.xlf index a8c183a8e6..9e7ba8694b 100644 --- a/src/main/webapp/site/src/messages.xlf +++ b/src/main/webapp/site/src/messages.xlf @@ -211,11 +211,11 @@
app/modules/library/share-project-dialog/share-project-dialog.component.html - 19 + 22 app/teacher/share-run-dialog/share-run-dialog.component.html - 29 + 34
@@ -1032,6 +1032,89 @@ 8 + + Copy Unit + + app/modules/library/copy-project-dialog/copy-project-dialog.component.html + 1 + + + + (Unit ID: ) + + app/modules/library/copy-project-dialog/copy-project-dialog.component.html + 5 + + + + Copying creates a duplicate that will appear in “My Units”. You will be the owner and can edit the content and share the new unit with other WISE users. + + app/modules/library/copy-project-dialog/copy-project-dialog.component.html + 7 + + + + Cancel + + app/modules/library/copy-project-dialog/copy-project-dialog.component.html + 11 + + + app/teacher/list-classroom-courses-dialog/list-classroom-courses-dialog.component.html + 47 + + + app/teacher/create-run-dialog/create-run-dialog.component.html + 63 + + + app/teacher/use-with-class-warning-dialog/use-with-class-warning-dialog.component.html + 15 + + + app/teacher/edit-run-warning-dialog/edit-run-warning-dialog.component.html + 20 + + + app/student/add-project-dialog/add-project-dialog.component.html + 23 + + + app/student/team-sign-in-dialog/team-sign-in-dialog.component.html + 68 + + + app/teacher/share-run-dialog/share-run-dialog.component.html + 100 + + + app/authoring-tool/import-step/choose-import-step/choose-import-step.component.html + 62 + + + app/authoring-tool/import-step/choose-import-step-location/choose-import-step-location.component.html + 40 + + + app/authoring-tool/add-component/choose-new-component/choose-new-component.component.html + 23 + + + app/authoring-tool/add-component/choose-new-component-location/choose-new-component-location.component.html + 41 + + + + Copy + + app/modules/library/copy-project-dialog/copy-project-dialog.component.html + 17 + + + app/modules/library/library-project-menu/library-project-menu.component.html + 11 + + Share to Google Classroom @@ -1117,57 +1200,6 @@ 39 - - Cancel - - app/teacher/list-classroom-courses-dialog/list-classroom-courses-dialog.component.html - 47 - - - app/teacher/create-run-dialog/create-run-dialog.component.html - 63 - - - app/teacher/use-with-class-warning-dialog/use-with-class-warning-dialog.component.html - 15 - - - app/modules/library/copy-project-dialog/copy-project-dialog.component.html - 11 - - - app/teacher/edit-run-warning-dialog/edit-run-warning-dialog.component.html - 20 - - - app/student/add-project-dialog/add-project-dialog.component.html - 23 - - - app/student/team-sign-in-dialog/team-sign-in-dialog.component.html - 68 - - - app/teacher/share-run-dialog/share-run-dialog.component.html - 95 - - - app/authoring-tool/import-step/choose-import-step/choose-import-step.component.html - 62 - - - app/authoring-tool/import-step/choose-import-step-location/choose-import-step-location.component.html - 40 - - - app/authoring-tool/add-component/choose-new-component/choose-new-component.component.html - 23 - - - app/authoring-tool/add-component/choose-new-component-location/choose-new-component-location.component.html - 41 - - Add @@ -1205,11 +1237,11 @@ app/modules/library/share-project-dialog/share-project-dialog.component.html - 67 + 70 app/teacher/share-run-dialog/share-run-dialog.component.html - 97 + 102 app/teacher/run-settings-dialog/run-settings-dialog.component.html @@ -1564,33 +1596,47 @@ 1 - - Enter teacher username + + Sharing a curriculum unit allows other WISE teachers to use it with their own students and optionally edit the unit's content. + + app/modules/library/share-project-dialog/share-project-dialog.component.html + 6 + + + + Shared units appear in a teacher's "My Units" library. app/modules/library/share-project-dialog/share-project-dialog.component.html 7 + + + Find a teacher + + app/modules/library/share-project-dialog/share-project-dialog.component.html + 10 + app/teacher/share-run-dialog/share-run-dialog.component.html - 17 + 22 Teacher is already on shared list. app/modules/library/share-project-dialog/share-project-dialog.component.html - 24 + 27 app/teacher/share-run-dialog/share-run-dialog.component.html - 35 + 40 Name app/modules/library/share-project-dialog/share-project-dialog.component.html - 34 + 37 app/contact/contact-form/contact-form.component.html @@ -1598,90 +1644,58 @@ app/teacher/share-run-dialog/share-run-dialog.component.html - 46 + 51 Revoke app/modules/library/share-project-dialog/share-project-dialog.component.html - 40 + 43 app/teacher/share-run-dialog/share-run-dialog.component.html - 52 + 57 Permissions app/modules/library/share-project-dialog/share-project-dialog.component.html - 45 + 48 app/teacher/share-run-dialog/share-run-dialog.component.html - 57 + 62 Owner. Full permissions. app/modules/library/share-project-dialog/share-project-dialog.component.html - 47 + 50 app/teacher/share-run-dialog/share-run-dialog.component.html - 59 + 64 View & Use with Students app/modules/library/share-project-dialog/share-project-dialog.component.html - 52 + 55 Edit Unit Content app/modules/library/share-project-dialog/share-project-dialog.component.html - 56 + 59 app/teacher/share-run-dialog/share-run-dialog.component.html - 76 - - - - Copy Unit - - app/modules/library/copy-project-dialog/copy-project-dialog.component.html - 1 - - - - (Unit ID: ) - - app/modules/library/copy-project-dialog/copy-project-dialog.component.html - 5 - - - - Copying creates a duplicate that will appear in “My Units”. You will be the owner and can edit the content and share the new unit with other WISE users. - - app/modules/library/copy-project-dialog/copy-project-dialog.component.html - 7 - - - - Copy - - app/modules/library/copy-project-dialog/copy-project-dialog.component.html - 17 - - - app/modules/library/library-project-menu/library-project-menu.component.html - 11 + 81 @@ -1728,7 +1742,7 @@ app/teacher/share-run-dialog/share-run-dialog.component.html - 96 + 101 @@ -1751,10 +1765,6 @@ app/modules/library/library-project-menu/library-project-menu.component.html 17 - - app/teacher/run-menu/run-menu.component.html - 22 - Toggle filters @@ -5101,7 +5111,7 @@ Launch Unit app/student/team-sign-in-dialog/team-sign-in-dialog.component.html - 69 + 70 @@ -5407,8 +5417,8 @@ 91 - - Share Classroom Unit + + Share Classroom Access app/teacher/share-run-dialog/share-run-dialog.component.html 1 @@ -5421,46 +5431,60 @@ 6 + + Sharing access allows other WISE teachers to view student work and optionally view student names, grade, manage teams, and edit unit content. + + app/teacher/share-run-dialog/share-run-dialog.component.html + 17 + + + + If you have customized the content in this unit and want to share so other teachers can use with their students, make a copy of the unit. + + app/teacher/share-run-dialog/share-run-dialog.component.html + 18 + + View Student Work app/teacher/share-run-dialog/share-run-dialog.component.html - 64 + 69 View Student Names app/teacher/share-run-dialog/share-run-dialog.component.html - 68 + 73 Grade and Manage app/teacher/share-run-dialog/share-run-dialog.component.html - 72 + 77 Are you sure you want to make the new owner of this unit? app/teacher/share-run-dialog/share-run-dialog.component.html - 86 + 91 You will still be able to access the unit but the new owner will have the ability to take away or change your access permissions. app/teacher/share-run-dialog/share-run-dialog.component.html - 87 + 92 Transfer Ownership app/teacher/share-run-dialog/share-run-dialog.component.html - 94 + 99 @@ -5568,6 +5592,13 @@ 18 + + Share Access + + app/teacher/run-menu/run-menu.component.html + 22 + + Edit Content diff --git a/src/main/webapp/site/src/style/components/_dialog.scss b/src/main/webapp/site/src/style/components/_dialog.scss index d64d43bd69..6457d35ee8 100644 --- a/src/main/webapp/site/src/style/components/_dialog.scss +++ b/src/main/webapp/site/src/style/components/_dialog.scss @@ -5,6 +5,7 @@ .mat-dialog-content { margin: 0 -16px; padding: 0 16px; + font-size: mat-font-size($config, body-1); } .mat-dialog-content--scroll { @@ -35,6 +36,6 @@ .cdk-overlay-pane { @media (max-width: breakpoint('xs.max')) { - max-width: 90vw; + max-width: 95vw; } } diff --git a/src/main/webapp/site/src/style/components/_menu.scss b/src/main/webapp/site/src/style/components/_menu.scss index 5d76b28a7b..8b13789179 100644 --- a/src/main/webapp/site/src/style/components/_menu.scss +++ b/src/main/webapp/site/src/style/components/_menu.scss @@ -1,5 +1 @@ -.mat-menu-content { - .mat-divider { - margin: 8px 0; - } -} + From e7db56facb9103a6a2fe96b9f07aab1e7cbf5909 Mon Sep 17 00:00:00 2001 From: breity Date: Mon, 9 Nov 2020 12:16:09 -0800 Subject: [PATCH 03/11] Added explanation text to ShareUnitDialog. #2787 --- .../share-project-dialog/share-project-dialog.component.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/webapp/site/src/app/modules/library/share-project-dialog/share-project-dialog.component.html b/src/main/webapp/site/src/app/modules/library/share-project-dialog/share-project-dialog.component.html index 3ef5b66779..3f260395fa 100644 --- a/src/main/webapp/site/src/app/modules/library/share-project-dialog/share-project-dialog.component.html +++ b/src/main/webapp/site/src/app/modules/library/share-project-dialog/share-project-dialog.component.html @@ -3,8 +3,11 @@

Share Unit

{{ project.name }} (Unit ID: {{ project.id }})

+

Sharing a curriculum unit allows other WISE teachers to use it with their own students and optionally edit the unit's content.

+

Shared units appear in a teacher's "My Units" library.

+ - Enter teacher username + Find a teacher search Date: Mon, 9 Nov 2020 12:19:12 -0800 Subject: [PATCH 04/11] Standardized mat-divider style; fixed button style in TeamSignInDialog. #2787 --- .../webapp/site/src/app/features/features.component.scss | 4 ---- .../app/modules/library/library/library.component.scss | 4 ++++ .../team-sign-in-dialog.component.html | 3 ++- .../team-sign-in-dialog.component.scss | 4 ---- .../create-run-dialog/create-run-dialog.component.scss | 4 ---- .../list-classroom-courses-dialog.component.scss | 4 ---- .../run-settings-dialog.component.scss | 4 ---- src/main/webapp/site/src/style/abstracts/_mixins.scss | 8 ++++++++ 8 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/main/webapp/site/src/app/features/features.component.scss b/src/main/webapp/site/src/app/features/features.component.scss index ae98b61c8d..a507123603 100644 --- a/src/main/webapp/site/src/app/features/features.component.scss +++ b/src/main/webapp/site/src/app/features/features.component.scss @@ -115,7 +115,3 @@ margin-left: -16%; } } - -.mat-divider { - margin: 16px 0; -} diff --git a/src/main/webapp/site/src/app/modules/library/library/library.component.scss b/src/main/webapp/site/src/app/modules/library/library/library.component.scss index c1f220bb3a..52b3a10de8 100644 --- a/src/main/webapp/site/src/app/modules/library/library/library.component.scss +++ b/src/main/webapp/site/src/app/modules/library/library/library.component.scss @@ -17,6 +17,10 @@ margin-right: 8px; } } + + .mat-divider { + margin: 0; + } } .library__header { diff --git a/src/main/webapp/site/src/app/student/team-sign-in-dialog/team-sign-in-dialog.component.html b/src/main/webapp/site/src/app/student/team-sign-in-dialog/team-sign-in-dialog.component.html index 7a855a321b..fc21c0900a 100644 --- a/src/main/webapp/site/src/app/student/team-sign-in-dialog/team-sign-in-dialog.component.html +++ b/src/main/webapp/site/src/app/student/team-sign-in-dialog/team-sign-in-dialog.component.html @@ -66,5 +66,6 @@

Team Sign In

- + diff --git a/src/main/webapp/site/src/app/student/team-sign-in-dialog/team-sign-in-dialog.component.scss b/src/main/webapp/site/src/app/student/team-sign-in-dialog/team-sign-in-dialog.component.scss index a799c4a492..caa3b197f3 100644 --- a/src/main/webapp/site/src/app/student/team-sign-in-dialog/team-sign-in-dialog.component.scss +++ b/src/main/webapp/site/src/app/student/team-sign-in-dialog/team-sign-in-dialog.component.scss @@ -2,10 +2,6 @@ display: block !important; } -.mat-divider { - margin: 16px 0 16px; -} - .mat-form-field { display: block; } diff --git a/src/main/webapp/site/src/app/teacher/create-run-dialog/create-run-dialog.component.scss b/src/main/webapp/site/src/app/teacher/create-run-dialog/create-run-dialog.component.scss index fdf1067694..b254716669 100644 --- a/src/main/webapp/site/src/app/teacher/create-run-dialog/create-run-dialog.component.scss +++ b/src/main/webapp/site/src/app/teacher/create-run-dialog/create-run-dialog.component.scss @@ -1,7 +1,3 @@ -.mat-divider { - margin: 20px 0 16px; -} - .period-select { margin-right: 24px; } diff --git a/src/main/webapp/site/src/app/teacher/list-classroom-courses-dialog/list-classroom-courses-dialog.component.scss b/src/main/webapp/site/src/app/teacher/list-classroom-courses-dialog/list-classroom-courses-dialog.component.scss index f2afbb25af..d1b0584a65 100644 --- a/src/main/webapp/site/src/app/teacher/list-classroom-courses-dialog/list-classroom-courses-dialog.component.scss +++ b/src/main/webapp/site/src/app/teacher/list-classroom-courses-dialog/list-classroom-courses-dialog.component.scss @@ -4,10 +4,6 @@ '~style/abstracts/variables', '~style/abstracts/mixins'; -.mat-divider { - margin: 20px 0 16px; -} - h2 { .mat-icon { @include mat-icon-size(mat-font-size($config, display-1)); diff --git a/src/main/webapp/site/src/app/teacher/run-settings-dialog/run-settings-dialog.component.scss b/src/main/webapp/site/src/app/teacher/run-settings-dialog/run-settings-dialog.component.scss index 622f822f70..3e3b1ea891 100644 --- a/src/main/webapp/site/src/app/teacher/run-settings-dialog/run-settings-dialog.component.scss +++ b/src/main/webapp/site/src/app/teacher/run-settings-dialog/run-settings-dialog.component.scss @@ -1,7 +1,3 @@ -.mat-divider { - margin: 20px 0 16px; -} - .info-block { margin-bottom: 16px; padding: 4px; diff --git a/src/main/webapp/site/src/style/abstracts/_mixins.scss b/src/main/webapp/site/src/style/abstracts/_mixins.scss index 814fc295a3..cfc4de9e92 100644 --- a/src/main/webapp/site/src/style/abstracts/_mixins.scss +++ b/src/main/webapp/site/src/style/abstracts/_mixins.scss @@ -91,6 +91,10 @@ } } + .mat-divider { + margin: 16px 0; + } + .mat-card-actions { margin-left: 0; margin-right: 0; @@ -103,6 +107,10 @@ >.mat-card-actions:last-child { margin-bottom: 0; } + + .mat-divider { + margin: 0; + } } .mat-card--button { From a5f76cd97cfe7276770f5ef3308ccdb36b84e09b Mon Sep 17 00:00:00 2001 From: breity Date: Thu, 12 Nov 2020 16:56:38 -0800 Subject: [PATCH 05/11] Added 'Share with students' option to TeacherRunListItem; removed 'Share to Google Classroom' option from run menu. #2783 --- .../controllers/user/UserAPIController.java | 1 + src/main/webapp/site/src/app/domain/config.ts | 1 + .../site/src/app/services/config.service.ts | 4 + .../teacher/run-menu/run-menu.component.html | 5 -- .../teacher/run-menu/run-menu.component.ts | 39 --------- .../share-run-code-dialog.component.html | 45 +++++++++++ .../share-run-code-dialog.component.scss | 19 +++++ .../share-run-code-dialog.component.spec.ts | 81 +++++++++++++++++++ .../share-run-code-dialog.component.ts | 77 ++++++++++++++++++ .../teacher-run-list-item.component.html | 5 +- .../teacher-run-list-item.component.spec.ts | 7 +- .../teacher-run-list-item.component.ts | 13 ++- .../site/src/app/teacher/teacher.module.ts | 8 +- .../src/assets/img/icons/google-classroom.svg | 44 ++++++---- src/main/webapp/site/src/messages-code.xlf | 3 + src/main/webapp/site/src/messages.xlf | 68 +++++++++++++--- 16 files changed, 343 insertions(+), 77 deletions(-) create mode 100644 src/main/webapp/site/src/app/teacher/share-run-code-dialog/share-run-code-dialog.component.html create mode 100644 src/main/webapp/site/src/app/teacher/share-run-code-dialog/share-run-code-dialog.component.scss create mode 100644 src/main/webapp/site/src/app/teacher/share-run-code-dialog/share-run-code-dialog.component.spec.ts create mode 100644 src/main/webapp/site/src/app/teacher/share-run-code-dialog/share-run-code-dialog.component.ts diff --git a/src/main/java/org/wise/portal/presentation/web/controllers/user/UserAPIController.java b/src/main/java/org/wise/portal/presentation/web/controllers/user/UserAPIController.java index 50c9eeb233..633d4ace40 100644 --- a/src/main/java/org/wise/portal/presentation/web/controllers/user/UserAPIController.java +++ b/src/main/java/org/wise/portal/presentation/web/controllers/user/UserAPIController.java @@ -133,6 +133,7 @@ protected HashMap getConfig(HttpServletRequest request) { config.put("isGoogleClassroomEnabled", isGoogleClassroomEnabled()); config.put("logOutURL", contextPath + "/logout"); config.put("recaptchaPublicKey", appProperties.get("recaptcha_public_key")); + config.put("wiseHostname", appProperties.get("wise.hostname")); config.put("wise4Hostname", appProperties.get("wise4.hostname")); return config; } diff --git a/src/main/webapp/site/src/app/domain/config.ts b/src/main/webapp/site/src/app/domain/config.ts index 0e982145d4..d22e021b6e 100644 --- a/src/main/webapp/site/src/app/domain/config.ts +++ b/src/main/webapp/site/src/app/domain/config.ts @@ -6,5 +6,6 @@ export class Config { recaptchaPublicKey?: string; logOutURL: string; currentTime: number; + wiseHostname?: string; wise4Hostname?: string; } diff --git a/src/main/webapp/site/src/app/services/config.service.ts b/src/main/webapp/site/src/app/services/config.service.ts index dc5118b854..dee63db684 100644 --- a/src/main/webapp/site/src/app/services/config.service.ts +++ b/src/main/webapp/site/src/app/services/config.service.ts @@ -48,6 +48,10 @@ export class ConfigService { return this.config$.getValue().recaptchaPublicKey; } + getWISEHostname() { + return this.config$.getValue().wiseHostname; + } + getWISE4Hostname() { return this.config$.getValue().wise4Hostname; } diff --git a/src/main/webapp/site/src/app/teacher/run-menu/run-menu.component.html b/src/main/webapp/site/src/app/teacher/run-menu/run-menu.component.html index ae8ba6dbb4..f9bdf92592 100644 --- a/src/main/webapp/site/src/app/teacher/run-menu/run-menu.component.html +++ b/src/main/webapp/site/src/app/teacher/run-menu/run-menu.component.html @@ -21,11 +21,6 @@ share Share - - - Share to Google Classroom - edit Edit Content diff --git a/src/main/webapp/site/src/app/teacher/run-menu/run-menu.component.ts b/src/main/webapp/site/src/app/teacher/run-menu/run-menu.component.ts index 0643ae51b5..7b0414e8fb 100644 --- a/src/main/webapp/site/src/app/teacher/run-menu/run-menu.component.ts +++ b/src/main/webapp/site/src/app/teacher/run-menu/run-menu.component.ts @@ -8,7 +8,6 @@ import { TeacherRun } from '../teacher-run'; import { ConfigService } from '../../services/config.service'; import { RunSettingsDialogComponent } from '../run-settings-dialog/run-settings-dialog.component'; import { EditRunWarningDialogComponent } from '../edit-run-warning-dialog/edit-run-warning-dialog.component'; -import { ListClassroomCoursesDialogComponent } from '../list-classroom-courses-dialog/list-classroom-courses-dialog.component'; import { Router } from '@angular/router'; @Component({ @@ -45,36 +44,6 @@ export class RunMenuComponent implements OnInit { }); } - checkClassroomAuthorization() { - this.teacherService - .getClassroomAuthorizationUrl(this.userService.getUser().getValue().username) - .subscribe(({ authorizationUrl }) => { - if (authorizationUrl == null) { - this.getClassroomCourses(); - } else { - const authWindow = window.open(authorizationUrl, 'authorize', 'width=600,height=800'); - const timer = setInterval(() => { - if (authWindow.closed) { - clearInterval(timer); - this.checkClassroomAuthorization(); - } - }, 1000); - } - }); - } - - getClassroomCourses() { - this.teacherService - .getClassroomCourses(this.userService.getUser().getValue().username) - .subscribe(courses => { - const panelClass = courses.length ? 'mat-dialog--md' : ''; - this.dialog.open(ListClassroomCoursesDialogComponent, { - data: { run: this.run, courses }, - panelClass: panelClass - }); - }); - } - showUnitDetails() { const project = this.run.project; this.dialog.open(LibraryProjectDetailsComponent, { @@ -95,14 +64,6 @@ export class RunMenuComponent implements OnInit { return this.run.isOwner(this.userService.getUserId()); } - isGoogleUser() { - return this.userService.isGoogleUser(); - } - - isGoogleClassroomEnabled() { - return this.configService.isGoogleClassroomEnabled(); - } - isRunCompleted() { return this.run.isCompleted(this.configService.getCurrentServerTime()); } diff --git a/src/main/webapp/site/src/app/teacher/share-run-code-dialog/share-run-code-dialog.component.html b/src/main/webapp/site/src/app/teacher/share-run-code-dialog/share-run-code-dialog.component.html new file mode 100644 index 0000000000..6fad3ad93d --- /dev/null +++ b/src/main/webapp/site/src/app/teacher/share-run-code-dialog/share-run-code-dialog.component.html @@ -0,0 +1,45 @@ +

Share with Students

+ +
+

+ {{ run.project.name }} (Run ID: {{ run.id }}) +

+

+ Copy this link to share with your students:
+ +

+

+ Students with WISE accounts can also select Add Unit+ and type the Access Code:
+ +

+

+ Add as an assignment in Google Classroom:
+ +

+
+
+ + + diff --git a/src/main/webapp/site/src/app/teacher/share-run-code-dialog/share-run-code-dialog.component.scss b/src/main/webapp/site/src/app/teacher/share-run-code-dialog/share-run-code-dialog.component.scss new file mode 100644 index 0000000000..c325c00c53 --- /dev/null +++ b/src/main/webapp/site/src/app/teacher/share-run-code-dialog/share-run-code-dialog.component.scss @@ -0,0 +1,19 @@ +.share { + display: block; + text-align: center; +} + +.mat-raised-button, .mat-button { + text-transform: none; + white-space: normal; +} + +.mat-raised-button { + margin-top: 8px; + + img { + width: 32px; + margin-right: 8px; + padding: 4px 8px 4px 0; + } +} \ No newline at end of file diff --git a/src/main/webapp/site/src/app/teacher/share-run-code-dialog/share-run-code-dialog.component.spec.ts b/src/main/webapp/site/src/app/teacher/share-run-code-dialog/share-run-code-dialog.component.spec.ts new file mode 100644 index 0000000000..3dccdfb090 --- /dev/null +++ b/src/main/webapp/site/src/app/teacher/share-run-code-dialog/share-run-code-dialog.component.spec.ts @@ -0,0 +1,81 @@ +import { async, ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ShareRunCodeDialogComponent } from './share-run-code-dialog.component'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog"; +import { MatSnackBarModule } from '@angular/material/snack-bar'; +import { NO_ERRORS_SCHEMA } from "@angular/core"; +import { ConfigService } from "../../services/config.service"; +import { TeacherService } from "../teacher.service"; +import { UserService } from "../../services/user.service"; +import { TeacherRun } from "../teacher-run"; +import { Project } from '../../domain/project'; + +const runObj = new TeacherRun(); +runObj.id = 1; +runObj.runCode = 'Dog123' +const project = new Project(); +project.id = 1; +project.name = "Photosynthesis"; +runObj.project = project; + +export class MockConfigService { + getWISEHostname(): string { + return 'http://localhost:8080'; + } + + getContextPath(): string { + return ''; + } + + isGoogleClassroomEnabled() { + return true; + } +} + +export class MockTeacherService { + +} + +export class MockUserService { + isGoogleUser() { + return true; + } +} + +describe('ShareRunCodeDialogComponent', () => { + let component: ShareRunCodeDialogComponent; + let fixture: ComponentFixture; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [ ShareRunCodeDialogComponent ], + imports: [ BrowserAnimationsModule, MatDialogModule, MatSnackBarModule ], + providers: [ + { provide: ConfigService, useClass: MockConfigService }, + { provide: TeacherService, useClass: MockTeacherService }, + { provide: UserService, useClass: MockUserService }, + { provide: MatDialogRef, useValue: {} }, + { provide: MAT_DIALOG_DATA, useValue: { run: runObj } }, + ], + schemas: [ NO_ERRORS_SCHEMA ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ShareRunCodeDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should show run info and sharing url', () => { + const compiled = fixture.debugElement.nativeElement; + expect(compiled.textContent).toContain('Photosynthesis (Run ID: 1)'); + const url = `http://localhost:8080/login?accessCode=${component.run.runCode}`; + expect(compiled.textContent).toContain(url); + }); +}); diff --git a/src/main/webapp/site/src/app/teacher/share-run-code-dialog/share-run-code-dialog.component.ts b/src/main/webapp/site/src/app/teacher/share-run-code-dialog/share-run-code-dialog.component.ts new file mode 100644 index 0000000000..f691f67e20 --- /dev/null +++ b/src/main/webapp/site/src/app/teacher/share-run-code-dialog/share-run-code-dialog.component.ts @@ -0,0 +1,77 @@ +import { Component, Inject } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef, MatDialog } from '@angular/material/dialog'; +import { MatSnackBar } from '@angular/material/snack-bar'; +import { ConfigService } from '../../services/config.service'; +import { UserService } from '../../services/user.service'; +import { TeacherRun } from '../teacher-run'; +import { TeacherService } from '../teacher.service'; +import { ListClassroomCoursesDialogComponent } from '../list-classroom-courses-dialog/list-classroom-courses-dialog.component'; + +@Component({ + selector: 'app-share-run-code-dialog', + templateUrl: './share-run-code-dialog.component.html', + styleUrls: ['./share-run-code-dialog.component.scss'] +}) +export class ShareRunCodeDialogComponent { + run: TeacherRun; + code: string; + link: string; + + constructor(private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) private data: any, + private dialog: MatDialog, + private snackBar: MatSnackBar, + private teacherService: TeacherService, + private userService: UserService, + private configService: ConfigService) { + } + + ngOnInit() { + this.run = new TeacherRun(this.data.run); + this.code = this.run.runCode; + const host = this.configService.getWISEHostname() + this.configService.getContextPath(); + this.link = `${host}/login?accessCode=${this.code}`; + } + + copyMsg() { + this.snackBar.open($localize`Copied to clipboard.`); + } + + isGoogleUser() { + return this.userService.isGoogleUser(); + } + + isGoogleClassroomEnabled() { + return this.configService.isGoogleClassroomEnabled(); + } + + checkClassroomAuthorization() { + this.teacherService + .getClassroomAuthorizationUrl(this.userService.getUser().getValue().username) + .subscribe(({ authorizationUrl }) => { + if (authorizationUrl == null) { + this.getClassroomCourses(); + } else { + const authWindow = window.open(authorizationUrl, 'authorize', 'width=600,height=800'); + const timer = setInterval(() => { + if (authWindow.closed) { + clearInterval(timer); + this.checkClassroomAuthorization(); + } + }, 1000); + } + }); + } + + getClassroomCourses() { + this.teacherService + .getClassroomCourses(this.userService.getUser().getValue().username) + .subscribe(courses => { + const panelClass = courses.length ? 'mat-dialog--md' : ''; + this.dialog.open(ListClassroomCoursesDialogComponent, { + data: { run: this.run, courses }, + panelClass: panelClass + }); + }); + } +} diff --git a/src/main/webapp/site/src/app/teacher/teacher-run-list-item/teacher-run-list-item.component.html b/src/main/webapp/site/src/app/teacher/teacher-run-list-item/teacher-run-list-item.component.html index e353343d85..90be4e46d0 100644 --- a/src/main/webapp/site/src/app/teacher/teacher-run-list-item/teacher-run-list-item.component.html +++ b/src/main/webapp/site/src/app/teacher/teacher-run-list-item/teacher-run-list-item.component.html @@ -28,7 +28,10 @@ -
Access Code: {{ run.runCode }}
+
Shared by {{run.owner.firstName}} {{run.owner.lastName}}
diff --git a/src/main/webapp/site/src/app/teacher/teacher-run-list-item/teacher-run-list-item.component.spec.ts b/src/main/webapp/site/src/app/teacher/teacher-run-list-item/teacher-run-list-item.component.spec.ts index d6acd3fc2b..1ab2531602 100644 --- a/src/main/webapp/site/src/app/teacher/teacher-run-list-item/teacher-run-list-item.component.spec.ts +++ b/src/main/webapp/site/src/app/teacher/teacher-run-list-item/teacher-run-list-item.component.spec.ts @@ -6,6 +6,7 @@ import { TeacherRun } from "../teacher-run"; import { ConfigService } from "../../services/config.service"; import { NO_ERRORS_SCHEMA } from "@angular/core"; import { MomentModule } from "ngx-moment"; +import { MatDialogModule } from "@angular/material/dialog"; import { configureTestSuite } from 'ng-bullet'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { RouterTestingModule } from '@angular/router/testing'; @@ -33,7 +34,7 @@ describe('TeacherRunListItemComponent', () => { configureTestSuite(() => { TestBed.configureTestingModule({ declarations: [ TeacherRunListItemComponent ], - imports: [ MomentModule, BrowserAnimationsModule, RouterTestingModule ], + imports: [ MatDialogModule, MomentModule, BrowserAnimationsModule, RouterTestingModule ], providers: [ { provide: TeacherService, useClass: MockTeacherService }, { provide: ConfigService, useClass: MockConfigService } @@ -52,6 +53,7 @@ describe('TeacherRunListItemComponent', () => { run.endTime = new Date('2018-10-18T23:59:59.0').getTime(); run.numStudents = 30; run.periods = ['1', '2']; + run.runCode = 'Dog123' const project = new Project(); project.id = 1; project.name = "Photosynthesis"; @@ -68,5 +70,8 @@ describe('TeacherRunListItemComponent', () => { it('should show run info', () => { const compiled = fixture.debugElement.nativeElement; expect(compiled.textContent).toContain('Photosynthesis'); + expect(compiled.textContent).toContain('2 periods'); + expect(compiled.textContent).toContain('30 students'); + expect(compiled.textContent).toContain('Access Code: Dog123'); }); }); diff --git a/src/main/webapp/site/src/app/teacher/teacher-run-list-item/teacher-run-list-item.component.ts b/src/main/webapp/site/src/app/teacher/teacher-run-list-item/teacher-run-list-item.component.ts index 12332a8278..57f0177d6d 100644 --- a/src/main/webapp/site/src/app/teacher/teacher-run-list-item/teacher-run-list-item.component.ts +++ b/src/main/webapp/site/src/app/teacher/teacher-run-list-item/teacher-run-list-item.component.ts @@ -5,7 +5,8 @@ import { TeacherRun } from "../teacher-run"; import { ConfigService } from "../../services/config.service"; import { flash } from '../../animations'; import { Router } from '@angular/router'; - +import { MatDialog } from '@angular/material/dialog'; +import { ShareRunCodeDialogComponent } from '../share-run-code-dialog/share-run-code-dialog.component'; @Component({ selector: 'app-teacher-run-list-item', @@ -28,7 +29,8 @@ export class TeacherRunListItemComponent implements OnInit { constructor(private sanitizer: DomSanitizer, private configService: ConfigService, private router: Router, - private elRef: ElementRef) { + private elRef: ElementRef, + private dialog: MatDialog,) { this.sanitizer = sanitizer; } @@ -94,4 +96,11 @@ export class TeacherRunListItemComponent implements OnInit { isRunCompleted(run) { return run.isCompleted(this.configService.getCurrentServerTime()); } + + shareCode() { + this.dialog.open(ShareRunCodeDialogComponent, { + data: { run: this.run }, + panelClass: 'mat-dialog--sm' + }); + } } diff --git a/src/main/webapp/site/src/app/teacher/teacher.module.ts b/src/main/webapp/site/src/app/teacher/teacher.module.ts index b98c020540..cf56de3c28 100644 --- a/src/main/webapp/site/src/app/teacher/teacher.module.ts +++ b/src/main/webapp/site/src/app/teacher/teacher.module.ts @@ -26,6 +26,7 @@ import { MatSnackBarModule } from '@angular/material/snack-bar'; import { MatTableModule } from '@angular/material/table'; import { MatTabsModule } from '@angular/material/tabs'; import { MatTooltipModule } from '@angular/material/tooltip'; +import { ClipboardModule } from '@angular/cdk/clipboard'; import { RunMenuComponent } from './run-menu/run-menu.component'; import { CreateRunDialogComponent } from './create-run-dialog/create-run-dialog.component'; import { LibraryModule } from "../modules/library/library.module"; @@ -37,6 +38,7 @@ import { RunSettingsDialogComponent } from './run-settings-dialog/run-settings-d import { UseWithClassWarningDialogComponent } from './use-with-class-warning-dialog/use-with-class-warning-dialog.component'; import { EditRunWarningDialogComponent } from './edit-run-warning-dialog/edit-run-warning-dialog.component'; import { ListClassroomCoursesDialogComponent } from './list-classroom-courses-dialog/list-classroom-courses-dialog.component'; +import { ShareRunCodeDialogComponent } from './share-run-code-dialog/share-run-code-dialog.component'; const materialModules = [ MatAutocompleteModule, MatButtonModule, MatCardModule, MatCheckboxModule, @@ -54,7 +56,8 @@ const materialModules = [ MomentModule, SharedModule, TeacherRoutingModule, - TimelineModule + TimelineModule, + ClipboardModule ], declarations: [ CreateRunDialogComponent, @@ -69,7 +72,8 @@ const materialModules = [ EditProfileComponent, UseWithClassWarningDialogComponent, EditRunWarningDialogComponent, - ListClassroomCoursesDialogComponent + ListClassroomCoursesDialogComponent, + ShareRunCodeDialogComponent ], providers: [ AuthGuard diff --git a/src/main/webapp/site/src/assets/img/icons/google-classroom.svg b/src/main/webapp/site/src/assets/img/icons/google-classroom.svg index 8715120da9..541b7039b6 100644 --- a/src/main/webapp/site/src/assets/img/icons/google-classroom.svg +++ b/src/main/webapp/site/src/assets/img/icons/google-classroom.svg @@ -1,16 +1,28 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/site/src/messages-code.xlf b/src/main/webapp/site/src/messages-code.xlf index 1523829291..40563e0a3f 100644 --- a/src/main/webapp/site/src/messages-code.xlf +++ b/src/main/webapp/site/src/messages-code.xlf @@ -338,6 +338,9 @@ The JSON is invalid. Invalid JSON will not be saved.\nClick "OK" to revert back to the last valid JSON.\nClick "Cancel" to keep the invalid JSON open so you can fix it. + + Copied to clipboard. + \ No newline at end of file diff --git a/src/main/webapp/site/src/messages.xlf b/src/main/webapp/site/src/messages.xlf index 91e736e203..28c71006a5 100644 --- a/src/main/webapp/site/src/messages.xlf +++ b/src/main/webapp/site/src/messages.xlf @@ -533,6 +533,10 @@ app/modules/library/personal-library/personal-library-details.html 9
+ + app/teacher/share-run-code-dialog/share-run-code-dialog.component.html + 44 +
WISE Terms of Use & Privacy Policy @@ -1046,8 +1050,8 @@ 6 - app/teacher/run-menu/run-menu.component.html - 27 + app/teacher/share-run-code-dialog/share-run-code-dialog.component.html + 34 @@ -1374,7 +1378,7 @@ app/teacher/teacher-run-list-item/teacher-run-list-item.component.html - 31 + 32 @@ -1466,7 +1470,7 @@ app/teacher/teacher-run-list-item/teacher-run-list-item.component.html - 52 + 55 @@ -1704,6 +1708,10 @@ app/teacher/edit-run-warning-dialog/edit-run-warning-dialog.component.html 9 + + app/teacher/share-run-code-dialog/share-run-code-dialog.component.html + 5 + app/teacher/share-run-dialog/share-run-dialog.component.html 14 @@ -5166,7 +5174,7 @@ app/teacher/run-menu/run-menu.component.html - 35 + 30 @@ -5177,7 +5185,7 @@ app/teacher/teacher-run-list-item/teacher-run-list-item.component.html - 83 + 86 @@ -5359,6 +5367,34 @@ 30 + + Share with Students + + app/teacher/share-run-code-dialog/share-run-code-dialog.component.html + 1 + + + + Copy this link to share with your students: + + app/teacher/share-run-code-dialog/share-run-code-dialog.component.html + 8 + + + + Students with WISE accounts can also select Add Unit+ and type the Access Code: + + app/teacher/share-run-code-dialog/share-run-code-dialog.component.html + 19 + + + + Add as an assignment in Google Classroom: + + app/teacher/share-run-code-dialog/share-run-code-dialog.component.html + 30 + + periods @@ -5407,32 +5443,39 @@ 26 + + Share with students + + app/teacher/teacher-run-list-item/teacher-run-list-item.component.html + 33 + + Shared by app/teacher/teacher-run-list-item/teacher-run-list-item.component.html - 32 + 35 (Legacy Unit) app/teacher/teacher-run-list-item/teacher-run-list-item.component.html - 54 + 57 Last student login: app/teacher/teacher-run-list-item/teacher-run-list-item.component.html - 77 + 80 Teacher Tools app/teacher/teacher-run-list-item/teacher-run-list-item.component.html - 91 + 94 @@ -5600,7 +5643,7 @@ Edit Content app/teacher/run-menu/run-menu.component.html - 31 + 26 @@ -6257,6 +6300,9 @@ Click "OK" to revert back to the last valid JSON. Click "Cancel" to keep the invalid JSON open so you can fix it. + + Copied to clipboard. + From 35b658a1274bac3eb69ecb227d83ba8803689dab Mon Sep 17 00:00:00 2001 From: breity Date: Fri, 13 Nov 2020 11:19:00 -0800 Subject: [PATCH 06/11] Updated UserAPIController test with wise.hostname addition to getConfig. #2783 --- .../presentation/web/controllers/user/UserAPIControllerTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/org/wise/portal/presentation/web/controllers/user/UserAPIControllerTest.java b/src/test/java/org/wise/portal/presentation/web/controllers/user/UserAPIControllerTest.java index 47ab8e7357..11c392e136 100644 --- a/src/test/java/org/wise/portal/presentation/web/controllers/user/UserAPIControllerTest.java +++ b/src/test/java/org/wise/portal/presentation/web/controllers/user/UserAPIControllerTest.java @@ -64,6 +64,7 @@ public void getConfig_WISEContextPath_ReturnConfig() { expect(appProperties.get("google_analytics_id")).andReturn("UA-XXXXXX-1"); expect(appProperties.get("recaptcha_public_key")).andReturn("recaptcha-123-abc"); expect(appProperties.get("wise4.hostname")).andReturn("http://localhost:8080/legacy"); + expect(appProperties.get("wise.hostname")).andReturn("http://localhost:8080"); replay(appProperties); HashMap config = userAPIController.getConfig(request); assertEquals("wise", config.get("contextPath")); From 5740c4e530a4e8b31aec5dca5f77cc4f7a8690d1 Mon Sep 17 00:00:00 2001 From: breity Date: Mon, 16 Nov 2020 11:45:11 -0800 Subject: [PATCH 07/11] Fixed bug that was preventing PersonalLibrary component from updating to show new copied unit. #2787 --- .../copy-project-dialog.component.ts | 9 +++----- .../library-project-menu.component.ts | 14 ++++++------- .../personal-library.component.ts | 21 ++++++++++++++----- .../share-run-dialog.component.spec.ts | 7 ++++++- .../share-run-dialog.component.ts | 7 ++++--- .../site/src/app/teacher/teacher.service.ts | 6 +++--- 6 files changed, 39 insertions(+), 25 deletions(-) diff --git a/src/main/webapp/site/src/app/modules/library/copy-project-dialog/copy-project-dialog.component.ts b/src/main/webapp/site/src/app/modules/library/copy-project-dialog/copy-project-dialog.component.ts index 3792d2f106..054eb89ccc 100644 --- a/src/main/webapp/site/src/app/modules/library/copy-project-dialog/copy-project-dialog.component.ts +++ b/src/main/webapp/site/src/app/modules/library/copy-project-dialog/copy-project-dialog.component.ts @@ -1,17 +1,18 @@ -import { Component, OnInit, Inject } from '@angular/core'; +import { Component, Inject } from '@angular/core'; import { LibraryProjectDetailsComponent } from "../library-project-details/library-project-details.component"; import { MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog'; import { finalize } from 'rxjs/operators'; import { LibraryProject } from "../libraryProject"; import { LibraryService } from "../../../services/library.service"; import { MatSnackBar } from '@angular/material/snack-bar'; +import { Subscription } from 'rxjs'; @Component({ selector: 'app-copy-project-dialog', templateUrl: './copy-project-dialog.component.html', styleUrls: ['./copy-project-dialog.component.scss'] }) -export class CopyProjectDialogComponent implements OnInit { +export class CopyProjectDialogComponent { isCopying: boolean = false; @@ -20,15 +21,11 @@ export class CopyProjectDialogComponent implements OnInit { @Inject(MAT_DIALOG_DATA) public data: any, private libraryService: LibraryService, private snackBar: MatSnackBar) { - this.libraryService.newProjectSource$.subscribe(() => { this.dialog.closeAll(); }); } - ngOnInit() { - } - copy() { this.isCopying = true; this.libraryService.copyProject(this.data.project.id) diff --git a/src/main/webapp/site/src/app/modules/library/library-project-menu/library-project-menu.component.ts b/src/main/webapp/site/src/app/modules/library/library-project-menu/library-project-menu.component.ts index 4b6f9801a3..9202ac757b 100644 --- a/src/main/webapp/site/src/app/modules/library/library-project-menu/library-project-menu.component.ts +++ b/src/main/webapp/site/src/app/modules/library/library-project-menu/library-project-menu.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { Project } from '../../../domain/project'; import { TeacherService } from '../../../teacher/teacher.service'; @@ -13,7 +13,7 @@ import { EditRunWarningDialogComponent } from '../../../teacher/edit-run-warning templateUrl: './library-project-menu.component.html', styleUrls: ['./library-project-menu.component.scss'] }) -export class LibraryProjectMenuComponent implements OnInit { +export class LibraryProjectMenuComponent { @Input() project: Project; @@ -27,10 +27,10 @@ export class LibraryProjectMenuComponent implements OnInit { isChild: boolean = false; constructor( - public dialog: MatDialog, - public teacherService: TeacherService, - public userService: UserService, - public configService: ConfigService + private dialog: MatDialog, + private teacherService: TeacherService, + private userService: UserService, + private configService: ConfigService ) {} ngOnInit() { @@ -59,7 +59,7 @@ export class LibraryProjectMenuComponent implements OnInit { } copyProject() { - this.teacherService.copyProject(this.project); + this.teacherService.copyProject(this.project, this.dialog); } editProject() { diff --git a/src/main/webapp/site/src/app/modules/library/personal-library/personal-library.component.ts b/src/main/webapp/site/src/app/modules/library/personal-library/personal-library.component.ts index 6976f57e54..110582080f 100644 --- a/src/main/webapp/site/src/app/modules/library/personal-library/personal-library.component.ts +++ b/src/main/webapp/site/src/app/modules/library/personal-library/personal-library.component.ts @@ -3,6 +3,7 @@ import { LibraryProject } from "../libraryProject"; import { LibraryService } from "../../../services/library.service"; import { LibraryComponent } from "../library/library.component"; import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { Subscription } from 'rxjs'; @Component({ selector: 'app-personal-library', @@ -15,20 +16,27 @@ export class PersonalLibraryComponent extends LibraryComponent { filteredProjects: LibraryProject[] = []; personalProjects: LibraryProject[] = []; sharedProjects: LibraryProject[] = []; + personalLibraryProjectsSourceSubscription: Subscription; + sharedLibraryProjectsSourceSubscription: Subscription; + newProjectSourceSubscription: Subscription; - constructor(libraryService: LibraryService, public dialog: MatDialog) { + constructor(libraryService: LibraryService, private dialog: MatDialog) { super(libraryService); this.libraryService = libraryService; + } - this.libraryService.personalLibraryProjectsSource$.subscribe((personalProjects: LibraryProject[]) => { + ngOnInit() { + this.personalLibraryProjectsSourceSubscription = + this.libraryService.personalLibraryProjectsSource$.subscribe((personalProjects: LibraryProject[]) => { this.personalProjects = personalProjects; this.updateProjects(); }); - this.libraryService.sharedLibraryProjectsSource$.subscribe((sharedProjects: LibraryProject[]) => { + this.sharedLibraryProjectsSourceSubscription = + this.libraryService.sharedLibraryProjectsSource$.subscribe((sharedProjects: LibraryProject[]) => { this.sharedProjects = sharedProjects; this.updateProjects(); }); - this.libraryService.newProjectSource$.subscribe(project => { + this.newProjectSourceSubscription = this.libraryService.newProjectSource$.subscribe(project => { if (project) { project.isHighlighted = true; this.projects.unshift(project); @@ -37,7 +45,10 @@ export class PersonalLibraryComponent extends LibraryComponent { }); } - ngOnInit() { + ngOnDestroy() { + this.personalLibraryProjectsSourceSubscription.unsubscribe(); + this.sharedLibraryProjectsSourceSubscription.unsubscribe(); + this.newProjectSourceSubscription.unsubscribe(); } combinePersonalAndSharedProjects() { diff --git a/src/main/webapp/site/src/app/teacher/share-run-dialog/share-run-dialog.component.spec.ts b/src/main/webapp/site/src/app/teacher/share-run-dialog/share-run-dialog.component.spec.ts index 4d10ef499a..9152e7802a 100644 --- a/src/main/webapp/site/src/app/teacher/share-run-dialog/share-run-dialog.component.spec.ts +++ b/src/main/webapp/site/src/app/teacher/share-run-dialog/share-run-dialog.component.spec.ts @@ -4,7 +4,7 @@ import { Observable } from "rxjs"; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { TeacherService } from "../teacher.service"; import { Run } from "../../domain/run"; -import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog"; +import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog"; import { MatAutocompleteModule } from '@angular/material/autocomplete'; import { MatSnackBarModule } from '@angular/material/snack-bar'; import { MatTableModule } from '@angular/material/table'; @@ -85,6 +85,10 @@ describe('ShareRunDialogComponent', () => { { provide: TeacherService, useClass: MockTeacherService }, { provide: MatDialogRef, useValue: {} }, { provide: MAT_DIALOG_DATA, useValue: { run: runObj } }, + { provide: MatDialog, useValue: { + closeAll: () => { + } + }}, { provide: UserService, useClass: MockUserService } ], schemas: [ NO_ERRORS_SCHEMA ] @@ -95,6 +99,7 @@ describe('ShareRunDialogComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(ShareRunDialogComponent); component = fixture.componentInstance; + component.dialog = TestBed.get(MatDialog); fixture.detectChanges(); }); diff --git a/src/main/webapp/site/src/app/teacher/share-run-dialog/share-run-dialog.component.ts b/src/main/webapp/site/src/app/teacher/share-run-dialog/share-run-dialog.component.ts index f4718c1cc1..921a9999ca 100644 --- a/src/main/webapp/site/src/app/teacher/share-run-dialog/share-run-dialog.component.ts +++ b/src/main/webapp/site/src/app/teacher/share-run-dialog/share-run-dialog.component.ts @@ -1,6 +1,6 @@ import { Component, Inject } from '@angular/core'; import { TeacherService } from "../teacher.service"; -import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { MAT_DIALOG_DATA, MatDialogRef, MatDialog } from '@angular/material/dialog'; import { MatSnackBar } from '@angular/material/snack-bar'; import { MatTableDataSource } from "@angular/material/table"; import { ShareItemDialogComponent } from "../../modules/library/share-item-dialog/share-item-dialog.component"; @@ -28,7 +28,8 @@ export class ShareRunDialogComponent extends ShareItemDialogComponent { public teacherService: TeacherService, private userService: UserService, private utilService: UtilService, - public snackBar: MatSnackBar) { + public snackBar: MatSnackBar, + public dialog: MatDialog) { super(dialogRef, data, teacherService, snackBar); this.teacherService.getRun(this.data.run.id).subscribe((run: TeacherRun) => { this.run = new TeacherRun(run); @@ -184,6 +185,6 @@ export class ShareRunDialogComponent extends ShareItemDialogComponent { } copyProject() { - this.teacherService.copyProject(this.project); + this.teacherService.copyProject(this.project, this.dialog); } } diff --git a/src/main/webapp/site/src/app/teacher/teacher.service.ts b/src/main/webapp/site/src/app/teacher/teacher.service.ts index a5d0d36449..9e3409fc95 100644 --- a/src/main/webapp/site/src/app/teacher/teacher.service.ts +++ b/src/main/webapp/site/src/app/teacher/teacher.service.ts @@ -41,10 +41,10 @@ export class TeacherService { public newRunSource$ = this.newRunSource.asObservable(); private updateProfileUrl = '/api/teacher/profile/update'; - constructor(private http: HttpClient, public dialog: MatDialog) { } + constructor(private http: HttpClient) { } - copyProject(project: Project) { - this.dialog.open(CopyProjectDialogComponent, { + copyProject(project: Project, dialog: MatDialog) { + dialog.open(CopyProjectDialogComponent, { data: { project: project }, panelClass: 'mat-dialog--sm' }); From 978aa019f90c26ecdfcf938c6dac4d746ecfa057 Mon Sep 17 00:00:00 2001 From: Hiroki Terashima Date: Mon, 16 Nov 2020 15:34:22 -0800 Subject: [PATCH 08/11] Changed ComponentAnnotation to TypeScript --- .../componentAnnotations.js | 231 ------------------ .../componentAnnotations.ts | 159 ++++++++++++ 2 files changed, 159 insertions(+), 231 deletions(-) delete mode 100644 src/main/webapp/wise5/directives/componentAnnotations/componentAnnotations.js create mode 100644 src/main/webapp/wise5/directives/componentAnnotations/componentAnnotations.ts diff --git a/src/main/webapp/wise5/directives/componentAnnotations/componentAnnotations.js b/src/main/webapp/wise5/directives/componentAnnotations/componentAnnotations.js deleted file mode 100644 index 75ac6dda09..0000000000 --- a/src/main/webapp/wise5/directives/componentAnnotations/componentAnnotations.js +++ /dev/null @@ -1,231 +0,0 @@ -'use strict'; - -class ComponentAnnotationsController { - constructor($scope, - $element, // TODO remove after verifying that this is not being used - $filter, - $mdDialog, - $timeout, - ConfigService, - ProjectService, - StudentDataService) { - this.$scope = $scope; - this.$filter = $filter; - this.$mdDialog = $mdDialog; - this.ConfigService = ConfigService; - this.ProjectService = ProjectService; - this.StudentDataService = StudentDataService; - this.$translate = this.$filter('translate'); - this.maxScoreDisplay = (parseInt(this.maxScore) > 0) ? '/' + this.maxScore : ''; - this.themeSettings = this.ProjectService.getThemeSettings(); - this.hideComponentScores = this.themeSettings.hideComponentScores; - this.nodeId = null; - this.componentId = null; - this.latestAnnotationTime = null; - this.isNew = false; - this.label = ''; - this.icon = 'person'; // (default to person/teacher) - this.showScore = true; - this.showComment = true; - - this.studentWorkSavedToServerSubscription = - this.StudentDataService.studentWorkSavedToServer$.subscribe((args) => { - let nodeId = args.studentWork.nodeId; - let componentId = args.studentWork.componentId; - if (nodeId === this.nodeId && componentId === this.componentId) { - this.isNew = false; - } - }); - - /* used to pop up annotation - $timeout(() => { - this.$mdDialog.show({ - contentElement: '#componentAnnotationsCard', - parent: angular.element(document.body) - }); - }); - */ - - /* uncomment me and use me instead of timeout when we switch to angular 2 - this.$onAfterViewInit = () => { - this.$mdDialog.show({ - contentElement: '#componentAnnotationsCard', - parent: angular.element(document.body) - }); - }; - */ - - this.$onChanges = (changes) => { - //if (changes.annotations) { - //this.annotations = angular.copy(changes.annotations.currentValue); - this.processAnnotations(); - //} - }; - - this.$scope.$on('$destroy', () => { - this.ngOnDestroy(); - }); - } - - ngOnDestroy() { - this.unsubscribeAll(); - } - - unsubscribeAll() { - this.studentWorkSavedToServerSubscription.unsubscribe(); - } - - closeDialog() { - this.$mdDialog.hide(); - } - - /** - * Get the most recent annotation (from the current score and comment annotations) - * @return Object (latest annotation) - */ - getLatestAnnotation() { - let latest = null; - - if (this.annotations.comment || this.annotations.score) { - let commentSaveTime = this.annotations.comment ? this.annotations.comment.serverSaveTime : 0; - let scoreSaveTime = this.annotations.score ? this.annotations.score.serverSaveTime : 0; - - if (commentSaveTime >= scoreSaveTime) { - latest = this.annotations.comment; - } else if (scoreSaveTime > commentSaveTime) { - latest = this.annotations.score; - } - } - - return latest; - } - - /** - * Calculate the save time of the latest annotation - * @return Number (latest annotation post time) - */ - getLatestAnnotationTime() { - let latest = this.getLatestAnnotation(); - let time = null; - - if (latest) { - let serverSaveTime = latest.serverSaveTime; - time = this.ConfigService.convertToClientTimestamp(serverSaveTime) - } - - return time; - } - - /** - * Find nodeExited time of the latest node visit for this component - * @return Number (latest node exit time) - */ - getLatestVisitTime() { - let nodeEvents = this.StudentDataService.getEventsByNodeId(this.nodeId); - let n = nodeEvents.length - 1; - let visitTime = null; - - for (let i = n; i > 0; i--) { - let event = nodeEvents[i]; - if (event.event === 'nodeExited') { - visitTime = this.ConfigService.convertToClientTimestamp(event.serverSaveTime); - break; - } - } - - return visitTime; - } - - /** - * Find and the latest save time for this component - * @return Number (latest save time) - */ - getLatestSaveTime() { - let latestState = this.StudentDataService.getLatestComponentStateByNodeIdAndComponentId(this.nodeId, this.componentId); - let saveTime = null; - - if (latestState) { - saveTime = this.ConfigService.convertToClientTimestamp(latestState.serverSaveTime); - } - - return saveTime; - } - - /** - * Check whether the current annotation for this component is new to the - * workgroup (i.e. if the workgroup hasn't seen the annotation on a previous - * node visit and the latest annotation came after the latest component state) - * @return Boolean (true or false) - */ - isNewAnnotation() { - let latestVisitTime = this.getLatestVisitTime(); - let latestSaveTime = this.getLatestSaveTime(); - let latestAnnotationTime = this.getLatestAnnotationTime(); - let isNew = true; - - if (latestVisitTime && (latestVisitTime > latestAnnotationTime)) { - isNew = false; - } - - if (latestSaveTime && (latestSaveTime > latestAnnotationTime)) { - isNew = false; - } - - return isNew; - } - - /** - * Set the label based on whether this is an automated or teacher annotation - **/ - setLabelAndIcon() { - const latest = this.getLatestAnnotation(); - if (latest) { - if (latest.type === 'autoComment' || latest.type === 'autoScore') { - this.label = this.$translate('automatedFeedbackLabel'); - this.icon = 'keyboard'; - } else { - this.label = this.$translate('teacherFeedbackLabel'); - this.icon = 'person'; - } - } - } - - processAnnotations() { - if (this.annotations != null) { - if (this.annotations.comment || this.annotations.score) { - this.nodeId = this.annotations.comment ? - this.annotations.comment.nodeId : this.annotations.score.nodeId; - this.componentId = this.annotations.comment ? - this.annotations.comment.componentId : this.annotations.score.nodeId; - this.showScore = this.annotations.score != null && - this.ProjectService.displayAnnotation(this.annotations.score); - this.showComment = this.annotations.comment != null && - this.ProjectService.displayAnnotation(this.annotations.comment); - this.setLabelAndIcon(); - } - } - } -} - -ComponentAnnotationsController.$inject = [ - '$scope', - '$element', - '$filter', - '$mdDialog', - '$timeout', - 'ConfigService', - 'ProjectService', - 'StudentDataService' -]; - -const ComponentAnnotations = { - bindings: { - annotations: '<', - maxScore: '<' - }, - templateUrl: 'wise5/directives/componentAnnotations/componentAnnotations.html', - controller: ComponentAnnotationsController, - controllerAs: 'componentAnnotationsCtrl' -}; - -export default ComponentAnnotations; diff --git a/src/main/webapp/wise5/directives/componentAnnotations/componentAnnotations.ts b/src/main/webapp/wise5/directives/componentAnnotations/componentAnnotations.ts new file mode 100644 index 0000000000..726f76ea42 --- /dev/null +++ b/src/main/webapp/wise5/directives/componentAnnotations/componentAnnotations.ts @@ -0,0 +1,159 @@ +'use strict'; + +import { Directive } from "@angular/core"; +import { Subscription } from "rxjs"; +import { ConfigService } from "../../services/configService"; +import { StudentDataService } from "../../services/studentDataService"; +import { VLEProjectService } from "../../vle/vleProjectService"; + +@Directive() +class ComponentAnnotationsController { + + $translate: any; + annotations: any; + maxScoreDisplay: string; + nodeId: string = null; + componentId: string = null + latestAnnotationTime: any = null; + isNew: boolean; + label: string = ''; + maxScore: string; + icon: string = 'person'; + showScore: boolean = true; + showComment: boolean = true; + studentWorkSavedToServerSubscription: Subscription; + + static $inject = ['$filter', 'ConfigService', 'ProjectService', 'StudentDataService']; + + constructor(private $filter: any, + private ConfigService: ConfigService, + private ProjectService: VLEProjectService, + private StudentDataService: StudentDataService) { + this.$translate = this.$filter('translate'); + } + + $onInit() { + this.maxScoreDisplay = (parseInt(this.maxScore) > 0) ? '/' + this.maxScore : ''; + this.studentWorkSavedToServerSubscription = + this.StudentDataService.studentWorkSavedToServer$.subscribe(({studentWork}) => { + if (studentWork.nodeId === this.nodeId && studentWork.componentId === this.componentId) { + this.isNew = false; + } + }); + } + + $onChanges() { + this.processAnnotations(); + }; + + $onDestroy() { + this.ngOnDestroy(); + } + + ngOnDestroy() { + this.unsubscribeAll(); + } + + unsubscribeAll() { + this.studentWorkSavedToServerSubscription.unsubscribe(); + } + + processAnnotations() { + if (this.annotations.comment || this.annotations.score) { + this.nodeId = this.annotations.comment ? + this.annotations.comment.nodeId : this.annotations.score.nodeId; + this.componentId = this.annotations.comment ? + this.annotations.comment.componentId : this.annotations.score.nodeId; + this.showScore = this.annotations.score != null && + this.ProjectService.displayAnnotation(this.annotations.score); + this.showComment = this.annotations.comment != null && + this.ProjectService.displayAnnotation(this.annotations.comment); + this.setLabelAndIcon(); + } + } + + getLatestAnnotation() { + let latest = null; + if (this.annotations.comment || this.annotations.score) { + let commentSaveTime = this.annotations.comment ? this.annotations.comment.serverSaveTime : 0; + let scoreSaveTime = this.annotations.score ? this.annotations.score.serverSaveTime : 0; + if (commentSaveTime >= scoreSaveTime) { + latest = this.annotations.comment; + } else if (scoreSaveTime > commentSaveTime) { + latest = this.annotations.score; + } + } + return latest; + } + + getLatestAnnotationTime() { + const latest = this.getLatestAnnotation(); + if (latest) { + return this.ConfigService.convertToClientTimestamp(latest.serverSaveTime) + } + return null; + } + + getLatestVisitTime() { + let nodeEvents = this.StudentDataService.getEventsByNodeId(this.nodeId); + let n = nodeEvents.length - 1; + let visitTime = null; + for (let i = n; i > 0; i--) { + let event = nodeEvents[i]; + if (event.event === 'nodeExited') { + visitTime = this.ConfigService.convertToClientTimestamp(event.serverSaveTime); + break; + } + } + return visitTime; + } + + getLatestSaveTime() { + const latestState = this.StudentDataService.getLatestComponentStateByNodeIdAndComponentId( + this.nodeId, this.componentId); + let saveTime = null; + if (latestState) { + saveTime = this.ConfigService.convertToClientTimestamp(latestState.serverSaveTime); + } + return saveTime; + } + + isNewAnnotation() { + let latestVisitTime = this.getLatestVisitTime(); + let latestSaveTime = this.getLatestSaveTime(); + let latestAnnotationTime = this.getLatestAnnotationTime(); + let isNew = true; + if (latestVisitTime && (latestVisitTime > latestAnnotationTime)) { + isNew = false; + } + if (latestSaveTime && (latestSaveTime > latestAnnotationTime)) { + isNew = false; + } + return isNew; + } + + setLabelAndIcon() { + const latest = this.getLatestAnnotation(); + if (latest) { + if (latest.type === 'autoComment' || latest.type === 'autoScore') { + this.label = this.$translate('automatedFeedbackLabel'); + this.icon = 'keyboard'; + } else { + this.label = this.$translate('teacherFeedbackLabel'); + this.icon = 'person'; + } + } + } +} + +const ComponentAnnotations = { + bindings: { + annotations: '<', + maxScore: '<' + }, + templateUrl: 'wise5/directives/componentAnnotations/componentAnnotations.html', + controller: ComponentAnnotationsController, + controllerAs: 'componentAnnotationsCtrl' +}; + +export default ComponentAnnotations; From fc71dd32d269b4d3a2b8c75b582fca3484f8190f Mon Sep 17 00:00:00 2001 From: Hiroki Terashima Date: Mon, 16 Nov 2020 17:53:07 -0800 Subject: [PATCH 09/11] Upgraded ComponentAnnotations to Angular. Moved it to student module, since it wasn't being used by teacher. #2811 --- .../src/app/common-hybrid-angular.module.ts | 3 ++ .../src/app/student-hybrid-angular.module.ts | 3 ++ src/main/webapp/site/src/messages.xlf | 33 ++++++++----- .../wise5/components/animation/index.html | 4 +- .../components/audioOscillator/index.html | 4 +- .../wise5/components/conceptMap/index.html | 4 +- .../wise5/components/discussion/index.html | 4 +- .../webapp/wise5/components/draw/index.html | 4 +- .../wise5/components/embedded/index.html | 4 +- .../webapp/wise5/components/graph/index.html | 4 +- .../webapp/wise5/components/label/index.html | 4 +- .../webapp/wise5/components/match/index.html | 4 +- .../components/multipleChoice/index.html | 4 +- .../wise5/components/openResponse/index.html | 4 +- .../webapp/wise5/components/table/index.html | 4 +- .../component-annotations.component.html | 26 ++++++++++ .../component-annotations.component.scss | 3 ++ ....ts => component-annotations.component.ts} | 48 +++++++------------ .../componentAnnotations.html | 27 ----------- .../webapp/wise5/directives/components.ts | 4 +- .../wise5/vle/student-angular-js-module.ts | 5 +- 21 files changed, 102 insertions(+), 98 deletions(-) create mode 100644 src/main/webapp/wise5/directives/componentAnnotations/component-annotations.component.html create mode 100644 src/main/webapp/wise5/directives/componentAnnotations/component-annotations.component.scss rename src/main/webapp/wise5/directives/componentAnnotations/{componentAnnotations.ts => component-annotations.component.ts} (82%) delete mode 100644 src/main/webapp/wise5/directives/componentAnnotations/componentAnnotations.html diff --git a/src/main/webapp/site/src/app/common-hybrid-angular.module.ts b/src/main/webapp/site/src/app/common-hybrid-angular.module.ts index 4faae0ac9c..6f79f3ff09 100644 --- a/src/main/webapp/site/src/app/common-hybrid-angular.module.ts +++ b/src/main/webapp/site/src/app/common-hybrid-angular.module.ts @@ -49,6 +49,7 @@ import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatSelectModule } from '@angular/material/select'; import { HelpIconComponent } from '../../../wise5/themes/default/themeComponents/helpIcon/help-icon.component'; import { NodeStatusIcon } from '../../../wise5/themes/default/themeComponents/nodeStatusIcon/node-status-icon.component'; +import { MomentModule } from 'ngx-moment'; @Component({template: ``}) export class EmptyComponent {} @@ -75,6 +76,7 @@ export class EmptyComponent {} MatListModule, MatSelectModule, MatTooltipModule, + MomentModule, ReactiveFormsModule, RouterModule.forChild([ {path: '**', component: EmptyComponent} @@ -127,6 +129,7 @@ export class EmptyComponent {} MatListModule, MatSelectModule, MatTooltipModule, + MomentModule, NodeIconComponent, ReactiveFormsModule ] diff --git a/src/main/webapp/site/src/app/student-hybrid-angular.module.ts b/src/main/webapp/site/src/app/student-hybrid-angular.module.ts index 8563282f74..35c843460c 100644 --- a/src/main/webapp/site/src/app/student-hybrid-angular.module.ts +++ b/src/main/webapp/site/src/app/student-hybrid-angular.module.ts @@ -14,9 +14,12 @@ import { MatButtonModule } from '@angular/material/button'; import { MatListModule } from '@angular/material/list'; import { DataService } from './services/data.service'; import { AngularJSModule } from './common-hybrid-angular.module'; +import { ComponentAnnotationsComponent } from '../../../wise5/directives/componentAnnotations/component-annotations.component'; +import { MomentModule } from 'ngx-moment'; @NgModule({ declarations: [ + ComponentAnnotationsComponent, PossibleScoreComponent ], imports: [ diff --git a/src/main/webapp/site/src/messages.xlf b/src/main/webapp/site/src/messages.xlf index bbbdcbb073..f725d63e46 100644 --- a/src/main/webapp/site/src/messages.xlf +++ b/src/main/webapp/site/src/messages.xlf @@ -5282,6 +5282,28 @@ 120
+ + New + + ../../wise5/directives/componentAnnotations/component-annotations.component.html + 9 + + + app/classroom-monitor/component-new-work-badge/component-new-work-badge.component.ts + 1 + + + ../../wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/workgroupInfo/workgroup-info.component.html + 10 + + + + Score: + + ../../wise5/directives/componentAnnotations/component-annotations.component.html + 18 + + point @@ -5889,17 +5911,6 @@ 36 - - New - - app/classroom-monitor/component-new-work-badge/component-new-work-badge.component.ts - 1 - - - ../../wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/workgroupInfo/workgroup-info.component.html - 10 - - Show Save Button diff --git a/src/main/webapp/wise5/components/animation/index.html b/src/main/webapp/wise5/components/animation/index.html index 9edaca04c7..0f2b78cabe 100644 --- a/src/main/webapp/wise5/components/animation/index.html +++ b/src/main/webapp/wise5/components/animation/index.html @@ -169,8 +169,8 @@ + [annotations]='animationController.latestAnnotations' + [max-score]='animationController.componentContent.maxScore'> diff --git a/src/main/webapp/wise5/components/audioOscillator/index.html b/src/main/webapp/wise5/components/audioOscillator/index.html index 63f8221e02..5cede81d06 100644 --- a/src/main/webapp/wise5/components/audioOscillator/index.html +++ b/src/main/webapp/wise5/components/audioOscillator/index.html @@ -132,8 +132,8 @@ + [annotations]='audioOscillatorController.latestAnnotations' + [max-score]='audioOscillatorController.componentContent.maxScore'> diff --git a/src/main/webapp/wise5/components/conceptMap/index.html b/src/main/webapp/wise5/components/conceptMap/index.html index db9222c167..279c365176 100644 --- a/src/main/webapp/wise5/components/conceptMap/index.html +++ b/src/main/webapp/wise5/components/conceptMap/index.html @@ -195,7 +195,7 @@ + [annotations]='conceptMapController.latestAnnotations' + [max-score]='conceptMapController.componentContent.maxScore'> diff --git a/src/main/webapp/wise5/components/discussion/index.html b/src/main/webapp/wise5/components/discussion/index.html index 358c18e70a..c9fc293912 100644 --- a/src/main/webapp/wise5/components/discussion/index.html +++ b/src/main/webapp/wise5/components/discussion/index.html @@ -59,8 +59,8 @@
+ [annotations]='discussionController.latestAnnotations' + [max-score]='::discussionController.componentContent.maxScore'>
diff --git a/src/main/webapp/wise5/components/draw/index.html b/src/main/webapp/wise5/components/draw/index.html index e693999536..fd4a57ef68 100644 --- a/src/main/webapp/wise5/components/draw/index.html +++ b/src/main/webapp/wise5/components/draw/index.html @@ -127,8 +127,8 @@

API examples:

+ [annotations]='drawController.latestAnnotations' + [max-score]='drawController.componentContent.maxScore'>
diff --git a/src/main/webapp/wise5/components/embedded/index.html b/src/main/webapp/wise5/components/embedded/index.html index 2a671f8730..36d72bc44f 100644 --- a/src/main/webapp/wise5/components/embedded/index.html +++ b/src/main/webapp/wise5/components/embedded/index.html @@ -73,8 +73,8 @@ + [annotations]='embeddedController.latestAnnotations' + [max-score]='embeddedController.componentContent.maxScore'> diff --git a/src/main/webapp/wise5/components/graph/index.html b/src/main/webapp/wise5/components/graph/index.html index 7c5828ca49..06f81bdc30 100644 --- a/src/main/webapp/wise5/components/graph/index.html +++ b/src/main/webapp/wise5/components/graph/index.html @@ -197,8 +197,8 @@ + [annotations]='graphController.latestAnnotations' + [max-score]='graphController.componentContent.maxScore'>
diff --git a/src/main/webapp/wise5/components/label/index.html b/src/main/webapp/wise5/components/label/index.html index 3a80cc9def..d8d7ffbfbd 100644 --- a/src/main/webapp/wise5/components/label/index.html +++ b/src/main/webapp/wise5/components/label/index.html @@ -189,8 +189,8 @@ + [annotations]='labelController.latestAnnotations' + [max-score]='labelController.componentContent.maxScore'> diff --git a/src/main/webapp/wise5/components/match/index.html b/src/main/webapp/wise5/components/match/index.html index 30698a68f8..0c5a978486 100644 --- a/src/main/webapp/wise5/components/match/index.html +++ b/src/main/webapp/wise5/components/match/index.html @@ -174,8 +174,8 @@
+ [annotations]='matchController.latestAnnotations' + [max-score]='matchController.componentContent.maxScore'>
diff --git a/src/main/webapp/wise5/components/multipleChoice/index.html b/src/main/webapp/wise5/components/multipleChoice/index.html index deaed51295..174ed85e2d 100644 --- a/src/main/webapp/wise5/components/multipleChoice/index.html +++ b/src/main/webapp/wise5/components/multipleChoice/index.html @@ -188,8 +188,8 @@
+ [annotations]='multipleChoiceController.latestAnnotations' + [max-score]='multipleChoiceController.componentContent.maxScore'>
diff --git a/src/main/webapp/wise5/components/openResponse/index.html b/src/main/webapp/wise5/components/openResponse/index.html index 6eab8e760b..844178ca66 100644 --- a/src/main/webapp/wise5/components/openResponse/index.html +++ b/src/main/webapp/wise5/components/openResponse/index.html @@ -155,7 +155,7 @@ + [annotations]='openResponseController.latestAnnotations' + [max-score]='openResponseController.componentContent.maxScore'> diff --git a/src/main/webapp/wise5/components/table/index.html b/src/main/webapp/wise5/components/table/index.html index 6dda718eaa..a45fd38546 100644 --- a/src/main/webapp/wise5/components/table/index.html +++ b/src/main/webapp/wise5/components/table/index.html @@ -191,8 +191,8 @@ + [annotations]='tableController.latestAnnotations' + [max-score]='tableController.componentContent.maxScore'> diff --git a/src/main/webapp/wise5/directives/componentAnnotations/component-annotations.component.html b/src/main/webapp/wise5/directives/componentAnnotations/component-annotations.component.html new file mode 100644 index 0000000000..9d2c55671d --- /dev/null +++ b/src/main/webapp/wise5/directives/componentAnnotations/component-annotations.component.html @@ -0,0 +1,26 @@ + + +
+ {{icon}} +
+
+ {{label}} + New +
+
+ +
+
+
+ Score: {{annotations.score.data.value}}{{maxScoreDisplay}} + + + {{ getLatestAnnotationTime() | amTimeAgo }} + +
+
+
diff --git a/src/main/webapp/wise5/directives/componentAnnotations/component-annotations.component.scss b/src/main/webapp/wise5/directives/componentAnnotations/component-annotations.component.scss new file mode 100644 index 0000000000..f10ecae67b --- /dev/null +++ b/src/main/webapp/wise5/directives/componentAnnotations/component-annotations.component.scss @@ -0,0 +1,3 @@ +mat-card.annotations { + padding: 0; +} diff --git a/src/main/webapp/wise5/directives/componentAnnotations/componentAnnotations.ts b/src/main/webapp/wise5/directives/componentAnnotations/component-annotations.component.ts similarity index 82% rename from src/main/webapp/wise5/directives/componentAnnotations/componentAnnotations.ts rename to src/main/webapp/wise5/directives/componentAnnotations/component-annotations.component.ts index 726f76ea42..e01bb86bc0 100644 --- a/src/main/webapp/wise5/directives/componentAnnotations/componentAnnotations.ts +++ b/src/main/webapp/wise5/directives/componentAnnotations/component-annotations.component.ts @@ -1,15 +1,20 @@ 'use strict'; -import { Directive } from "@angular/core"; +import { Component, Input } from "@angular/core"; +import { UpgradeModule } from "@angular/upgrade/static"; import { Subscription } from "rxjs"; import { ConfigService } from "../../services/configService"; import { StudentDataService } from "../../services/studentDataService"; import { VLEProjectService } from "../../vle/vleProjectService"; -@Directive() -class ComponentAnnotationsController { +@Component({ + selector: 'component-annotations', + styleUrls: ['component-annotations.component.scss'], + templateUrl: 'component-annotations.component.html' +}) +export class ComponentAnnotationsComponent { - $translate: any; + @Input() annotations: any; maxScoreDisplay: string; nodeId: string = null; @@ -17,22 +22,21 @@ class ComponentAnnotationsController { latestAnnotationTime: any = null; isNew: boolean; label: string = ''; + + @Input() maxScore: string; icon: string = 'person'; showScore: boolean = true; showComment: boolean = true; studentWorkSavedToServerSubscription: Subscription; - static $inject = ['$filter', 'ConfigService', 'ProjectService', 'StudentDataService']; - - constructor(private $filter: any, + constructor(private upgrade: UpgradeModule, private ConfigService: ConfigService, private ProjectService: VLEProjectService, private StudentDataService: StudentDataService) { - this.$translate = this.$filter('translate'); } - $onInit() { + ngOnInit() { this.maxScoreDisplay = (parseInt(this.maxScore) > 0) ? '/' + this.maxScore : ''; this.studentWorkSavedToServerSubscription = this.StudentDataService.studentWorkSavedToServer$.subscribe(({studentWork}) => { @@ -42,19 +46,11 @@ class ComponentAnnotationsController { }); } - $onChanges() { + ngOnChanges() { this.processAnnotations(); - }; - - $onDestroy() { - this.ngOnDestroy(); } ngOnDestroy() { - this.unsubscribeAll(); - } - - unsubscribeAll() { this.studentWorkSavedToServerSubscription.unsubscribe(); } @@ -136,24 +132,12 @@ class ComponentAnnotationsController { const latest = this.getLatestAnnotation(); if (latest) { if (latest.type === 'autoComment' || latest.type === 'autoScore') { - this.label = this.$translate('automatedFeedbackLabel'); + this.label = this.upgrade.$injector.get('$filter')('translate')('automatedFeedbackLabel'); this.icon = 'keyboard'; } else { - this.label = this.$translate('teacherFeedbackLabel'); + this.label = this.upgrade.$injector.get('$filter')('translate')('teacherFeedbackLabel'); this.icon = 'person'; } } } } - -const ComponentAnnotations = { - bindings: { - annotations: '<', - maxScore: '<' - }, - templateUrl: 'wise5/directives/componentAnnotations/componentAnnotations.html', - controller: ComponentAnnotationsController, - controllerAs: 'componentAnnotationsCtrl' -}; - -export default ComponentAnnotations; diff --git a/src/main/webapp/wise5/directives/componentAnnotations/componentAnnotations.html b/src/main/webapp/wise5/directives/componentAnnotations/componentAnnotations.html deleted file mode 100644 index 83e7eb4f3a..0000000000 --- a/src/main/webapp/wise5/directives/componentAnnotations/componentAnnotations.html +++ /dev/null @@ -1,27 +0,0 @@ - - -
- {{componentAnnotationsCtrl.icon}} -
-
- {{componentAnnotationsCtrl.label}} - -
-
- -
-
-
- - - - - {{ componentAnnotationsCtrl.getLatestAnnotationTime() | amDateFormat:'ddd, MMM D YYYY, h:mm a' }} - -
-
-
diff --git a/src/main/webapp/wise5/directives/components.ts b/src/main/webapp/wise5/directives/components.ts index 0c83aa3d72..5e032fde70 100644 --- a/src/main/webapp/wise5/directives/components.ts +++ b/src/main/webapp/wise5/directives/components.ts @@ -3,7 +3,6 @@ import * as angular from 'angular'; import Compile from './compile/compile'; import Component from './component/component'; -import ComponentAnnotations from './componentAnnotations/componentAnnotations'; import DisableDeleteKeypress from './disableDeleteKeypress/disableDeleteKeypress'; import Draggable from './draggable/draggable'; import GlobalAnnotations from './globalAnnotations/globalAnnotations'; @@ -22,7 +21,6 @@ const Components = angular.module('components', []); Components.component('compile', Compile); Components.component('component', Component); -Components.component('componentAnnotations', ComponentAnnotations); Components.component('disableDeleteKeypress', DisableDeleteKeypress); Components.component('draggable', Draggable); Components.component('globalAnnotations', GlobalAnnotations); @@ -32,7 +30,7 @@ Components.directive('milestoneReportData', downgradeComponent({ component: MilestoneReportDataComponent}) as angular.IDirectiveFactory); Components.component('milestoneReportGraph', MilestoneReportGraph); Components.directive('nodeIcon', - downgradeComponent({ component: NodeIconComponent}) as angular.IDirectiveFactory) + downgradeComponent({ component: NodeIconComponent}) as angular.IDirectiveFactory); Components.directive('possibleScore', downgradeComponent({ component: PossibleScoreComponent}) as angular.IDirectiveFactory); Components.component('summaryDisplay', SummaryDisplay); diff --git a/src/main/webapp/wise5/vle/student-angular-js-module.ts b/src/main/webapp/wise5/vle/student-angular-js-module.ts index 9ed38e53a4..4ef4953585 100644 --- a/src/main/webapp/wise5/vle/student-angular-js-module.ts +++ b/src/main/webapp/wise5/vle/student-angular-js-module.ts @@ -1,7 +1,7 @@ import '../lib/jquery/jquery-global'; import '../lib/bootstrap/js/bootstrap.min' import * as angular from 'angular'; -import { downgradeInjectable } from '@angular/upgrade/static'; +import { downgradeComponent, downgradeInjectable } from '@angular/upgrade/static'; import '../common-angular-js-module'; import NavigationController from '../vle/navigation/navigationController'; import NodeController from '../vle/node/nodeController'; @@ -11,6 +11,7 @@ import { VLEProjectService } from '../vle/vleProjectService'; import '../lib/summernote/dist/summernote.min'; import '../lib/summernoteExtensions/summernote-ext-addNote.js'; import '../lib/summernoteExtensions/summernote-ext-print.js' +import { ComponentAnnotationsComponent } from '../directives/componentAnnotations/component-annotations.component'; export function createStudentAngularJSModule(type = 'preview') { return angular.module(type, [ @@ -26,6 +27,8 @@ export function createStudentAngularJSModule(type = 'preview') { .controller('NavigationController', NavigationController) .controller('NodeController', NodeController) .controller('VLEController', VLEController) + .directive('componentAnnotations', + downgradeComponent({ component: ComponentAnnotationsComponent }) as angular.IDirectiveFactory) .config([ '$stateProvider', '$translatePartialLoaderProvider', From 08d4631ca291b2c22cab5bfb0c303d92716894dd Mon Sep 17 00:00:00 2001 From: Hiroki Terashima Date: Tue, 17 Nov 2020 11:12:35 -0800 Subject: [PATCH 10/11] Changed component annotation title font-size to 15px. #2811 --- .../componentAnnotations/component-annotations.component.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/webapp/wise5/directives/componentAnnotations/component-annotations.component.scss b/src/main/webapp/wise5/directives/componentAnnotations/component-annotations.component.scss index f10ecae67b..7bb5ef784a 100644 --- a/src/main/webapp/wise5/directives/componentAnnotations/component-annotations.component.scss +++ b/src/main/webapp/wise5/directives/componentAnnotations/component-annotations.component.scss @@ -1,3 +1,7 @@ mat-card.annotations { padding: 0; } + +.annotations__title { + font-size: 15px; +} From c668d86767aaaea10e438d5502143bf3ad13a474 Mon Sep 17 00:00:00 2001 From: Hiroki Terashima Date: Tue, 17 Nov 2020 14:10:36 -0800 Subject: [PATCH 11/11] Bumped version number to 5.18.4 --- package-lock.json | 2 +- package.json | 2 +- pom.xml | 2 +- src/main/resources/version.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 75ec5fab57..6d53a740ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "wise", - "version": "5.18.3", + "version": "5.18.4", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 6f244ac2bc..23d097c2a1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wise", - "version": "5.18.3", + "version": "5.18.4", "description": "Web-based Inquiry Science Environment", "main": "app.js", "browserslist": [ diff --git a/pom.xml b/pom.xml index 18bf86b28d..aacbbc7e07 100644 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,7 @@ wise war Web-based Inquiry Science Environment - 5.18.3 + 5.18.4 http://wise5.org diff --git a/src/main/resources/version.txt b/src/main/resources/version.txt index 716cd660e0..e4df8b80ba 100644 --- a/src/main/resources/version.txt +++ b/src/main/resources/version.txt @@ -1 +1 @@ -5.18.3 +5.18.4