+
-
+
+ [disabled]="!editProfileFormGroup.valid || !changed || isSaving">
Save Changes
+
+
+
+
This profile is linked to a Google account.
+
+
+ Unlink Google Account
+
+
diff --git a/src/main/webapp/site/src/app/teacher/account/edit-profile/edit-profile.component.scss b/src/main/webapp/site/src/app/teacher/account/edit-profile/edit-profile.component.scss
index dbd834f0b1..1888291374 100644
--- a/src/main/webapp/site/src/app/teacher/account/edit-profile/edit-profile.component.scss
+++ b/src/main/webapp/site/src/app/teacher/account/edit-profile/edit-profile.component.scss
@@ -21,3 +21,16 @@
}
}
}
+
+.actions {
+ margin-top: 8px;
+}
+
+.google-icon {
+ height: 1.8em;
+ width: auto;
+}
+
+.unlink {
+ margin: 8px 0;
+}
diff --git a/src/main/webapp/site/src/app/teacher/account/edit-profile/edit-profile.component.spec.ts b/src/main/webapp/site/src/app/teacher/account/edit-profile/edit-profile.component.spec.ts
index e8fe132d86..05b8ad23a2 100644
--- a/src/main/webapp/site/src/app/teacher/account/edit-profile/edit-profile.component.spec.ts
+++ b/src/main/webapp/site/src/app/teacher/account/edit-profile/edit-profile.component.spec.ts
@@ -13,6 +13,7 @@ import { NO_ERRORS_SCHEMA } from '@angular/core';
import { By } from '@angular/platform-browser';
import { User } from '../../../domain/user';
import { configureTestSuite } from 'ng-bullet';
+import { MatDialogModule } from '@angular/material/dialog';
export class MockUserService {
user: User;
@@ -89,6 +90,7 @@ describe('EditProfileComponent', () => {
imports: [
BrowserAnimationsModule,
ReactiveFormsModule,
+ MatDialogModule,
MatInputModule,
MatSelectModule,
MatSnackBarModule
diff --git a/src/main/webapp/site/src/app/teacher/account/edit-profile/edit-profile.component.ts b/src/main/webapp/site/src/app/teacher/account/edit-profile/edit-profile.component.ts
index 6ed9c50c25..01c612ea48 100644
--- a/src/main/webapp/site/src/app/teacher/account/edit-profile/edit-profile.component.ts
+++ b/src/main/webapp/site/src/app/teacher/account/edit-profile/edit-profile.component.ts
@@ -1,17 +1,20 @@
-import { Component, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators, FormBuilder } from '@angular/forms';
import { finalize } from 'rxjs/operators';
import { MatSnackBar } from '@angular/material/snack-bar';
import { UserService } from '../../../services/user.service';
import { Teacher } from '../../../domain/teacher';
import { TeacherService } from '../../teacher.service';
+import { MatDialog } from '@angular/material/dialog';
+import { UnlinkGoogleAccountConfirmComponent } from '../../../modules/shared/unlink-google-account-confirm/unlink-google-account-confirm.component';
+import { Subscription } from 'rxjs';
@Component({
selector: 'app-edit-profile',
templateUrl: './edit-profile.component.html',
styleUrls: ['./edit-profile.component.scss']
})
-export class EditProfileComponent implements OnInit {
+export class EditProfileComponent {
user: Teacher;
schoolLevels: any[] = [
{ id: 'ELEMENTARY_SCHOOL', label: $localize`Elementary School` },
@@ -23,6 +26,8 @@ export class EditProfileComponent implements OnInit {
languages: object[];
changed: boolean = false;
isSaving: boolean = false;
+ isGoogleUser: boolean = false;
+ userSubscription: Subscription;
editProfileFormGroup: FormGroup = this.fb.group({
firstName: new FormControl({ value: '', disabled: true }, [Validators.required]),
@@ -41,6 +46,7 @@ export class EditProfileComponent implements OnInit {
private fb: FormBuilder,
private teacherService: TeacherService,
private userService: UserService,
+ public dialog: MatDialog,
public snackBar: MatSnackBar
) {
this.user =
this.getUser().getValue();
@@ -57,10 +63,6 @@ export class EditProfileComponent implements OnInit {
this.userService.getLanguages().subscribe((response) => {
this.languages = response;
});
-
- this.editProfileFormGroup.valueChanges.subscribe(() => {
- this.changed = true;
- });
}
getUser() {
@@ -71,7 +73,19 @@ export class EditProfileComponent implements OnInit {
this.editProfileFormGroup.controls[name].setValue(value);
}
- ngOnInit() {}
+ ngOnInit() {
+ this.editProfileFormGroup.valueChanges.subscribe(() => {
+ this.changed = true;
+ });
+
+ this.userSubscription = this.userService.getUser().subscribe((user) => {
+ this.isGoogleUser = user.isGoogleUser;
+ });
+ }
+
+ ngOnDestroy() {
+ this.userSubscription.unsubscribe();
+ }
saveChanges() {
this.isSaving = true;
@@ -128,4 +142,10 @@ export class EditProfileComponent implements OnInit {
this.snackBar.open($localize`An error occurred. Please try again.`);
}
}
+
+ unlinkGoogleAccount() {
+ this.dialog.open(UnlinkGoogleAccountConfirmComponent, {
+ panelClass: 'mat-dialog--sm'
+ });
+ }
}
diff --git a/src/main/webapp/site/src/app/teacher/edit-run-warning-dialog/edit-run-warning-dialog.component.html b/src/main/webapp/site/src/app/teacher/edit-run-warning-dialog/edit-run-warning-dialog.component.html
index 1f9c2f19f8..c196fa4e2f 100644
--- a/src/main/webapp/site/src/app/teacher/edit-run-warning-dialog/edit-run-warning-dialog.component.html
+++ b/src/main/webapp/site/src/app/teacher/edit-run-warning-dialog/edit-run-warning-dialog.component.html
@@ -1,7 +1,7 @@
-
+
Edit Classroom Unit
- warning
+ warning
diff --git a/src/main/webapp/site/src/messages.xlf b/src/main/webapp/site/src/messages.xlf
index 2419779b02..01901da39b 100644
--- a/src/main/webapp/site/src/messages.xlf
+++ b/src/main/webapp/site/src/messages.xlf
@@ -236,29 +236,138 @@
10
-
- Current Password
+
+ Google logo
+
+ app/modules/shared/unlink-google-account-success/unlink-google-account-success.component.html
+ 2
+
+
+ app/modules/shared/unlink-google-account-password/unlink-google-account-password.component.html
+ 2
+
+
+ app/modules/shared/unlink-google-account-confirm/unlink-google-account-confirm.component.html
+ 2
+
app/modules/shared/edit-password/edit-password.component.html
- 8
+ 61
+
+
+ app/register/register-teacher/register-teacher.component.html
+ 28
+
+
+ app/register/register-teacher-complete/register-teacher-complete.component.html
+ 14
+
+
+ app/register/register-student-complete/register-student-complete.component.html
+ 14
+
+
+ app/register/register-student/register-student.component.html
+ 39
+
+
+ app/register/register-google-user-already-exists/register-google-user-already-exists.component.html
+ 10
+
+
+ app/student/team-sign-in-dialog/team-sign-in-dialog.component.html
+ 59
+
+
+ app/student/account/edit-profile/edit-profile.component.html
+ 64
+
+
+ app/teacher/account/edit-profile/edit-profile.component.html
+ 132
-
- Current Password required
+
+ Unlink Google Account
+
+ app/modules/shared/unlink-google-account-success/unlink-google-account-success.component.html
+ 3
+
+
+ app/modules/shared/unlink-google-account-password/unlink-google-account-password.component.html
+ 3
+
+
+ app/modules/shared/unlink-google-account-confirm/unlink-google-account-confirm.component.html
+ 3
+
app/modules/shared/edit-password/edit-password.component.html
- 15
+ 70
+
+
+ app/student/account/edit-profile/edit-profile.component.html
+ 68
+
+
+ app/teacher/account/edit-profile/edit-profile.component.html
+ 136
-
- Current Password is incorrect
+
+ Success! You have unlinked your Google account from WISE. To sign in to WISE in the future, please use your username and the password you just created.
- app/modules/shared/edit-password/edit-password.component.html
- 16
+ app/modules/shared/unlink-google-account-success/unlink-google-account-success.component.html
+ 7
+
+
+
+ Your username is: .
+
+ app/modules/shared/unlink-google-account-success/unlink-google-account-success.component.html
+ 8
+
+
+
+ Done
+
+ app/modules/shared/unlink-google-account-success/unlink-google-account-success.component.html
+ 12
+
+
+ app/teacher/list-classroom-courses-dialog/list-classroom-courses-dialog.component.html
+ 75
+
+
+ app/teacher/create-run-dialog/create-run-dialog.component.html
+ 85
+
+
+ app/modules/library/share-project-dialog/share-project-dialog.component.html
+ 70
+
+
+ app/teacher/share-run-dialog/share-run-dialog.component.html
+ 102
+
+
+ app/teacher/run-settings-dialog/run-settings-dialog.component.html
+ 76
+
+
+
+ Create a WISE password:
+
+ app/modules/shared/unlink-google-account-password/unlink-google-account-password.component.html
+ 7
New Password
+
+ app/modules/shared/unlink-google-account-password/unlink-google-account-password.component.html
+ 9
+
app/modules/shared/edit-password/edit-password.component.html
22
@@ -266,6 +375,10 @@
New Password required
+
+ app/modules/shared/unlink-google-account-password/unlink-google-account-password.component.html
+ 16
+
app/modules/shared/edit-password/edit-password.component.html
29
@@ -273,6 +386,10 @@
Confirm New Password
+
+ app/modules/shared/unlink-google-account-password/unlink-google-account-password.component.html
+ 19
+
app/modules/shared/edit-password/edit-password.component.html
34
@@ -280,6 +397,10 @@
Confirm Password required
+
+ app/modules/shared/unlink-google-account-password/unlink-google-account-password.component.html
+ 26
+
app/modules/shared/edit-password/edit-password.component.html
41
@@ -303,11 +424,170 @@
Passwords do not match
+
+ app/modules/shared/unlink-google-account-password/unlink-google-account-password.component.html
+ 27
+
app/modules/shared/edit-password/edit-password.component.html
42
+
+ Cancel
+
+ app/modules/shared/unlink-google-account-password/unlink-google-account-password.component.html
+ 31
+
+
+ app/modules/shared/unlink-google-account-confirm/unlink-google-account-confirm.component.html
+ 14
+
+
+ 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
+
+
+
+ Submit
+
+ app/modules/shared/unlink-google-account-password/unlink-google-account-password.component.html
+ 37
+
+
+ app/contact/contact-form/contact-form.component.html
+ 112
+
+
+ app/forgot/student/forgot-student-password/forgot-student-password.component.html
+ 25
+
+
+ app/forgot/teacher/forgot-teacher-username/forgot-teacher-username.component.html
+ 25
+
+
+ app/forgot/teacher/forgot-teacher-password/forgot-teacher-password.component.html
+ 25
+
+
+ app/forgot/student/forgot-student-password-security/forgot-student-password-security.component.html
+ 28
+
+
+ app/forgot/student/forgot-student-password-change/forgot-student-password-change.component.html
+ 41
+
+
+ app/forgot/teacher/forgot-teacher-password-change/forgot-teacher-password-change.component.html
+ 39
+
+
+ app/forgot/teacher/forgot-teacher-password-verify/forgot-teacher-password-verify.component.html
+ 26
+
+
+
+ Warning
+
+ app/modules/shared/unlink-google-account-confirm/unlink-google-account-confirm.component.html
+ 5
+
+
+ app/teacher/edit-run-warning-dialog/edit-run-warning-dialog.component.html
+ 4
+
+
+ app/help/teacher-faq/teacher-faq.component.html
+ 85
+
+
+
+ To remove the link to your Google account, you will be asked to create a WISE password. In the future, you'll sign in to WISE using your username and password.
+
+ app/modules/shared/unlink-google-account-confirm/unlink-google-account-confirm.component.html
+ 9
+
+
+
+ You will no longer be able to sign in to WISE using Google. Would you like to continue?
+
+ app/modules/shared/unlink-google-account-confirm/unlink-google-account-confirm.component.html
+ 10
+
+
+
+ Continue
+
+ app/modules/shared/unlink-google-account-confirm/unlink-google-account-confirm.component.html
+ 15
+
+
+
+ Current Password
+
+ app/modules/shared/edit-password/edit-password.component.html
+ 8
+
+
+
+ Current Password required
+
+ app/modules/shared/edit-password/edit-password.component.html
+ 15
+
+
+
+ Current Password is incorrect
+
+ app/modules/shared/edit-password/edit-password.component.html
+ 16
+
+
Change Password
@@ -323,8 +603,8 @@
7
-
- This account was created using Google and doesn't use a WISE password. If you would like to unlink your Google account, please contact us .
+
+ This account was created using Google and doesn't use a WISE password.
app/modules/shared/edit-password/edit-password.component.html
60
@@ -1068,57 +1348,6 @@
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
@@ -1256,29 +1485,6 @@
69
-
- Done
-
- app/teacher/list-classroom-courses-dialog/list-classroom-courses-dialog.component.html
- 75
-
-
- app/teacher/create-run-dialog/create-run-dialog.component.html
- 85
-
-
- app/modules/library/share-project-dialog/share-project-dialog.component.html
- 70
-
-
- app/teacher/share-run-dialog/share-run-dialog.component.html
- 102
-
-
- app/teacher/run-settings-dialog/run-settings-dialog.component.html
- 76
-
-
Use with Class
@@ -2294,41 +2500,6 @@
104
-
- Submit
-
- app/contact/contact-form/contact-form.component.html
- 112
-
-
- app/forgot/student/forgot-student-password/forgot-student-password.component.html
- 25
-
-
- app/forgot/teacher/forgot-teacher-username/forgot-teacher-username.component.html
- 25
-
-
- app/forgot/teacher/forgot-teacher-password/forgot-teacher-password.component.html
- 25
-
-
- app/forgot/student/forgot-student-password-security/forgot-student-password-security.component.html
- 28
-
-
- app/forgot/student/forgot-student-password-change/forgot-student-password-change.component.html
- 41
-
-
- app/forgot/teacher/forgot-teacher-password-change/forgot-teacher-password-change.component.html
- 39
-
-
- app/forgot/teacher/forgot-teacher-password-verify/forgot-teacher-password-verify.component.html
- 26
-
-
WISE Features
@@ -3850,13 +4021,6 @@
84
-
- Warning
-
- app/help/teacher-faq/teacher-faq.component.html
- 85
-
-
If you move a student to a different period, they will lose all of their work.
@@ -4563,50 +4727,23 @@
app/register/register-teacher-form/register-teacher-form.component.html
7
-
-
- Sign Up
-
- app/register/register-teacher/register-teacher.component.html
- 18
-
-
- app/register/register-student/register-student.component.html
- 29
-
-
-
- - or -
-
- app/register/register-teacher/register-teacher.component.html
- 22
-
-
-
- Google logo
-
- app/register/register-teacher/register-teacher.component.html
- 28
-
-
- app/register/register-teacher-complete/register-teacher-complete.component.html
- 14
-
-
- app/register/register-student-complete/register-student-complete.component.html
- 14
-
+
+
+ Sign Up
- app/register/register-student/register-student.component.html
- 39
+ app/register/register-teacher/register-teacher.component.html
+ 18
- app/register/register-google-user-already-exists/register-google-user-already-exists.component.html
- 10
+ app/register/register-student/register-student.component.html
+ 29
+
+
+ - or -
- app/student/team-sign-in-dialog/team-sign-in-dialog.component.html
- 59
+ app/register/register-teacher/register-teacher.component.html
+ 22
@@ -5290,20 +5427,27 @@
app/student/account/edit-profile/edit-profile.component.html
42
+
+
+ Save Changes
+
+ app/student/account/edit-profile/edit-profile.component.html
+ 57
+
app/teacher/account/edit-profile/edit-profile.component.html
- 108
+ 125
-
- Save Changes
+
+ This profile is linked to a Google account.
app/student/account/edit-profile/edit-profile.component.html
- 53
+ 65
app/teacher/account/edit-profile/edit-profile.component.html
- 120
+ 133
@@ -5804,6 +5948,13 @@
107
+
+ Language required
+
+ app/teacher/account/edit-profile/edit-profile.component.html
+ 108
+
+
Back to Unit Plan
@@ -6024,6 +6175,14 @@
../../wise5/components/draw/draw-authoring/draw-authoring.component.html
2
+
+ ../../wise5/components/discussion/discussion-authoring/discussion-authoring.component.html
+ 2
+
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 2
+
../../wise5/components/match/match-authoring/match-authoring.component.html
2
@@ -6036,6 +6195,10 @@
../../wise5/components/openResponse/open-response-authoring/open-response-authoring.component.html
11
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 2
+
Enter Prompt Here
@@ -6047,6 +6210,14 @@
../../wise5/components/draw/draw-authoring/draw-authoring.component.html
6
+
+ ../../wise5/components/discussion/discussion-authoring/discussion-authoring.component.html
+ 6
+
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 6
+
../../wise5/components/match/match-authoring/match-authoring.component.html
6
@@ -6059,6 +6230,10 @@
../../wise5/components/openResponse/open-response-authoring/open-response-authoring.component.html
15
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 6
+
Background Image (Optional)
@@ -6105,6 +6280,10 @@
../../wise5/components/draw/draw-authoring/draw-authoring.component.html
228
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 21
+
../../wise5/components/match/match-authoring/match-authoring.component.html
41
@@ -6189,6 +6368,10 @@
../../wise5/components/conceptMap/concept-map-authoring/concept-map-authoring.component.html
87
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 24
+
../../wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.component.html
68
@@ -6316,6 +6499,14 @@
app/authoring-tool/edit-component-tags/edit-component-tags.component.html
38
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 206
+
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 232
+
../../wise5/components/match/match-authoring/match-authoring.component.html
79
@@ -6332,6 +6523,14 @@
../../wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.component.html
124
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 61
+
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 102
+
Show Node Labels
@@ -6378,6 +6577,10 @@
../../wise5/components/conceptMap/concept-map-authoring/concept-map-authoring.component.html
195
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 128
+
(Optional) Create a starting state for the concept map by editing the "Student Preview" below and then saving here:
@@ -6613,6 +6816,10 @@
../../wise5/components/draw/draw-authoring/draw-authoring.component.html
277
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 221
+
Delete Starter Drawing
@@ -6621,6 +6828,20 @@
285
+
+ Students can upload and use images in their posts
+
+ ../../wise5/components/discussion/discussion-authoring/discussion-authoring.component.html
+ 16
+
+
+
+ Students must create a post before viewing classmates' posts
+
+ ../../wise5/components/discussion/discussion-authoring/discussion-authoring.component.html
+ 25
+
+
Rubric
@@ -6691,6 +6912,196 @@
2
+
+ Background Image
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 13
+
+
+
+ Canvas Width (px)
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 31
+
+
+
+ Canvas Height (px)
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 38
+
+
+
+ Point Radius Size (px)
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 47
+
+
+
+ Font Size
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 54
+
+
+
+ Label Max Character Width
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 61
+
+
+
+ Can Student Create Labels
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 74
+
+
+
+ Enable Dots
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 83
+
+
+
+ Allow Student to Upload Image for Background
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 92
+
+
+
+ Starter Labels
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 99
+
+
+
+ Add Starter Label
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 103
+
+
+
+ add
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 106
+
+
+
+ There are no starter labels. Click the "Add Label" button to add a starter label.
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 113
+
+
+
+ Text
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 120
+
+
+
+ Enter Label Text Here
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 124
+
+
+
+ View Colors
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 137
+
+
+
+ Color Palette
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 140
+
+
+
+ Can Student Edit Label
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 151
+
+
+
+ Can Student Delete Label
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 160
+
+
+
+ Point Location
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 167
+
+
+
+ X
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 169
+
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 186
+
+
+
+ Y
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 176
+
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 193
+
+
+
+ Text Location
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 184
+
+
+
+ Delete Label
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 203
+
+
+
+ Save Starter Labels
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 218
+
+
+
+ Delete Starter Labels
+
+ ../../wise5/components/label/label-authoring/label-authoring.component.html
+ 229
+
+
Choices
@@ -7067,6 +7478,113 @@
6
+
+ Columns
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 13
+
+
+
+ Rows
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 21
+
+
+
+ Global Cell Size
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 29
+
+
+
+ Insert Column Before
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 47
+
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 50
+
+
+
+ Delete Column
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 58
+
+
+
+ Insert Column After
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 70
+
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 73
+
+
+
+ Insert Row Before
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 88
+
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 91
+
+
+
+ Delete Row
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 99
+
+
+
+ Insert Row After
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 111
+
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 114
+
+
+
+ Editable
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 133
+
+
+
+ Column Cell Size
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 155
+
+
+
+ Make All Cells Editable
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 171
+
+
+
+ Make All Cells Uneditable
+
+ ../../wise5/components/table/table-authoring/table-authoring.component.html
+ 178
+
+
(Team )
diff --git a/src/main/webapp/site/src/style/layout/_section.scss b/src/main/webapp/site/src/style/layout/_section.scss
index bc80d059f1..25b5b018a6 100644
--- a/src/main/webapp/site/src/style/layout/_section.scss
+++ b/src/main/webapp/site/src/style/layout/_section.scss
@@ -20,7 +20,7 @@
}
.section__tab {
- padding: 24px 0;
+ padding: 24px 4px;
@media (min-width: breakpoint('sm.min')) {
padding: 24px 16px;
diff --git a/src/main/webapp/wise5/authoringTool/components/component-authoring.component.ts b/src/main/webapp/wise5/authoringTool/components/component-authoring.component.ts
index 6634abd0cc..67ae4403ea 100644
--- a/src/main/webapp/wise5/authoringTool/components/component-authoring.component.ts
+++ b/src/main/webapp/wise5/authoringTool/components/component-authoring.component.ts
@@ -62,6 +62,11 @@ export abstract class ComponentAuthoring {
);
}
+ ngOnDestroy() {
+ this.componentChangedSubscription.unsubscribe();
+ this.starterStateResponseSubscription.unsubscribe();
+ }
+
promptChanged(prompt: string): void {
this.promptChange.next(prompt);
}
@@ -103,6 +108,16 @@ export abstract class ComponentAuthoring {
});
}
+ chooseBackgroundImage(): void {
+ const params = {
+ isPopup: true,
+ nodeId: this.nodeId,
+ componentId: this.componentId,
+ target: 'background'
+ };
+ this.openAssetChooser(params);
+ }
+
openAssetChooser(params: any): any {
return this.ProjectAssetService.openAssetChooser(params).then((data: any) => {
return this.assetSelected(data);
diff --git a/src/main/webapp/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestoneDetailsDialog/milestoneDetailsDialog.html b/src/main/webapp/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestoneDetailsDialog/milestoneDetailsDialog.html
new file mode 100644
index 0000000000..986833bfc1
--- /dev/null
+++ b/src/main/webapp/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestoneDetailsDialog/milestoneDetailsDialog.html
@@ -0,0 +1,21 @@
+
+
+
+
{{ 'MILESTONE_DETAILS_TITLE' | translate : { name: $ctrl.milestone.name } }}
+
+
+
+
+
+
+
+
+ {{ ::'CLOSE' | translate }}
+
+
+
\ No newline at end of file
diff --git a/src/main/webapp/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestoneDetailsDialog/milestoneDetailsDialog.ts b/src/main/webapp/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestoneDetailsDialog/milestoneDetailsDialog.ts
new file mode 100644
index 0000000000..eaec3e2d0b
--- /dev/null
+++ b/src/main/webapp/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestoneDetailsDialog/milestoneDetailsDialog.ts
@@ -0,0 +1,77 @@
+export class MilestoneDetailsDialog {
+ title: string;
+
+ static $inject = [
+ '$state',
+ '$mdDialog',
+ '$event',
+ 'milestone',
+ 'hideStudentWork',
+ 'TeacherDataService'
+ ];
+
+ constructor(
+ private $state,
+ private $mdDialog,
+ private $event,
+ private milestone,
+ private hideStudentWork,
+ private TeacherDataService
+ ) {}
+
+ $onInit() {
+ this.saveMilestoneOpenedEvent();
+ }
+
+ close() {
+ this.saveMilestoneClosedEvent();
+ this.$mdDialog.hide();
+ }
+
+ edit() {
+ this.$mdDialog.hide({
+ milestone: this.milestone,
+ action: 'edit',
+ $event: this.$event
+ });
+ }
+
+ onShowWorkgroup(workgroup: any) {
+ this.saveMilestoneClosedEvent();
+ this.$mdDialog.hide();
+ this.TeacherDataService.setCurrentWorkgroup(workgroup);
+ this.$state.go('root.nodeProgress');
+ }
+
+ onVisitNodeGrading() {
+ this.$mdDialog.hide();
+ }
+
+ saveMilestoneOpenedEvent() {
+ this.saveMilestoneEvent('MilestoneOpened');
+ }
+
+ saveMilestoneClosedEvent() {
+ this.saveMilestoneEvent('MilestoneClosed');
+ }
+
+ saveMilestoneEvent(event: any) {
+ const context = 'ClassroomMonitor',
+ nodeId = null,
+ componentId = null,
+ componentType = null,
+ category = 'Navigation',
+ data = { milestoneId: this.milestone.id },
+ projectId = null;
+ this.TeacherDataService.saveEvent(
+ context,
+ nodeId,
+ componentId,
+ componentType,
+ category,
+ event,
+ data,
+ projectId
+ );
+ }
+}
diff --git a/src/main/webapp/wise5/components/conceptMap/concept-map-authoring/concept-map-authoring.component.ts b/src/main/webapp/wise5/components/conceptMap/concept-map-authoring/concept-map-authoring.component.ts
index 5a140470a4..9fbf33365e 100644
--- a/src/main/webapp/wise5/components/conceptMap/concept-map-authoring/concept-map-authoring.component.ts
+++ b/src/main/webapp/wise5/components/conceptMap/concept-map-authoring/concept-map-authoring.component.ts
@@ -156,16 +156,6 @@ export class ConceptMapAuthoring extends ComponentAuthoring {
}
}
- chooseBackgroundImage(): void {
- const params = {
- isPopup: true,
- nodeId: this.nodeId,
- componentId: this.componentId,
- target: 'background'
- };
- this.openAssetChooser(params);
- }
-
chooseNodeImage(conceptMapNodeId: string): void {
const params = {
isPopup: true,
diff --git a/src/main/webapp/wise5/components/discussion/authoring.html b/src/main/webapp/wise5/components/discussion/authoring.html
deleted file mode 100644
index 1c169b45ce..0000000000
--- a/src/main/webapp/wise5/components/discussion/authoring.html
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
- {{ ::'PROMPT' | translate }}
-
-
-
-
- {{ ::'discussion.allowUploadedImagesInPosts' | translate }}
-
-
-
-
-
- {{ ::'discussion.gateClassmateResponses' | translate }}
-
-
-
-
diff --git a/src/main/webapp/wise5/components/discussion/discussion-authoring/discussion-authoring.component.html b/src/main/webapp/wise5/components/discussion/discussion-authoring/discussion-authoring.component.html
new file mode 100644
index 0000000000..d457e04955
--- /dev/null
+++ b/src/main/webapp/wise5/components/discussion/discussion-authoring/discussion-authoring.component.html
@@ -0,0 +1,28 @@
+
+ Prompt
+
+
+
+
+ Students can upload and use images in their posts
+
+
+
+
+ Students must create a post before viewing classmates' posts
+
+
\ No newline at end of file
diff --git a/src/main/webapp/wise5/components/discussion/discussion-authoring/discussion-authoring.component.scss b/src/main/webapp/wise5/components/discussion/discussion-authoring/discussion-authoring.component.scss
new file mode 100644
index 0000000000..7221a74cf4
--- /dev/null
+++ b/src/main/webapp/wise5/components/discussion/discussion-authoring/discussion-authoring.component.scss
@@ -0,0 +1,8 @@
+.prompt {
+ width: 100%;
+}
+
+.checkbox-container {
+ margin-top: 5px;
+ margin-bottom: 15px;
+}
\ No newline at end of file
diff --git a/src/main/webapp/wise5/components/discussion/discussion-authoring/discussion-authoring.component.ts b/src/main/webapp/wise5/components/discussion/discussion-authoring/discussion-authoring.component.ts
new file mode 100644
index 0000000000..ce81455ece
--- /dev/null
+++ b/src/main/webapp/wise5/components/discussion/discussion-authoring/discussion-authoring.component.ts
@@ -0,0 +1,24 @@
+'use strict';
+
+import { Component } from '@angular/core';
+import { ProjectAssetService } from '../../../../site/src/app/services/projectAssetService';
+import { ComponentAuthoring } from '../../../authoringTool/components/component-authoring.component';
+import { ConfigService } from '../../../services/configService';
+import { NodeService } from '../../../services/nodeService';
+import { TeacherProjectService } from '../../../services/teacherProjectService';
+
+@Component({
+ selector: 'discussion-authoring',
+ templateUrl: 'discussion-authoring.component.html',
+ styleUrls: ['discussion-authoring.component.scss']
+})
+export class DiscussionAuthoring extends ComponentAuthoring {
+ constructor(
+ protected ConfigService: ConfigService,
+ protected NodeService: NodeService,
+ protected ProjectAssetService: ProjectAssetService,
+ protected ProjectService: TeacherProjectService
+ ) {
+ super(ConfigService, NodeService, ProjectAssetService, ProjectService);
+ }
+}
diff --git a/src/main/webapp/wise5/components/discussion/discussionAuthoring.ts b/src/main/webapp/wise5/components/discussion/discussionAuthoring.ts
deleted file mode 100644
index d30b4b0c2f..0000000000
--- a/src/main/webapp/wise5/components/discussion/discussionAuthoring.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-'use strict';
-
-import { Directive } from '@angular/core';
-import { EditComponentController } from '../../authoringTool/components/editComponentController';
-
-@Directive()
-class DiscussionAuthoringController extends EditComponentController {
- static $inject = [
- '$filter',
- 'ConfigService',
- 'NodeService',
- 'NotificationService',
- 'ProjectAssetService',
- 'ProjectService',
- 'UtilService'
- ];
-
- constructor(
- $filter,
- ConfigService,
- NodeService,
- NotificationService,
- ProjectAssetService,
- ProjectService,
- UtilService
- ) {
- super(
- $filter,
- ConfigService,
- NodeService,
- NotificationService,
- ProjectAssetService,
- ProjectService,
- UtilService
- );
- }
-}
-
-const DiscussionAuthoring = {
- bindings: {
- nodeId: '@',
- componentId: '@'
- },
- controller: DiscussionAuthoringController,
- controllerAs: 'discussionController',
- templateUrl: 'wise5/components/discussion/authoring.html'
-};
-
-export default DiscussionAuthoring;
diff --git a/src/main/webapp/wise5/components/discussion/discussionAuthoringComponentModule.ts b/src/main/webapp/wise5/components/discussion/discussionAuthoringComponentModule.ts
index 77bf783b60..9acf77bcbe 100644
--- a/src/main/webapp/wise5/components/discussion/discussionAuthoringComponentModule.ts
+++ b/src/main/webapp/wise5/components/discussion/discussionAuthoringComponentModule.ts
@@ -1,16 +1,19 @@
'use strict';
import * as angular from 'angular';
-import { downgradeInjectable } from '@angular/upgrade/static';
+import { downgradeComponent, downgradeInjectable } from '@angular/upgrade/static';
import { DiscussionService } from './discussionService';
-import DiscussionAuthoring from './discussionAuthoring';
import { EditDiscussionAdvancedComponent } from './edit-discussion-advanced/edit-discussion-advanced.component';
+import { DiscussionAuthoring } from './discussion-authoring/discussion-authoring.component';
const discussionAuthoringComponentModule = angular
.module('discussionAuthoringComponentModule', ['pascalprecht.translate'])
.service('DiscussionService', downgradeInjectable(DiscussionService))
- .component('discussionAuthoring', DiscussionAuthoring)
.component('editDiscussionAdvanced', EditDiscussionAdvancedComponent)
+ .directive(
+ 'discussionAuthoring',
+ downgradeComponent({ component: DiscussionAuthoring }) as angular.IDirectiveFactory
+ )
.config([
'$translatePartialLoaderProvider',
($translatePartialLoaderProvider) => {
diff --git a/src/main/webapp/wise5/components/discussion/discussionService.ts b/src/main/webapp/wise5/components/discussion/discussionService.ts
index 7249536a45..78467bf01e 100644
--- a/src/main/webapp/wise5/components/discussion/discussionService.ts
+++ b/src/main/webapp/wise5/components/discussion/discussionService.ts
@@ -39,7 +39,7 @@ export class DiscussionService extends ComponentService {
createComponent() {
const component: any = super.createComponent();
component.type = 'Discussion';
- component.prompt = this.getTranslation('ENTER_PROMPT_HERE');
+ component.prompt = '';
component.isStudentAttachmentEnabled = true;
component.gateClassmateResponses = true;
return component;
diff --git a/src/main/webapp/wise5/components/draw/draw-authoring/draw-authoring.component.ts b/src/main/webapp/wise5/components/draw/draw-authoring/draw-authoring.component.ts
index 930150944a..c17659ba9a 100644
--- a/src/main/webapp/wise5/components/draw/draw-authoring/draw-authoring.component.ts
+++ b/src/main/webapp/wise5/components/draw/draw-authoring/draw-authoring.component.ts
@@ -176,16 +176,6 @@ export class DrawAuthoring extends ComponentAuthoring {
this.componentChanged();
}
- chooseBackgroundImage(): void {
- const params = {
- isPopup: true,
- nodeId: this.nodeId,
- componentId: this.componentId,
- target: 'background'
- };
- this.openAssetChooser(params);
- }
-
chooseStampImage(stampIndex: number): void {
const params = {
isPopup: true,
diff --git a/src/main/webapp/wise5/components/label/authoring.html b/src/main/webapp/wise5/components/label/authoring.html
deleted file mode 100644
index 2e53f91e8a..0000000000
--- a/src/main/webapp/wise5/components/label/authoring.html
+++ /dev/null
@@ -1,373 +0,0 @@
-
-
-
-
-
-
- {{ ::'SHOW_SAVE_BUTTON' | translate }}
-
-
-
-
- {{ ::'SHOW_SUBMIT_BUTTON' | translate }}
-
-
-
-
- {{ ::'SHOW_ADD_TO_NOTEBOOK_BUTTON' | translate }}
-
-
-
-
- {{ ::'MAX_SUBMIT' | translate }}
-
-
-
-
-
-
-
-
-
-
-
-
- {{ ::'CONNECTED_COMPONENTS' | translate }}
-
-
- add
-
- {{ ::'ADD_CONNECTED_COMPONENT' | translate }}
-
-
-
-
-
-
- {{ ::'step' | translate }}
-
-
- {{ labelController.getNodePositionAndTitleByNodeId(item.$key) }}
-
-
-
-
- {{ ::'component' | translate }}
-
-
- {{ componentIndex + 1 }}. {{ component.type }}
-
- ({{ ::'thisComponent' | translate }})
-
-
-
-
-
- {{ ::'type' | translate }}
-
-
- {{ ::'importWork' | translate }}
-
-
- {{ ::'showWork' | translate }}
-
-
-
-
-
-
- delete
-
- {{ ::'DELETE' | translate }}
-
-
-
-
-
-
-
-
- {{ ::'importWorkAsBackground' | translate }}
-
-
-
-
-
-
-
-
-
-
-
- {{ ::'PROMPT' | translate }}
-
-
-
-
- {{ ::'BACKGROUND_IMAGE' | translate }}
-
-
-
- insert_photo
-
- {{ ::'chooseAnImage' | translate }}
-
-
-
-
-
- {{ ::'label.canvasWidth' | translate }}
-
-
-
- {{ ::'label.canvasHeight' | translate }}
-
-
-
-
-
- {{ ::'label.pointSize' | translate }}
-
-
-
- {{ ::'label.fontSize' | translate }}
-
-
-
- {{ ::'label.labelWidth' | translate }}
-
-
-
-
-
- {{ ::'label.canStudentCreateLabels' | translate }}
-
-
-
- {{ ::'label.enableDots' | translate }}
-
-
-
- {{ ::'label.allowStudentToUploadImageForBackground' | translate }}
-
-
-
-
-
{{ ::'label.starterLabels' | translate }}
-
- add
-
- {{ ::'label.addStarterLabel' | translate }}
-
-
-
-
- {{ ::'label.thereAreNoStarterLabels' | translate }}
-
-
-
-
- create
-
- {{ ::'label.saveStarterLabels' | translate }}
-
-
-
- delete_sweep
-
- {{ ::'label.deleteStarterLabels' | translate }}
-
-
-
-
-
diff --git a/src/main/webapp/wise5/components/label/label-authoring/label-authoring.component.html b/src/main/webapp/wise5/components/label/label-authoring/label-authoring.component.html
new file mode 100644
index 0000000000..9aa57edb6b
--- /dev/null
+++ b/src/main/webapp/wise5/components/label/label-authoring/label-authoring.component.html
@@ -0,0 +1,236 @@
+
+ Prompt
+
+
+
+
+ Background Image
+
+
+
+ insert_photo
+
+
+
+
+ Canvas Width (px)
+
+
+
+ Canvas Height (px)
+
+
+
+
+
+ Point Radius Size (px)
+
+
+
+ Font Size
+
+
+
+ Label Max Character Width
+
+
+
+
+
+
+ Can Student Create Labels
+
+
+
+
+ Enable Dots
+
+
+
+
+ Allow Student to Upload Image for Background
+
+
+
+
+
+ Starter Labels
+
+ add
+
+
+
+ There are no starter labels. Click the "Add Label" button to add a starter label.
+
+
+
+
+
+ create
+
+
+ delete_sweep
+
+
diff --git a/src/main/webapp/wise5/components/label/label-authoring/label-authoring.component.scss b/src/main/webapp/wise5/components/label/label-authoring/label-authoring.component.scss
new file mode 100644
index 0000000000..2115fcb9d5
--- /dev/null
+++ b/src/main/webapp/wise5/components/label/label-authoring/label-authoring.component.scss
@@ -0,0 +1,64 @@
+.prompt {
+ width: 100%;
+}
+
+.background-image {
+ width: 80%;
+}
+
+.input {
+ margin-right: 20px;
+}
+
+.checkbox {
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+
+.starter-labels-button-container {
+ margin-top: 20px;
+ margin-bottom: 20px;
+}
+
+.starter-labels-button-label {
+ margin-right: 10px;
+}
+
+.starter-label-container {
+ border: 2px solid #dddddd;
+ border-radius: 5px;
+ margin-bottom: 10px;
+ padding: 20px 20px 10px 20px;
+}
+
+.info-block {
+ margin-bottom: 20px;
+ text-align: center;
+ font-weight: 500;
+}
+
+.label-input {
+ width: 40%;
+}
+
+.color-input {
+ width: 30%;
+}
+
+.coordinate-location-label {
+ margin-right: 20px;
+}
+
+.coordinate-input {
+ width: 15%;
+}
+
+.starter-labels-buttons-container {
+ margin-top: 20px;
+ margin-bottom: 10px;
+ margin-left: 10px;
+}
+
+.starter-labels-button {
+ margin-right: 10px;
+}
\ No newline at end of file
diff --git a/src/main/webapp/wise5/components/label/label-authoring/label-authoring.component.ts b/src/main/webapp/wise5/components/label/label-authoring/label-authoring.component.ts
new file mode 100644
index 0000000000..2c2ea4ff2b
--- /dev/null
+++ b/src/main/webapp/wise5/components/label/label-authoring/label-authoring.component.ts
@@ -0,0 +1,124 @@
+'use strict';
+
+import { Component } from '@angular/core';
+import { ComponentAuthoring } from '../../../authoringTool/components/component-authoring.component';
+import { ConfigService } from '../../../services/configService';
+import { NodeService } from '../../../services/nodeService';
+import { ProjectAssetService } from '../../../../site/src/app/services/projectAssetService';
+import { TeacherProjectService } from '../../../services/teacherProjectService';
+import { Subject, Subscription } from 'rxjs';
+import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
+
+@Component({
+ selector: 'label-authoring',
+ templateUrl: 'label-authoring.component.html',
+ styleUrls: ['label-authoring.component.scss']
+})
+export class LabelAuthoring extends ComponentAuthoring {
+ numberInputChange: Subject = new Subject();
+ textInputChange: Subject = new Subject();
+
+ numberInputChangeSubscription: Subscription;
+ textInputChangeSubscription: Subscription;
+
+ constructor(
+ protected ConfigService: ConfigService,
+ protected NodeService: NodeService,
+ protected ProjectAssetService: ProjectAssetService,
+ protected ProjectService: TeacherProjectService
+ ) {
+ super(ConfigService, NodeService, ProjectAssetService, ProjectService);
+ this.numberInputChangeSubscription = this.numberInputChange
+ .pipe(debounceTime(1000), distinctUntilChanged())
+ .subscribe(() => {
+ this.componentChanged();
+ });
+ this.textInputChangeSubscription = this.textInputChange
+ .pipe(debounceTime(1000), distinctUntilChanged())
+ .subscribe(() => {
+ this.componentChanged();
+ });
+ }
+
+ ngOnInit() {
+ super.ngOnInit();
+ if (this.authoringComponentContent.enableCircles == null) {
+ // If this component was created before enableCircles was implemented, we will default it to
+ // true in the authoring so that the "Enable Dots" checkbox is checked.
+ this.authoringComponentContent.enableCircles = true;
+ }
+ }
+
+ ngOnDestroy() {
+ super.ngOnDestroy();
+ this.unsubscribeAll();
+ }
+
+ unsubscribeAll() {
+ this.numberInputChangeSubscription.unsubscribe();
+ this.textInputChangeSubscription.unsubscribe();
+ }
+
+ addLabel(): void {
+ const newLabel = {
+ text: $localize`Enter text here`,
+ color: 'blue',
+ pointX: 100,
+ pointY: 100,
+ textX: 200,
+ textY: 200,
+ canEdit: false,
+ canDelete: false
+ };
+ this.authoringComponentContent.labels.push(newLabel);
+ this.componentChanged();
+ }
+
+ deleteLabel(index: number, label: any): void {
+ if (confirm($localize`Are you sure you want to delete this label?\n\n${label.text}`)) {
+ this.authoringComponentContent.labels.splice(index, 1);
+ this.componentChanged();
+ }
+ }
+
+ assetSelected({ nodeId, componentId, assetItem, target }): void {
+ super.assetSelected({ nodeId, componentId, assetItem, target });
+ const fileName = assetItem.fileName;
+ if (target === 'background') {
+ this.authoringComponentContent.backgroundImage = fileName;
+ this.componentChanged();
+ }
+ }
+
+ saveStarterLabels(): void {
+ if (confirm($localize`Are you sure you want to save the starter labels?`)) {
+ this.NodeService.requestStarterState({ nodeId: this.nodeId, componentId: this.componentId });
+ }
+ }
+
+ saveStarterState(starterState: any): void {
+ this.authoringComponentContent.labels = starterState;
+ this.componentChanged();
+ }
+
+ compareTextAlphabetically(stringA: string, stringB: string) {
+ if (stringA < stringB) {
+ return -1;
+ } else if (stringA > stringB) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ deleteStarterLabels(): void {
+ if (confirm($localize`label.areYouSureYouWantToDeleteAllTheStarterLabels`)) {
+ this.authoringComponentContent.labels = [];
+ this.componentChanged();
+ }
+ }
+
+ openColorViewer(): void {
+ window.open('http://www.javascripter.net/faq/colornam.htm');
+ }
+}
diff --git a/src/main/webapp/wise5/components/label/labelAuthoring.ts b/src/main/webapp/wise5/components/label/labelAuthoring.ts
deleted file mode 100644
index df29a8ac22..0000000000
--- a/src/main/webapp/wise5/components/label/labelAuthoring.ts
+++ /dev/null
@@ -1,177 +0,0 @@
-'use strict';
-
-import * as $ from 'jquery';
-import * as fabric from 'fabric';
-window['fabric'] = fabric.fabric;
-import html2canvas from 'html2canvas';
-import { Directive } from '@angular/core';
-import { EditComponentController } from '../../authoringTool/components/editComponentController';
-
-@Directive()
-class LabelAuthoringController extends EditComponentController {
- static $inject = [
- '$filter',
- '$window',
- 'ConfigService',
- 'NodeService',
- 'NotificationService',
- 'ProjectAssetService',
- 'ProjectService',
- 'UtilService'
- ];
-
- constructor(
- $filter,
- private $window,
- ConfigService,
- NodeService,
- NotificationService,
- ProjectAssetService,
- ProjectService,
- UtilService
- ) {
- super(
- $filter,
- ConfigService,
- NodeService,
- NotificationService,
- ProjectAssetService,
- ProjectService,
- UtilService
- );
- }
-
- $onInit() {
- super.$onInit();
- if (this.authoringComponentContent.enableCircles == null) {
- /*
- * If this component was created before enableCircles was implemented,
- * we will default it to true in the authoring so that the
- * "Enable Dots" checkbox is checked.
- */
- this.authoringComponentContent.enableCircles = true;
- }
- }
-
- addLabelClicked(): void {
- const newLabel = {
- text: this.$translate('label.enterTextHere'),
- color: 'blue',
- pointX: 100,
- pointY: 100,
- textX: 200,
- textY: 200,
- canEdit: false,
- canDelete: false
- };
- this.authoringComponentContent.labels.push(newLabel);
- this.componentChanged();
- }
-
- /**
- * Delete a label in the authoring view
- * @param index the index of the label in the labels array
- */
- deleteLabelClicked(index: number, label: any): void {
- const answer = confirm(
- this.$translate('label.areYouSureYouWantToDeleteThisLabel', {
- selectedLabelText: label.textString
- })
- );
- if (answer) {
- this.authoringComponentContent.labels.splice(index, 1);
- this.componentChanged();
- }
- }
-
- chooseBackgroundImage(): void {
- const params = {
- isPopup: true,
- nodeId: this.nodeId,
- componentId: this.componentId,
- target: 'background'
- };
- this.openAssetChooser(params);
- }
-
- assetSelected({ nodeId, componentId, assetItem, target }): void {
- super.assetSelected({ nodeId, componentId, assetItem, target });
- const fileName = assetItem.fileName;
- if (target === 'background') {
- this.authoringComponentContent.backgroundImage = fileName;
- this.componentChanged();
- }
- }
-
- saveStarterLabels(): void {
- if (confirm(this.$translate('label.areYouSureYouWantToSaveTheStarterLabels'))) {
- this.NodeService.requestStarterState({ nodeId: this.nodeId, componentId: this.componentId });
- }
- }
-
- saveStarterState(starterState: any): void {
- starterState.sort(this.labelTextComparator);
- this.authoringComponentContent.labels = starterState;
- this.componentChanged();
- }
-
- /**
- * A comparator used to sort labels alphabetically
- * It should be used like labels.sort(this.labelTextComparator);
- * @param labelA a label object
- * @param labelB a label object
- * @return -1 if labelA comes before labelB
- * 1 if labelB comes after labelB
- * 0 of the labels are equal
- */
- labelTextComparator(labelA: any, labelB: any): number {
- if (labelA.text < labelB.text) {
- return -1;
- } else if (labelA.text > labelB.text) {
- return 1;
- } else {
- if (labelA.color < labelB.color) {
- return -1;
- } else if (labelA.color > labelB.color) {
- return 1;
- } else {
- if (labelA.pointX < labelB.pointX) {
- return -1;
- } else if (labelA.pointX > labelB.pointX) {
- return 1;
- } else {
- if (labelA.pointY < labelB.pointY) {
- return -1;
- } else if (labelA.pointY > labelB.pointY) {
- return 1;
- } else {
- return 0;
- }
- }
- }
- }
- }
-
- deleteStarterLabels(): void {
- if (confirm(this.$translate('label.areYouSureYouWantToDeleteAllTheStarterLabels'))) {
- this.authoringComponentContent.labels = [];
- this.componentChanged();
- }
- }
-
- openColorViewer(): void {
- this.$window.open('http://www.javascripter.net/faq/colornam.htm');
- }
-}
-
-const LabelAuthoring = {
- bindings: {
- nodeId: '@',
- componentId: '@'
- },
- controller: LabelAuthoringController,
- controllerAs: 'labelController',
- templateUrl: 'wise5/components/label/authoring.html'
-};
-
-export default LabelAuthoring;
diff --git a/src/main/webapp/wise5/components/label/labelAuthoringComponentModule.ts b/src/main/webapp/wise5/components/label/labelAuthoringComponentModule.ts
index cceefafef9..e6bd14a03c 100644
--- a/src/main/webapp/wise5/components/label/labelAuthoringComponentModule.ts
+++ b/src/main/webapp/wise5/components/label/labelAuthoringComponentModule.ts
@@ -1,15 +1,18 @@
'use strict';
import * as angular from 'angular';
-import { downgradeInjectable } from '@angular/upgrade/static';
+import { downgradeComponent, downgradeInjectable } from '@angular/upgrade/static';
import { LabelService } from './labelService';
-import LabelAuthoring from './labelAuthoring';
import { EditLabelAdvancedComponent } from './edit-label-advanced/edit-label-advanced.component';
+import { LabelAuthoring } from './label-authoring/label-authoring.component';
const labelAuthoringComponentModule = angular
.module('labelAuthoringComponentModule', ['pascalprecht.translate'])
.service('LabelService', downgradeInjectable(LabelService))
- .component('labelAuthoring', LabelAuthoring)
+ .directive(
+ 'labelAuthoring',
+ downgradeComponent({ component: LabelAuthoring }) as angular.IDirectiveFactory
+ )
.component('editLabelAdvanced', EditLabelAdvancedComponent)
.config([
'$translatePartialLoaderProvider',
diff --git a/src/main/webapp/wise5/components/table/authoring.html b/src/main/webapp/wise5/components/table/authoring.html
deleted file mode 100644
index 08bbdb80d3..0000000000
--- a/src/main/webapp/wise5/components/table/authoring.html
+++ /dev/null
@@ -1,381 +0,0 @@
-
-
-
-
-
-
-
- {{ ::'SHOW_SAVE_BUTTON' | translate }}
-
-
-
-
- {{ ::'SHOW_SUBMIT_BUTTON' | translate }}
-
-
-
-
- {{ ::'SHOW_ADD_TO_NOTEBOOK_BUTTON' | translate }}
-
-
-
-
- {{ ::'MAX_SUBMIT' | translate }}
-
-
-
-
-
{{ ::'table.dataExplorer' | translate }}
-
-
- {{ ::'table.enableDataExplorer' | translate }}
-
-
-
-
-
{{ ::'table.allowedGraphTypes' | translate }}
-
- {{ ::'table.scatterPlot' | translate }}
-
-
- {{ ::'table.lineGraph' | translate }}
-
-
- {{ ::'table.barGraph' | translate }}
-
-
-
-
- {{ ::'table.showScatterPlotRegressionLine' | translate }}
-
-
-
-
- {{ ::'table.numberOfSeries' | translate }}
-
-
-
-
-
- {{ ::'table.numberOfYAxes' | translate }}
-
-
-
-
-
-
- {{ ::'table.series' | translate }} {{ $index + 1 }}
-
-
-
- {{ ::'table.yAxis' | translate }} {{ $index + 1 }}
-
-
-
-
-
-
-
-
- {{ ::'table.canStudentEditAxisLabels' | translate }}
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ ::'CONNECTED_COMPONENTS' | translate }}
-
-
- add
-
- {{ ::'ADD_CONNECTED_COMPONENT' | translate }}
-
-
-
-
-
-
- {{ ::'step' | translate }}
-
-
- {{tableController.getNodePositionAndTitleByNodeId(item.$key)}}
-
-
-
-
- {{ ::'component' | translate }}
-
-
- {{ componentIndex + 1 }}. {{component.type}}
-
- ({{ ::'thisComponent' | translate }})
-
-
-
-
-
- {{ ::'type' | translate }}
-
-
- {{ ::'importWork' | translate }}
-
-
- {{ ::'showWork' | translate }}
-
-
-
-
- {{ ::'action' | translate }}
-
-
- {{ ::'merge' | translate }}
-
-
- {{ ::'append' | translate }}
-
-
-
-
-
-
- delete
-
- {{ ::'DELETE' | translate }}
-
-
-
-
-
- {{ ::'table.onlyShowDataAtMouseXPosition' | translate }}
-
-
-
-
-
-
-
-
-
-
- {{ ::'PROMPT' | translate }}
-
-
-
-
-
- {{ ::'table.columns' | translate }}
-
-
-
- {{ ::'table.rows' | translate }}
-
-
-
- {{ ::'table.globalCellSize' | translate }}
-
-
-
-
-
-
-
-
- {{ ::'table.makeAllCellsEditable' | translate }}
-
-
- {{ ::'table.makeAllCellsUneditable' | translate }}
-
-
-
-
-
diff --git a/src/main/webapp/wise5/components/table/table-authoring/table-authoring.component.html b/src/main/webapp/wise5/components/table/table-authoring/table-authoring.component.html
new file mode 100644
index 0000000000..9fcbfba3af
--- /dev/null
+++ b/src/main/webapp/wise5/components/table/table-authoring/table-authoring.component.html
@@ -0,0 +1,181 @@
+
+ Prompt
+
+
+
+
+ Columns
+
+
+
+ Rows
+
+
+
+ Global Cell Size
+
+
+
+
+
+
+
+
+
+ loupe
+
+
+ delete
+
+
+ loupe
+
+
+
+
+
+
+
+
+
+ loupe
+
+
+ delete
+
+
+ loupe
+
+
+
+
+
+
+
+
+ Editable
+
+
+
+
+
+
+
+
+
+
+
+
+ Optional
+
+
+
+
+
+ Column Cell Size
+
+
+
+
+
+
+
+
+ Make All Cells Editable
+
+
+ Make All Cells Uneditable
+
+
\ No newline at end of file
diff --git a/src/main/webapp/wise5/components/table/table-authoring/table-authoring.component.scss b/src/main/webapp/wise5/components/table/table-authoring/table-authoring.component.scss
new file mode 100644
index 0000000000..cdd97d67ff
--- /dev/null
+++ b/src/main/webapp/wise5/components/table/table-authoring/table-authoring.component.scss
@@ -0,0 +1,62 @@
+.prompt {
+ width: 100%;
+}
+
+.size-input {
+ width: 120px;
+ margin-right: 20px;
+}
+
+.table {
+ width: 100%;
+}
+
+.rotate90 {
+ -webkit-transform: rotate(90deg);
+ transform: rotate(90deg);
+}
+
+.rotate270 {
+ -webkit-transform: rotate(270deg);
+ transform: rotate(270deg);
+}
+
+.column-buttons {
+ margin: 5px;
+}
+
+.row-buttons {
+ margin-top: 5px;
+ margin-bottom: 5px;
+}
+
+.spacer {
+ width: 56px;
+}
+
+.outer-cell-container {
+ border: 1px solid black;
+ padding: 5px;
+ width: auto;
+}
+
+.inner-cell-container {
+ border: 1px solid black;
+ padding: 10px;
+}
+
+.cell-text {
+ width: 100%;
+}
+
+.blank-row-cell {
+ height: 20px;
+}
+
+::ng-deep .mat-form-field-infix {
+ width: auto !important;
+}
+
+.make-all-cells-editable-buttons {
+ margin: 10px;
+}
\ No newline at end of file
diff --git a/src/main/webapp/wise5/components/table/table-authoring/table-authoring.component.ts b/src/main/webapp/wise5/components/table/table-authoring/table-authoring.component.ts
new file mode 100644
index 0000000000..0d4cfa8f31
--- /dev/null
+++ b/src/main/webapp/wise5/components/table/table-authoring/table-authoring.component.ts
@@ -0,0 +1,361 @@
+'use strict';
+
+import { Component } from '@angular/core';
+import { Subject, Subscription } from 'rxjs';
+import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
+import { ProjectAssetService } from '../../../../site/src/app/services/projectAssetService';
+import { ComponentAuthoring } from '../../../authoringTool/components/component-authoring.component';
+import { ConfigService } from '../../../services/configService';
+import { NodeService } from '../../../services/nodeService';
+import { TeacherProjectService } from '../../../services/teacherProjectService';
+
+@Component({
+ selector: 'table-authoring',
+ templateUrl: 'table-authoring.component.html',
+ styleUrls: ['table-authoring.component.scss']
+})
+export class TableAuthoring extends ComponentAuthoring {
+ columnCellSizes: any;
+
+ numColumnsChange: Subject
= new Subject();
+ numRowsChange: Subject = new Subject();
+ globalCellSizeChange: Subject = new Subject();
+ inputChange: Subject = new Subject();
+
+ numColumnsChangeSubscription: Subscription;
+ numRowsChangeSubscription: Subscription;
+ globalCellSizeChangeSubscription: Subscription;
+ inputChangeSubscription: Subscription;
+
+ constructor(
+ protected ConfigService: ConfigService,
+ protected NodeService: NodeService,
+ protected ProjectAssetService: ProjectAssetService,
+ protected ProjectService: TeacherProjectService
+ ) {
+ super(ConfigService, NodeService, ProjectAssetService, ProjectService);
+ this.numColumnsChangeSubscription = this.numColumnsChange
+ .pipe(debounceTime(1000), distinctUntilChanged())
+ .subscribe(() => {
+ this.tableNumColumnsChanged();
+ });
+ this.numRowsChangeSubscription = this.numRowsChange
+ .pipe(debounceTime(1000), distinctUntilChanged())
+ .subscribe(() => {
+ this.tableNumRowsChanged();
+ });
+ this.globalCellSizeChangeSubscription = this.globalCellSizeChange
+ .pipe(debounceTime(1000), distinctUntilChanged())
+ .subscribe(() => {
+ this.componentChanged();
+ });
+ this.inputChangeSubscription = this.inputChange
+ .pipe(debounceTime(1000), distinctUntilChanged())
+ .subscribe(() => {
+ this.componentChanged();
+ });
+ }
+
+ ngOnInit() {
+ super.ngOnInit();
+ this.columnCellSizes = this.parseColumnCellSizes(this.componentContent);
+ }
+
+ ngOnDestroy() {
+ super.ngOnDestroy();
+ this.unsubscribeAll();
+ }
+
+ unsubscribeAll() {
+ this.numColumnsChangeSubscription.unsubscribe();
+ this.numRowsChangeSubscription.unsubscribe();
+ this.globalCellSizeChangeSubscription.unsubscribe();
+ this.inputChangeSubscription.unsubscribe();
+ }
+
+ tableNumRowsChanged(): void {
+ const oldValue = this.getNumRowsInTableData();
+ const newValue = this.authoringComponentContent.numRows;
+ if (newValue < oldValue) {
+ if (this.areRowsAfterEmpty(newValue)) {
+ this.tableSizeChanged();
+ } else {
+ if (confirm($localize`Are you sure you want to decrease the number of rows?`)) {
+ this.tableSizeChanged();
+ } else {
+ this.authoringComponentContent.numRows = oldValue;
+ }
+ }
+ } else {
+ this.tableSizeChanged();
+ }
+ }
+
+ areRowsAfterEmpty(rowIndex: number): boolean {
+ const oldNumRows = this.getNumRowsInTableData();
+ for (let r = rowIndex; r < oldNumRows; r++) {
+ if (!this.isRowEmpty(r)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ isRowEmpty(rowIndex: number): boolean {
+ const tableData = this.authoringComponentContent.tableData;
+ for (const cell of tableData[rowIndex]) {
+ if (!this.isEmpty(cell.text)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ tableNumColumnsChanged(): void {
+ const oldValue = this.getNumColumnsInTableData();
+ const newValue = this.authoringComponentContent.numColumns;
+ if (newValue < oldValue) {
+ if (this.areColumnsAfterEmpty(newValue)) {
+ this.tableSizeChanged();
+ } else {
+ if (confirm($localize`Are you sure you want to decrease the number of columns?`)) {
+ this.tableSizeChanged();
+ } else {
+ this.authoringComponentContent.numColumns = oldValue;
+ }
+ }
+ } else {
+ this.tableSizeChanged();
+ }
+ }
+
+ areColumnsAfterEmpty(columnIndex: number): boolean {
+ const oldNumColumns = this.getNumColumnsInTableData();
+ for (let c = columnIndex; c < oldNumColumns; c++) {
+ if (!this.isColumnEmpty(c)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ isColumnEmpty(columnIndex: number): boolean {
+ for (const row of this.authoringComponentContent.tableData) {
+ const cell = row[columnIndex];
+ if (!this.isEmpty(cell.text)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ isEmpty(txt: string): boolean {
+ return txt == null || txt == '';
+ }
+
+ tableSizeChanged(): void {
+ this.authoringComponentContent.tableData = this.getUpdatedTable(
+ this.authoringComponentContent.numRows,
+ this.authoringComponentContent.numColumns
+ );
+ this.componentChanged();
+ }
+
+ /**
+ * Create a table with the given dimensions. Populate the cells with the cells from the old table.
+ * @param newNumRows the number of rows in the new table
+ * @param newNumColumns the number of columns in the new table
+ * @returns a new table
+ */
+ getUpdatedTable(newNumRows: number, newNumColumns: number): any {
+ const newTable = [];
+ for (let r = 0; r < newNumRows; r++) {
+ const newRow = [];
+ for (let c = 0; c < newNumColumns; c++) {
+ let cell = this.getCellObjectFromTableData(c, r);
+ if (cell == null) {
+ cell = this.createEmptyCell();
+ }
+ newRow.push(cell);
+ }
+ newTable.push(newRow);
+ }
+ return newTable;
+ }
+
+ /**
+ * Get the cell object at the given x, y location
+ * @param x the column number (zero indexed)
+ * @param y the row number (zero indexed)
+ * @returns the cell at the given x, y location or null if there is none
+ */
+ getCellObjectFromTableData(x: number, y: number): any {
+ let cellObject = null;
+ const tableData = this.authoringComponentContent.tableData;
+ if (tableData != null) {
+ const row = tableData[y];
+ if (row != null) {
+ cellObject = row[x];
+ }
+ }
+ return cellObject;
+ }
+
+ createEmptyCell(): any {
+ return {
+ text: '',
+ editable: true,
+ size: null
+ };
+ }
+
+ insertRow(rowIndex: number): void {
+ const tableData = this.authoringComponentContent.tableData;
+ const newRow = [];
+ const numColumns = this.authoringComponentContent.numColumns;
+ for (let c = 0; c < numColumns; c++) {
+ const newCell = this.createEmptyCell();
+ const cellSize = this.columnCellSizes[c];
+ if (cellSize != null) {
+ newCell.size = cellSize;
+ }
+ newRow.push(newCell);
+ }
+ tableData.splice(rowIndex, 0, newRow);
+ this.authoringComponentContent.numRows++;
+ this.componentChanged();
+ }
+
+ deleteRow(rowIndex: number): void {
+ if (confirm($localize`Are you sure you want to delete this row?`)) {
+ const tableData = this.authoringComponentContent.tableData;
+ if (tableData != null) {
+ tableData.splice(rowIndex, 1);
+ this.authoringComponentContent.numRows--;
+ }
+ this.componentChanged();
+ }
+ }
+
+ insertColumn(columnIndex: number): void {
+ const tableData = this.authoringComponentContent.tableData;
+ const numRows = this.authoringComponentContent.numRows;
+ for (let r = 0; r < numRows; r++) {
+ const row = tableData[r];
+ const newCell = this.createEmptyCell();
+ row.splice(columnIndex, 0, newCell);
+ }
+ this.authoringComponentContent.numColumns++;
+ this.parseColumnCellSizes(this.authoringComponentContent);
+ this.componentChanged();
+ }
+
+ deleteColumn(columnIndex: number): void {
+ if (confirm($localize`Are you sure you want to delete this column?`)) {
+ const tableData = this.authoringComponentContent.tableData;
+ const numRows = this.authoringComponentContent.numRows;
+ for (let r = 0; r < numRows; r++) {
+ const row = tableData[r];
+ row.splice(columnIndex, 1);
+ }
+ this.authoringComponentContent.numColumns--;
+ this.parseColumnCellSizes(this.authoringComponentContent);
+ this.componentChanged();
+ }
+ }
+
+ /**
+ * Get the number of rows in the table data. This is slightly different from just getting the
+ * numRows field in the component content. Usually the number of rows will be the same. In some
+ * cases it can be different such as during authoring immediately after the author changes the
+ * number of rows using the number of rows input.
+ * @return {number} The number of rows in the table data.
+ */
+ getNumRowsInTableData(): number {
+ return this.authoringComponentContent.tableData.length;
+ }
+
+ /**
+ * Get the number of columns in the table data. This is slightly different from just getting the
+ * numColumns field in the component content. Usually the number of columns will be the same. In
+ * some cases it can be different such as during authoring immediately after the author changes
+ * the number of columns using the number of columns input.
+ * @return {number} The number of columns in the table data.
+ */
+ getNumColumnsInTableData(): number {
+ const tableData = this.authoringComponentContent.tableData;
+ if (tableData.length > 0) {
+ return tableData[0].length;
+ }
+ return 0;
+ }
+
+ setAllCellsUneditable(): void {
+ this.setAllCellsIsEditable(false);
+ this.componentChanged();
+ }
+
+ setAllCellsEditable(): void {
+ this.setAllCellsIsEditable(true);
+ this.componentChanged();
+ }
+
+ setAllCellsIsEditable(isEditable: boolean): void {
+ for (const row of this.authoringComponentContent.tableData) {
+ for (const cell of row) {
+ cell.editable = isEditable;
+ }
+ }
+ }
+
+ /**
+ * Parse the column cell sizes. We will get the column cell sizes by looking at the size value of
+ * each cell in the first row.
+ * @param componentContent the component content
+ */
+ parseColumnCellSizes(componentContent: any): any {
+ const columnCellSizes = {};
+ const tableData = componentContent.tableData;
+ const firstRow = tableData[0];
+ if (firstRow != null) {
+ for (let x = 0; x < firstRow.length; x++) {
+ const cell = firstRow[x];
+ columnCellSizes[x] = cell.size;
+ }
+ }
+ return columnCellSizes;
+ }
+
+ columnSizeChanged(index: number): void {
+ let cellSize = this.columnCellSizes[index];
+ if (cellSize == '') {
+ cellSize = null;
+ }
+ this.setColumnCellSizes(index, cellSize);
+ }
+
+ setColumnCellSizes(column: number, size: number): void {
+ const tableData = this.authoringComponentContent.tableData;
+ for (let r = 0; r < tableData.length; r++) {
+ const row = tableData[r];
+ const cell = row[column];
+ if (cell != null) {
+ cell.size = size;
+ }
+ }
+ this.componentChanged();
+ }
+
+ automaticallySetConnectedComponentFieldsIfPossible(connectedComponent) {
+ if (connectedComponent.type === 'importWork' && connectedComponent.action == null) {
+ connectedComponent.action = 'merge';
+ } else if (connectedComponent.type === 'showWork') {
+ connectedComponent.action = null;
+ }
+ }
+
+ connectedComponentTypeChanged(connectedComponent) {
+ this.automaticallySetConnectedComponentFieldsIfPossible(connectedComponent);
+ this.componentChanged();
+ }
+}
diff --git a/src/main/webapp/wise5/components/table/tableAuthoring.ts b/src/main/webapp/wise5/components/table/tableAuthoring.ts
deleted file mode 100644
index beef4e7fef..0000000000
--- a/src/main/webapp/wise5/components/table/tableAuthoring.ts
+++ /dev/null
@@ -1,428 +0,0 @@
-'use strict';
-
-import { Directive } from '@angular/core';
-import { EditComponentController } from '../../authoringTool/components/editComponentController';
-
-@Directive()
-class TableAuthoringController extends EditComponentController {
- columnCellSizes: any;
-
- static $inject = [
- '$filter',
- 'ConfigService',
- 'NodeService',
- 'NotificationService',
- 'ProjectAssetService',
- 'ProjectService',
- 'UtilService'
- ];
-
- constructor(
- $filter,
- ConfigService,
- NodeService,
- NotificationService,
- ProjectAssetService,
- ProjectService,
- UtilService
- ) {
- super(
- $filter,
- ConfigService,
- NodeService,
- NotificationService,
- ProjectAssetService,
- ProjectService,
- UtilService
- );
- }
-
- $onInit() {
- super.$onInit();
- this.columnCellSizes = this.parseColumnCellSizes(this.componentContent);
- }
-
- tableNumRowsChanged(oldValue: number): void {
- if (this.authoringComponentContent.numRows < oldValue) {
- if (this.areRowsAfterEmpty(this.authoringComponentContent.numRows)) {
- this.tableSizeChanged();
- } else {
- if (confirm(this.$translate('table.areYouSureYouWantToDecreaseTheNumberOfRows'))) {
- this.tableSizeChanged();
- } else {
- this.authoringComponentContent.numRows = oldValue;
- }
- }
- } else {
- this.tableSizeChanged();
- }
- }
-
- /**
- * Determine if the rows after the given index are empty.
- * @param rowIndex The index of the row to start checking at. This value is zero indexed.
- * @return {boolean} True if the row at the given index and all the rows after are empty.
- * False if the row at the given index or any row after the row index is not empty.
- */
- areRowsAfterEmpty(rowIndex: number): boolean {
- const oldNumRows = this.getNumRowsInTableData();
- for (let r = rowIndex; r < oldNumRows; r++) {
- if (!this.isRowEmpty(r)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Determine if a row has cells that are all empty string.
- * @param rowIndex The row index. This value is zero indexed.
- * @returns {boolean} True if the text in all the cells in the row are empty string.
- * False if the text in any cell in the row is not empty string.
- */
- isRowEmpty(rowIndex: number): boolean {
- const tableData = this.authoringComponentContent.tableData;
- for (const cell of tableData[rowIndex]) {
- if (cell.text != null && cell.text != '') {
- return false;
- }
- }
- return true;
- }
-
- /**
- * The author has changed the number of columns.
- * @param oldValue The previous number of columns.
- */
- tableNumColumnsChanged(oldValue: number): void {
- if (this.authoringComponentContent.numColumns < oldValue) {
- // the author is reducing the number of columns
- if (this.areColumnsAfterEmpty(this.authoringComponentContent.numColumns)) {
- // the columns that we will delete are empty so we will remove the columns
- this.tableSizeChanged();
- } else {
- if (confirm(this.$translate('table.areYouSureYouWantToDecreaseTheNumberOfColumns'))) {
- this.tableSizeChanged();
- } else {
- this.authoringComponentContent.numColumns = oldValue;
- }
- }
- } else {
- // the author is increasing the number of columns
- this.tableSizeChanged();
- }
- }
-
- /**
- * Determine if the columns after the given index are empty.
- * @param columnIndex The index of the column to start checking at. This value is zero indexed.
- * @return {boolean} True if the column at the given index and all the columns after are empty.
- * False if the column at the given index or any column after the column index is not empty.
- */
- areColumnsAfterEmpty(columnIndex: number): boolean {
- const oldNumColumns = this.getNumColumnsInTableData();
- for (let c = columnIndex; c < oldNumColumns; c++) {
- if (!this.isColumnEmpty(c)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Determine if a column has cells that are all empty string.
- * @param columnIndex The column index. This value is zero indexed.
- * @returns {boolean} True if the text in all the cells in the column are empty string.
- * False if the text in any cell in the column is not empty string.
- */
- isColumnEmpty(columnIndex: number): boolean {
- for (const row of this.authoringComponentContent.tableData) {
- const cell = row[columnIndex];
- if (cell.text != null && cell.text != '') {
- return false;
- }
- }
- return true;
- }
-
- /**
- * The table size has changed in the authoring view so we will update it
- */
- tableSizeChanged(): void {
- this.authoringComponentContent.tableData = this.getUpdatedTableSize(
- this.authoringComponentContent.numRows,
- this.authoringComponentContent.numColumns
- );
- this.componentChanged();
- }
-
- /**
- * Create a table with the given dimensions. Populate the cells with
- * the cells from the old table.
- * @param newNumRows the number of rows in the new table
- * @param newNumColumns the number of columns in the new table
- * @returns a new table
- */
- getUpdatedTableSize(newNumRows: number, newNumColumns: number): any {
- const newTable = [];
- for (let r = 0; r < newNumRows; r++) {
- const newRow = [];
- for (let c = 0; c < newNumColumns; c++) {
- let cell = this.getCellObjectFromComponentContent(c, r);
- if (cell == null) {
- cell = this.createEmptyCell();
- }
- newRow.push(cell);
- }
- newTable.push(newRow);
- }
- return newTable;
- }
-
- /**
- * Get the cell object at the given x, y location
- * @param x the column number (zero indexed)
- * @param y the row number (zero indexed)
- * @returns the cell at the given x, y location or null if there is none
- */
- getCellObjectFromComponentContent(x: number, y: number): any {
- let cellObject = null;
- const tableData = this.authoringComponentContent.tableData;
- if (tableData != null) {
- const row = tableData[y];
- if (row != null) {
- cellObject = row[x];
- }
- }
- return cellObject;
- }
-
- createEmptyCell(): any {
- return {
- text: '',
- editable: true,
- size: null
- };
- }
-
- /**
- * Insert a row into the table from the authoring view
- * @param y the row number to insert at
- */
- insertRow(y: number): void {
- const tableData = this.authoringComponentContent.tableData;
- if (tableData != null) {
- const newRow = [];
- const numColumns = this.authoringComponentContent.numColumns;
- for (let c = 0; c < numColumns; c++) {
- const newCell = this.createEmptyCell();
- const cellSize = this.columnCellSizes[c];
- if (cellSize != null) {
- newCell.size = cellSize;
- }
- newRow.push(newCell);
- }
- tableData.splice(y, 0, newRow);
- this.authoringComponentContent.numRows++;
- }
- this.componentChanged();
- }
-
- /**
- * Delete a row in the table from the authoring view
- * @param y the row number to delete
- */
- deleteRow(y: number): void {
- if (confirm(this.$translate('table.areYouSureYouWantToDeleteThisRow'))) {
- const tableData = this.authoringComponentContent.tableData;
- if (tableData != null) {
- tableData.splice(y, 1);
- this.authoringComponentContent.numRows--;
- }
- this.componentChanged();
- }
- }
-
- /**
- * Insert a column into the table from the authoring view
- * @param x the column number to insert at
- */
- insertColumn(x: number): void {
- const tableData = this.authoringComponentContent.tableData;
- if (tableData != null) {
- const numRows = this.authoringComponentContent.numRows;
- for (let r = 0; r < numRows; r++) {
- const tempRow = tableData[r];
- if (tempRow != null) {
- const newCell = this.createEmptyCell();
- tempRow.splice(x, 0, newCell);
- }
- }
- this.authoringComponentContent.numColumns++;
- this.parseColumnCellSizes(this.authoringComponentContent);
- }
- this.componentChanged();
- }
-
- /**
- * Delete a column in the table from the authoring view
- * @param x the column number to delete
- */
- deleteColumn(x: number): void {
- if (confirm(this.$translate('table.areYouSureYouWantToDeleteThisColumn'))) {
- const tableData = this.authoringComponentContent.tableData;
- if (tableData != null) {
- const numRows = this.authoringComponentContent.numRows;
- for (let r = 0; r < numRows; r++) {
- const tempRow = tableData[r];
- if (tempRow != null) {
- tempRow.splice(x, 1);
- }
- }
- this.authoringComponentContent.numColumns--;
- this.parseColumnCellSizes(this.authoringComponentContent);
- }
- this.componentChanged();
- }
- }
-
- /**
- * Get the number of rows in the table data. This is slightly different from
- * just getting the numRows field in the component content. Usually the
- * number of rows will be the same. In some cases it can be different
- * such as during authoring immediately after the author changes the number
- * of rows using the number of rows input.
- * @return {number} The number of rows in the table data.
- */
- getNumRowsInTableData(): number {
- return this.authoringComponentContent.tableData.length;
- }
-
- /**
- * Get the number of columns in the table data. This is slightly different from
- * just getting the numColumns field in the component content. Usually the
- * number of columns will be the same. In some cases it can be different
- * such as during authoring immediately after the author changes the number
- * of columns using the number of columns input.
- * @return {number} The number of columns in the table data.
- */
- getNumColumnsInTableData(): number {
- const tableData = this.authoringComponentContent.tableData;
- if (tableData.length > 0) {
- return tableData[0].length;
- }
- return 0;
- }
-
- makeAllCellsUneditable(): void {
- const tableData = this.authoringComponentContent.tableData;
- if (tableData != null) {
- for (let r = 0; r < tableData.length; r++) {
- const row = tableData[r];
- if (row != null) {
- for (let c = 0; c < row.length; c++) {
- const cell = row[c];
- if (cell != null) {
- cell.editable = false;
- }
- }
- }
- }
- }
- this.componentChanged();
- }
-
- makeAllCellsEditable(): void {
- const tableData = this.authoringComponentContent.tableData;
- if (tableData != null) {
- for (let r = 0; r < tableData.length; r++) {
- const row = tableData[r];
- if (row != null) {
- for (let c = 0; c < row.length; c++) {
- const cell = row[c];
- if (cell != null) {
- cell.editable = true;
- }
- }
- }
- }
- }
- this.componentChanged();
- }
-
- /**
- * Parse the column cell sizes. We will get the column cell sizes by looking
- * at size value of each column in the first row.
- * @param componentContent the component content
- */
- parseColumnCellSizes(componentContent: any): any {
- const columnCellSizes = {};
- const tableData = componentContent.tableData;
- if (tableData != null) {
- const firstRow = tableData[0];
- if (firstRow != null) {
- for (let x = 0; x < firstRow.length; x++) {
- const cell = firstRow[x];
- columnCellSizes[x] = cell.size;
- }
- }
- }
- return columnCellSizes;
- }
-
- columnSizeChanged(index: number): void {
- if (index != null) {
- let cellSize = this.columnCellSizes[index];
- if (cellSize == '') {
- cellSize = null;
- }
- this.setColumnCellSizes(index, cellSize);
- }
- }
-
- /**
- * Set the cell sizes for all the cells in a column
- * @param column the column number
- * @param size the cell size
- */
- setColumnCellSizes(column: number, size: number): void {
- const tableData = this.authoringComponentContent.tableData;
- if (tableData != null) {
- for (let r = 0; r < tableData.length; r++) {
- const row = tableData[r];
- if (row != null) {
- const cell = row[column];
- if (cell != null) {
- cell.size = size;
- }
- }
- }
- }
- this.componentChanged();
- }
-
- automaticallySetConnectedComponentFieldsIfPossible(connectedComponent) {
- if (connectedComponent.type === 'importWork' && connectedComponent.action == null) {
- connectedComponent.action = 'merge';
- } else if (connectedComponent.type === 'showWork') {
- connectedComponent.action = null;
- }
- }
-
- connectedComponentTypeChanged(connectedComponent) {
- this.automaticallySetConnectedComponentFieldsIfPossible(connectedComponent);
- this.componentChanged();
- }
-}
-
-const TableAuthoring = {
- bindings: {
- nodeId: '@',
- componentId: '@'
- },
- controller: TableAuthoringController,
- controllerAs: 'tableController',
- templateUrl: 'wise5/components/table/authoring.html'
-};
-
-export default TableAuthoring;
diff --git a/src/main/webapp/wise5/components/table/tableAuthoringComponentModule.ts b/src/main/webapp/wise5/components/table/tableAuthoringComponentModule.ts
index 60f9c96360..c202b806cd 100644
--- a/src/main/webapp/wise5/components/table/tableAuthoringComponentModule.ts
+++ b/src/main/webapp/wise5/components/table/tableAuthoringComponentModule.ts
@@ -2,14 +2,17 @@
import * as angular from 'angular';
import { TableService } from './tableService';
-import { downgradeInjectable } from '@angular/upgrade/static';
-import TableAuthoring from './tableAuthoring';
+import { downgradeComponent, downgradeInjectable } from '@angular/upgrade/static';
import { EditTableAdvancedComponent } from './edit-table-advanced/edit-table-advanced.component';
+import { TableAuthoring } from './table-authoring/table-authoring.component';
const tableAuthoringComponentModule = angular
.module('tableAuthoringComponentModule', ['pascalprecht.translate'])
.service('TableService', downgradeInjectable(TableService))
- .component('tableAuthoring', TableAuthoring)
+ .directive(
+ 'tableAuthoring',
+ downgradeComponent({ component: TableAuthoring }) as angular.IDirectiveFactory
+ )
.component('editTableAdvanced', EditTableAdvancedComponent)
.config([
'$translatePartialLoaderProvider',
diff --git a/src/main/webapp/wise5/services/milestoneService.ts b/src/main/webapp/wise5/services/milestoneService.ts
index 47580d6e77..561e31ed79 100644
--- a/src/main/webapp/wise5/services/milestoneService.ts
+++ b/src/main/webapp/wise5/services/milestoneService.ts
@@ -9,6 +9,7 @@ import { TeacherDataService } from './teacherDataService';
import { UtilService } from './utilService';
import { Injectable } from '@angular/core';
import { UpgradeModule } from '@angular/upgrade/static';
+import { MilestoneDetailsDialog } from '../classroomMonitor/classroomMonitorComponents/milestones/milestoneDetailsDialog/milestoneDetailsDialog';
@Injectable()
export class MilestoneService {
@@ -511,40 +512,12 @@ export class MilestoneService {
}
showMilestoneDetails(milestone: any, $event: any, hideStudentWork: boolean = false) {
- const title = this.getTranslation('MILESTONE_DETAILS_TITLE', {
- name: milestone.name
- });
- const template = `
-
-
-
${title}
-
-
-
-
-
-
-
-
- {{ ::'EDIT' | translate }}
-
-
- {{ ::'CLOSE' | translate }}
-
-
- `;
this.upgrade.$injector.get('$mdDialog').show({
parent: angular.element(document.body),
- template: template,
- ariaLabel: title,
+ templateUrl:
+ 'wise5/classroomMonitor/classroomMonitorComponents/milestones/milestoneDetailsDialog/milestoneDetailsDialog.html',
+ controller: MilestoneDetailsDialog,
+ controllerAs: '$ctrl',
fullscreen: true,
multiple: true,
targetEvent: $event,
@@ -554,73 +527,7 @@ export class MilestoneService {
$event: $event,
milestone: milestone,
hideStudentWork: hideStudentWork
- },
- controller: [
- '$scope',
- '$state',
- '$mdDialog',
- 'milestone',
- '$event',
- 'TeacherDataService',
- function DialogController(
- $scope,
- $state,
- $mdDialog,
- milestone,
- $event,
- TeacherDataService
- ) {
- $scope.milestone = milestone;
- $scope.hideStudentWork = hideStudentWork;
- $scope.event = $event;
- $scope.close = function () {
- $scope.saveMilestoneClosedEvent();
- $mdDialog.hide();
- };
- $scope.edit = function () {
- $mdDialog.hide({
- milestone: $scope.milestone,
- action: 'edit',
- $event: $event
- });
- };
- $scope.onShowWorkgroup = function (workgroup: any) {
- $scope.saveMilestoneClosedEvent();
- $mdDialog.hide();
- TeacherDataService.setCurrentWorkgroup(workgroup);
- $state.go('root.nodeProgress');
- };
- $scope.onVisitNodeGrading = function () {
- $mdDialog.hide();
- };
- $scope.saveMilestoneOpenedEvent = function () {
- $scope.saveMilestoneEvent('MilestoneOpened');
- };
- $scope.saveMilestoneClosedEvent = function () {
- $scope.saveMilestoneEvent('MilestoneClosed');
- };
- $scope.saveMilestoneEvent = function (event: any) {
- const context = 'ClassroomMonitor',
- nodeId = null,
- componentId = null,
- componentType = null,
- category = 'Navigation',
- data = { milestoneId: $scope.milestone.id },
- projectId = null;
- TeacherDataService.saveEvent(
- context,
- nodeId,
- componentId,
- componentType,
- category,
- event,
- data,
- projectId
- );
- };
- $scope.saveMilestoneOpenedEvent();
- }
- ]
+ }
});
}
}
diff --git a/src/test/java/org/wise/portal/presentation/web/controllers/user/GoogleUserAPIControllerTest.java b/src/test/java/org/wise/portal/presentation/web/controllers/user/GoogleUserAPIControllerTest.java
new file mode 100644
index 0000000000..b66900f8ff
--- /dev/null
+++ b/src/test/java/org/wise/portal/presentation/web/controllers/user/GoogleUserAPIControllerTest.java
@@ -0,0 +1,108 @@
+package org.wise.portal.presentation.web.controllers.user;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.util.HashMap;
+
+import org.easymock.TestSubject;
+import org.junit.Test;
+import org.wise.portal.presentation.web.exception.InvalidPasswordExcpetion;
+
+public class GoogleUserAPIControllerTest extends UserAPIControllerTest {
+
+ @TestSubject
+ private GoogleUserAPIController controller = new GoogleUserAPIController();
+
+ @Test
+ public void isGoogleIdExist_GoogleUserExists_ReturnTrue() {
+ expect(userService.retrieveUserByGoogleUserId(STUDENT1_GOOGLE_ID)).andReturn(student1);
+ replay(userService);
+ assertTrue(controller.isGoogleIdExist(STUDENT1_GOOGLE_ID));
+ verify(userService);
+ }
+
+ @Test
+ public void isGoogleIdExist_InvalidGoogleUserId_ReturnFalse() {
+ String invalidGoogleId = "google-id-not-exists-in-db";
+ expect(userService.retrieveUserByGoogleUserId(invalidGoogleId)).andReturn(null);
+ replay(userService);
+ assertFalse(controller.isGoogleIdExist(invalidGoogleId));
+ verify(userService);
+ }
+
+ @Test
+ public void isGoogleIdMatches_GoogleUserIdAndUserIdMatch_ReturnTrue() {
+ expect(userService.retrieveUserByGoogleUserId(STUDENT1_GOOGLE_ID)).andReturn(student1);
+ replay(userService);
+ assertTrue(controller.isGoogleIdMatches(STUDENT1_GOOGLE_ID, student1Id.toString()));
+ verify(userService);
+ }
+
+ @Test
+ public void isGoogleIdMatches_InvalidGoogleUserId_ReturnFalse() {
+ String invalidGoogleId = "google-id-not-exists-in-db";
+ expect(userService.retrieveUserByGoogleUserId(invalidGoogleId)).andReturn(null);
+ replay(userService);
+ assertFalse(controller.isGoogleIdMatches(invalidGoogleId, student1Id.toString()));
+ verify(userService);
+ }
+
+ @Test
+ public void isGoogleIdMatches_GoogleUserIdAndUserIdDoNotMatch_ReturnFalse() {
+ expect(userService.retrieveUserByGoogleUserId(STUDENT1_GOOGLE_ID)).andReturn(teacher1);
+ replay(userService);
+ assertFalse(controller.isGoogleIdMatches(STUDENT1_GOOGLE_ID, teacher1.toString()));
+ verify(userService);
+ }
+
+ @Test
+ public void getUserByGoogleId_GoogleUserExists_ReturnSuccessResponse() {
+ expect(userService.retrieveUserByGoogleUserId(STUDENT1_GOOGLE_ID)).andReturn(student1);
+ replay(userService);
+ HashMap response = controller.getUserByGoogleId(STUDENT1_GOOGLE_ID);
+ assertEquals("success", response.get("status"));
+ assertEquals(student1.getId(), response.get("userId"));
+ verify(userService);
+ }
+
+ @Test
+ public void getUserByGoogleId_InvalidGoogleUserId_ReturnErrorResponse() {
+ String invalidGoogleId = "google-id-not-exists-in-db";
+ expect(userService.retrieveUserByGoogleUserId(invalidGoogleId)).andReturn(null);
+ replay(userService);
+ HashMap response = controller.getUserByGoogleId(invalidGoogleId);
+ assertEquals("error", response.get("status"));
+ verify(userService);
+ }
+
+ @Test
+ public void unlinkGoogleAccount_InvalidNewPassword_ThrowException() {
+ expect(userService.retrieveUserByUsername(STUDENT_USERNAME)).andReturn(student1);
+ replay(userService);
+ String newPass = "";
+ try {
+ controller.unlinkGoogleAccount(studentAuth, newPass);
+ fail("InvalidPasswordException was expected");
+ } catch (Exception e) {
+ }
+ }
+
+ @Test
+ public void unlinkGoogleAccount_ValidNewPassword_ReturnUpdatedUserMap()
+ throws InvalidPasswordExcpetion {
+ String newPassword = "my new pass";
+ assertTrue(student1.getUserDetails().isGoogleUser());
+ expect(userService.retrieveUserByUsername(STUDENT_USERNAME)).andReturn(student1).times(2);
+ expect(userService.updateUserPassword(student1, newPassword)).andReturn(student1);
+ expect(appProperties.getProperty("send_email_enabled", "false")).andReturn("false");
+ replay(userService, appProperties);
+ controller.unlinkGoogleAccount(studentAuth, newPassword);
+ verify(userService, appProperties);
+ }
+}
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 251fcb0b47..c5b901ce8f 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
@@ -143,68 +143,6 @@ public void getSupportedLanguages_ThreeSupportedLocales_ReturnLanguageArray() {
verify(appProperties);
}
- @Test
- public void isGoogleIdExist_GoogleUserExists_ReturnTrue() {
- expect(userService.retrieveUserByGoogleUserId(STUDENT1_GOOGLE_ID)).andReturn(student1);
- replay(userService);
- assertTrue(userAPIController.isGoogleIdExist(STUDENT1_GOOGLE_ID));
- verify(userService);
- }
-
- @Test
- public void isGoogleIdExist_InvalidGoogleUserId_ReturnFalse() {
- String invalidGoogleId = "google-id-not-exists-in-db";
- expect(userService.retrieveUserByGoogleUserId(invalidGoogleId)).andReturn(null);
- replay(userService);
- assertFalse(userAPIController.isGoogleIdExist(invalidGoogleId));
- verify(userService);
- }
-
- @Test
- public void isGoogleIdMatches_GoogleUserIdAndUserIdMatch_ReturnTrue() {
- expect(userService.retrieveUserByGoogleUserId(STUDENT1_GOOGLE_ID)).andReturn(student1);
- replay(userService);
- assertTrue(userAPIController.isGoogleIdMatches(STUDENT1_GOOGLE_ID, student1Id.toString()));
- verify(userService);
- }
-
- @Test
- public void isGoogleIdMatches_InvalidGoogleUserId_ReturnFalse() {
- String invalidGoogleId = "google-id-not-exists-in-db";
- expect(userService.retrieveUserByGoogleUserId(invalidGoogleId)).andReturn(null);
- replay(userService);
- assertFalse(userAPIController.isGoogleIdMatches(invalidGoogleId, student1Id.toString()));
- verify(userService);
- }
-
- @Test
- public void isGoogleIdMatches_GoogleUserIdAndUserIdDoNotMatch_ReturnFalse() {
- expect(userService.retrieveUserByGoogleUserId(STUDENT1_GOOGLE_ID)).andReturn(teacher1);
- replay(userService);
- assertFalse(userAPIController.isGoogleIdMatches(STUDENT1_GOOGLE_ID, teacher1.toString()));
- verify(userService);
- }
-
- @Test
- public void getUserByGoogleId_GoogleUserExists_ReturnSuccessResponse() {
- expect(userService.retrieveUserByGoogleUserId(STUDENT1_GOOGLE_ID)).andReturn(student1);
- replay(userService);
- HashMap response = userAPIController.getUserByGoogleId(STUDENT1_GOOGLE_ID);
- assertEquals("success", response.get("status"));
- assertEquals(student1.getId(), response.get("userId"));
- verify(userService);
- }
-
- @Test
- public void getUserByGoogleId_InvalidGoogleUserId_ReturnErrorResponse() {
- String invalidGoogleId = "google-id-not-exists-in-db";
- expect(userService.retrieveUserByGoogleUserId(invalidGoogleId)).andReturn(null);
- replay(userService);
- HashMap response = userAPIController.getUserByGoogleId(invalidGoogleId);
- assertEquals("error", response.get("status"));
- verify(userService);
- }
-
@Test
public void isNameValid_InvalidName_ReturnFalse() {
assertFalse(userAPIController.isNameValid(""));