Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
2feb176
Refactor create run dialog
Aaron-Detre May 16, 2025
9c454c3
Add run type selection to create run dialog
Aaron-Detre May 20, 2025
730d254
Restrict survey student access to student home
Aaron-Detre May 21, 2025
2c79ec6
Survey runs have access links instead of access codes
Aaron-Detre May 21, 2025
1f5d62d
Fixed survey students restricted from survey bug
Aaron-Detre May 23, 2025
15b48b0
Workgroup limit reached page
Aaron-Detre May 23, 2025
25a33d4
Log out page shown if logged in when accessing survey
Aaron-Detre May 23, 2025
32126f0
Unique access links for each period
Aaron-Detre May 27, 2025
3850b8c
Submit button
Aaron-Detre May 27, 2025
42ba92c
Don't check isSurvey if preview
Aaron-Detre May 27, 2025
fdfea1e
Clean code
Aaron-Detre May 27, 2025
5008e6a
Write tests
Aaron-Detre May 28, 2025
ff1084b
Merge branch 'develop' into survey-units
Aaron-Detre May 28, 2025
8ca729c
Fix tests
Aaron-Detre May 29, 2025
02c277b
Merge branch 'survey-units' of https://github.com/WISE-Community/WISE…
Aaron-Detre May 29, 2025
36e33cb
Merge branch 'develop' into survey-units
Aaron-Detre May 29, 2025
25700aa
Updated messages
github-actions[bot] May 29, 2025
1ed1387
Merge branch 'develop' into survey-units
Aaron-Detre May 29, 2025
c15dfef
Merge branch 'survey-units' of https://github.com/WISE-Community/WISE…
Aaron-Detre May 29, 2025
27f3ac0
Fix more tests
Aaron-Detre May 29, 2025
35ea419
Fixed another test
Aaron-Detre May 29, 2025
648a110
Comment out bad test for now
Aaron-Detre May 29, 2025
2f0a24c
Comment out whole file
Aaron-Detre May 29, 2025
ba7aac8
Simplify path to launch survey to /run-survey/code
hirokiterashima May 29, 2025
840df7e
Fix tests. xdescribe logoutService tests.
hirokiterashima May 29, 2025
ab7b209
Remove log out page
Aaron-Detre May 30, 2025
deb1a4a
Prevent custom periods for surveys
Aaron-Detre May 30, 2025
bee69b6
Merge branch 'survey-units' of https://github.com/WISE-Community/WISE…
Aaron-Detre May 30, 2025
872c19f
Fix test
hirokiterashima Jun 2, 2025
7d2e64a
Hide Workgroup membership section in Edit Run Settings when in survey…
hirokiterashima Jun 2, 2025
1a669d5
Move survey unit links to share run code dialog
breity Jun 4, 2025
a776d4d
Hide class periods and lock after end date controls for survey units
breity Jun 4, 2025
7579b3d
Update tests
breity Jun 4, 2025
69f0b97
Updated messages
github-actions[bot] Jun 4, 2025
59a2af5
Cleaned up ShareRunCodeDialog and added tests
hirokiterashima Jun 4, 2025
332c37e
Clean up test and make sure isSurveyRun is set before each test. This…
hirokiterashima Jun 4, 2025
62fdf03
Update survey workgroup limit reaced and completed pages
breity Jun 4, 2025
2d209ef
Updated messages
github-actions[bot] Jun 4, 2025
41142d7
Move submit survey button to last node in unit
breity Jun 5, 2025
82deef6
Clean up SubmitSurveyComponent and add tests
hirokiterashima Jun 5, 2025
d66b170
Clean up template. Fix test.
hirokiterashima Jun 5, 2025
62c5619
Updated messages
github-actions[bot] Jun 5, 2025
bab3a70
Hide browser alert when submitting survey. Remove LogoutService and h…
hirokiterashima Jun 5, 2025
1453b42
Fix routing to home from survey completed page.
hirokiterashima Jun 6, 2025
a65573f
Fix copying access link in confirmation
hirokiterashima Jun 6, 2025
83414f9
Add tests to check if submit survey should be displayed
hirokiterashima Jun 6, 2025
028b882
Clean up test code
hirokiterashima Jun 6, 2025
91e65e7
Update wording and styles
hirokiterashima Jun 6, 2025
ab9029b
Use SessionService to logout user
hirokiterashima Jun 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { FormsModule } from '@angular/forms';
import { HTTP_INTERCEPTORS, HttpRequest, HttpHandler, HttpInterceptor } from '@angular/common/http';
import { Injectable, NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { PublicLibraryComponent } from './modules/library/public-library/public-library.component';
import { PersonalLibraryComponent } from './modules/library/personal-library/personal-library.component';
import { PublicLibraryComponent } from './modules/library/public-library/public-library.component';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
{ path: '', loadChildren: () => import('./home/home.module').then((m) => m.HomeModule) },
Expand Down Expand Up @@ -56,6 +56,10 @@ const routes: Routes = [
{
path: 'teacher',
loadChildren: () => import('./teacher/teacher.module').then((m) => m.TeacherModule)
},
{
path: 'survey',
loadChildren: () => import('./student/survey/survey.module').then((m) => m.SurveyModule)
}
];

Expand Down
3 changes: 2 additions & 1 deletion src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,8 @@ export class AppComponent {
!this.router.url.includes('/login') &&
!this.router.url.includes('/join') &&
!this.router.url.includes('/contact') &&
!this.router.url.includes('/forgot')
!this.router.url.includes('/forgot') &&
!this.router.url.includes('/survey')
);
}

Expand Down
48 changes: 24 additions & 24 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
import { NgModule, inject, provideAppInitializer } from '@angular/core';
import { AnnouncementComponent } from './announcement/announcement.component';
import { AnnouncementDialogComponent } from './announcement/announcement.component';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { ArchiveProjectService } from './services/archive-project.service';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { BrowserModule } from '@angular/platform-browser';
import { ConfigService } from './services/config.service';
import { FooterComponent } from './modules/footer/footer.component';
import { FormsModule } from '@angular/forms';
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { HeaderComponent } from './modules/header/header.component';
import { HomeModule } from './home/home.module';
import { HttpErrorInterceptor } from './http-error.interceptor';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { RouterModule } from '@angular/router';
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { MatDialogModule } from '@angular/material/dialog';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MAT_SNACK_BAR_DEFAULT_OPTIONS } from '@angular/material/snack-bar';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { ConfigService } from './services/config.service';
import { HomeModule } from './home/home.module';
import { MobileMenuComponent } from './modules/mobile-menu/mobile-menu.component';
import { NgModule, inject, provideAppInitializer } from '@angular/core';
import { RecaptchaV3Module, RECAPTCHA_V3_SITE_KEY, RECAPTCHA_BASE_URL } from 'ng-recaptcha-2';
import { RouterModule } from '@angular/router';
import { StudentService } from './student/student.service';
import { UserService } from './services/user.service';
import { TeacherService } from './teacher/teacher.service';
import { MobileMenuComponent } from './modules/mobile-menu/mobile-menu.component';
import { AnnouncementComponent } from './announcement/announcement.component';
import { AnnouncementDialogComponent } from './announcement/announcement.component';
import { TrackScrollDirective } from './track-scroll.directive';
import { RecaptchaV3Module, RECAPTCHA_V3_SITE_KEY, RECAPTCHA_BASE_URL } from 'ng-recaptcha-2';
import { ArchiveProjectService } from './services/archive-project.service';
import { FooterComponent } from './modules/footer/footer.component';
import { HeaderComponent } from './modules/header/header.component';
import { UserService } from './services/user.service';

export function initialize(
configService: ConfigService,
Expand All @@ -47,17 +47,17 @@ export function initialize(
bootstrap: [AppComponent],
imports: [
AnnouncementComponent,
BrowserModule,
BrowserAnimationsModule,
FormsModule,
AppRoutingModule,
BrowserAnimationsModule,
BrowserModule,
FooterComponent,
FormsModule,
HeaderComponent,
HomeModule,
MobileMenuComponent,
MatDialogModule,
MatSidenavModule,
MatSnackBarModule,
MatDialogModule,
MobileMenuComponent,
RecaptchaV3Module,
RouterModule.forRoot([], {
scrollPositionRestoration: 'enabled',
Expand All @@ -73,9 +73,9 @@ export function initialize(
TeacherService,
UserService,
provideAppInitializer(() => {
const initializerFn = (initialize)(inject(ConfigService), inject(UserService));
return initializerFn();
}),
const initializerFn = initialize(inject(ConfigService), inject(UserService));
return initializerFn();
}),
{
provide: MAT_SNACK_BAR_DEFAULT_OPTIONS,
useValue: {
Expand Down
17 changes: 11 additions & 6 deletions src/app/domain/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export class Run {
owner: User;
sharedOwners: User[] = [];
project: Project;
private isSurvey: boolean;

static readonly VIEW_STUDENT_WORK_PERMISSION: number = 1;
static readonly GRADE_AND_MANAGE_PERMISSION: number = 2;
Expand All @@ -39,32 +40,32 @@ export class Run {
}
}

public canViewStudentWork(userId) {
public canViewStudentWork(userId): boolean {
return (
this.isOwner(userId) ||
this.isSharedOwnerWithPermission(userId, Run.VIEW_STUDENT_WORK_PERMISSION)
);
}

public canGradeAndManage(userId) {
public canGradeAndManage(userId): boolean {
return (
this.isOwner(userId) ||
this.isSharedOwnerWithPermission(userId, Run.GRADE_AND_MANAGE_PERMISSION)
);
}

public canViewStudentNames(userId) {
public canViewStudentNames(userId): boolean {
return (
this.isOwner(userId) ||
this.isSharedOwnerWithPermission(userId, Run.VIEW_STUDENT_NAMES_PERMISSION)
);
}

isOwner(userId) {
isOwner(userId): boolean {
return this.owner.id == userId;
}

isSharedOwnerWithPermission(userId, permissionId) {
isSharedOwnerWithPermission(userId, permissionId): boolean {
for (const sharedOwner of this.sharedOwners) {
if (sharedOwner.id == userId) {
return this.userHasPermission(sharedOwner, permissionId);
Expand All @@ -73,7 +74,7 @@ export class Run {
return false;
}

userHasPermission(user: User, permission: number) {
userHasPermission(user: User, permission: number): boolean {
return user.permissions.includes(permission);
}

Expand All @@ -92,6 +93,10 @@ export class Run {
private hasEndTime(): boolean {
return this.endTime != null;
}

isSurveyRun(): boolean {
return this.isSurvey;
}
}

export function sortByRunStartTimeDesc(a: Run, b: Run): number {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,80 +6,82 @@
</button>
<mat-menu #accountMenu="matMenu" xPosition="before">
<div class="header-account-menu">
<div class="user-info flex flex-row items-center space-x-2">
<mat-icon
*ngIf="roles.includes('student'); else teacherAvatar"
i18n-aria-label
aria-label="Account avatar"
>account_circle</mat-icon
@if (!roles.includes('surveyStudent')) {
<div class="user-info flex flex-row items-center space-x-2">
<mat-icon
*ngIf="roles.includes('student'); else teacherAvatar"
i18n-aria-label
aria-label="Account avatar"
>account_circle</mat-icon
>
<ng-template #teacherAvatar>
<mat-icon i18n-aria-label aria-label="Account avatar">account_box</mat-icon>
</ng-template>
<span>{{ firstName }} {{ lastName }}</span>
</div>
<div *ngIf="isPreviousAdmin" class="user-switch">
<a (click)="switchToOriginalUser()" i18n>Switch back to original user</a>
</div>
<mat-divider></mat-divider>
<a
*ngIf="roles.includes('student')"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
mat-menu-item
routerLink="/student"
>
<ng-template #teacherAvatar>
<mat-icon i18n-aria-label aria-label="Account avatar">account_box</mat-icon>
</ng-template>
<span>{{ firstName }} {{ lastName }}</span>
</div>
<div *ngIf="isPreviousAdmin" class="user-switch">
<a (click)="switchToOriginalUser()" i18n>Switch back to original user</a>
</div>
<mat-divider></mat-divider>
<a
*ngIf="roles.includes('student')"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
mat-menu-item
routerLink="/student"
>
<mat-icon>home</mat-icon>
<span i18n>Student Home</span>
</a>
<a
*ngIf="roles.includes('teacher')"
mat-menu-item
routerLink="/teacher"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>
<mat-icon>home</mat-icon>
<span i18n>Teacher Home</span>
</a>
<a
*ngIf="roles.includes('student')"
mat-menu-item
routerLink="/student/profile/edit"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>
<mat-icon>edit</mat-icon>
<span i18n>Edit Profile</span>
</a>
<a
*ngIf="roles.includes('teacher')"
mat-menu-item
routerLink="/teacher/profile/edit"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>
<mat-icon>edit</mat-icon>
<span i18n>Edit Profile</span>
</a>
<a *ngIf="roles.includes('researcher')" mat-menu-item (click)="switchToAdmin()">
<mat-icon>settings</mat-icon>
<span i18n>Researcher Tools</span>
</a>
<a *ngIf="roles.includes('admin')" mat-menu-item (click)="switchToAdmin()">
<mat-icon>settings</mat-icon>
<span i18n>Admin Tools</span>
</a>
<a
mat-menu-item
routerLink="/help"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>
<mat-icon>help</mat-icon>
<span i18n>Help</span>
</a>
<mat-divider></mat-divider>
<mat-icon>home</mat-icon>
<span i18n>Student Home</span>
</a>
<a
*ngIf="roles.includes('teacher')"
mat-menu-item
routerLink="/teacher"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>
<mat-icon>home</mat-icon>
<span i18n>Teacher Home</span>
</a>
<a
*ngIf="roles.includes('student')"
mat-menu-item
routerLink="/student/profile/edit"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>
<mat-icon>edit</mat-icon>
<span i18n>Edit Profile</span>
</a>
<a
*ngIf="roles.includes('teacher')"
mat-menu-item
routerLink="/teacher/profile/edit"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>
<mat-icon>edit</mat-icon>
<span i18n>Edit Profile</span>
</a>
<a *ngIf="roles.includes('researcher')" mat-menu-item (click)="switchToAdmin()">
<mat-icon>settings</mat-icon>
<span i18n>Researcher Tools</span>
</a>
<a *ngIf="roles.includes('admin')" mat-menu-item (click)="switchToAdmin()">
<mat-icon>settings</mat-icon>
<span i18n>Admin Tools</span>
</a>
<a
mat-menu-item
routerLink="/help"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>
<mat-icon>help</mat-icon>
<span i18n>Help</span>
</a>
<mat-divider></mat-divider>
}
<a mat-menu-item (click)="logOut()">
<mat-icon color="warn">exit_to_app</mat-icon>
<span class="warn" i18n>Sign Out</span>
Expand Down
Loading
Loading