diff --git a/src/app/modules/library/library-project-menu/library-project-menu.component.html b/src/app/modules/library/library-project-menu/library-project-menu.component.html index 1aea9d88cf7..8d58a75a13f 100644 --- a/src/app/modules/library/library-project-menu/library-project-menu.component.html +++ b/src/app/modules/library/library-project-menu/library-project-menu.component.html @@ -3,26 +3,33 @@
- + @if (isChild) { - - + + } content_copy Copy - - edit Edit - - - share Share - - - archive - Archive - - - unarchive - Restore - + @if (canEdit) { + + edit Edit + + } + @if (canShare) { + + share Share + + } + @if (archived) { + + unarchive + Restore + + } @else { + + archive + Archive + + }
diff --git a/src/app/modules/library/library-project-menu/library-project-menu.component.spec.ts b/src/app/modules/library/library-project-menu/library-project-menu.component.spec.ts index 5763364c140..eaf95840398 100644 --- a/src/app/modules/library/library-project-menu/library-project-menu.component.spec.ts +++ b/src/app/modules/library/library-project-menu/library-project-menu.component.spec.ts @@ -1,81 +1,30 @@ -import { ComponentFixture, fakeAsync, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { LibraryProjectMenuComponent } from './library-project-menu.component'; import { TeacherService } from '../../../teacher/teacher.service'; import { Project } from '../../../domain/project'; -import { MatDialogModule } from '@angular/material/dialog'; -import { MatMenuModule } from '@angular/material/menu'; import { UserService } from '../../../services/user.service'; import { User } from '../../../domain/user'; -import { Observable } from 'rxjs'; -import { NO_ERRORS_SCHEMA } from '@angular/core'; import { ConfigService } from '../../../services/config.service'; import { ArchiveProjectService } from '../../../services/archive-project.service'; -import { provideHttpClientTesting } from '@angular/common/http/testing'; -import { MatSnackBarModule } from '@angular/material/snack-bar'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { LibraryProjectMenuHarness } from './library-project-menu.harness'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; +import { MockProviders } from 'ng-mocks'; -export class MockUserService { - getUser(): Observable { - const user: User = new User(); - user.firstName = 'Demo'; - user.lastName = 'Teacher'; - user.roles = ['teacher']; - user.username = 'DemoTeacher'; - user.id = 123456; - return Observable.create((observer) => { - observer.next(user); - observer.complete(); - }); - } - getUserId(): number { - return 123456; - } -} - -export class MockTeacherService { - getProjectUsage(projectId: number): Observable { - return Observable.create((observer) => { - observer.next(projectId); - observer.complete(); - }); - } -} - -export class MockConfigService { - getContextPath(): string { - return ''; - } -} - -const archivedTag = { id: 1, text: 'archived', color: null }; let component: LibraryProjectMenuComponent; let fixture: ComponentFixture; let harness: LibraryProjectMenuHarness; - describe('LibraryProjectMenuComponent', () => { - beforeEach( - waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [LibraryProjectMenuComponent], - schemas: [NO_ERRORS_SCHEMA], - imports: [BrowserAnimationsModule, - MatDialogModule, - MatMenuModule, - MatSnackBarModule], - providers: [ - ArchiveProjectService, - { provide: TeacherService, useClass: MockTeacherService }, - { provide: UserService, useClass: MockUserService }, - { provide: ConfigService, useClass: MockConfigService }, - provideHttpClient(withInterceptorsFromDi()), - provideHttpClientTesting() - ] -}).compileComponents(); - }) - ); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [BrowserAnimationsModule, LibraryProjectMenuComponent], + providers: [ + MockProviders(ArchiveProjectService, ConfigService, TeacherService, UserService), + provideHttpClient(withInterceptorsFromDi()) + ] + }).compileComponents(); + })); beforeEach(async () => { fixture = TestBed.createComponent(LibraryProjectMenuComponent); @@ -109,7 +58,7 @@ function showsArchiveButton() { function showsRestoreButton() { describe('project has archived tag', () => { beforeEach(() => { - component.project.tags = [archivedTag]; + component.project.tags = [{ id: 1, text: 'archived', color: null }]; component.ngOnInit(); }); it('shows restore button', async () => { diff --git a/src/app/modules/library/library-project-menu/library-project-menu.component.ts b/src/app/modules/library/library-project-menu/library-project-menu.component.ts index 4fdc8b04d1c..1e485f1d8a5 100644 --- a/src/app/modules/library/library-project-menu/library-project-menu.component.ts +++ b/src/app/modules/library/library-project-menu/library-project-menu.component.ts @@ -7,66 +7,61 @@ import { UserService } from '../../../services/user.service'; import { ConfigService } from '../../../services/config.service'; import { EditRunWarningDialogComponent } from '../../../teacher/edit-run-warning-dialog/edit-run-warning-dialog.component'; import { ArchiveProjectService } from '../../../services/archive-project.service'; +import { CommonModule } from '@angular/common'; +import { MatIconModule } from '@angular/material/icon'; +import { MatButtonModule } from '@angular/material/button'; +import { MatDividerModule } from '@angular/material/divider'; +import { MatMenuModule } from '@angular/material/menu'; @Component({ - selector: 'app-library-project-menu', - styleUrl: './library-project-menu.component.scss', - templateUrl: './library-project-menu.component.html', - standalone: false + imports: [CommonModule, MatButtonModule, MatDividerModule, MatIconModule, MatMenuModule], + selector: 'app-library-project-menu', + styleUrl: './library-project-menu.component.scss', + templateUrl: './library-project-menu.component.html' }) export class LibraryProjectMenuComponent { - @Input() - project: Project; - - @Input() - isRun: boolean; - - protected archived: boolean = false; - editLink: string = ''; - previewLink: string = ''; - isCanEdit: boolean = false; - isCanShare: boolean = false; - isChild: boolean = false; + protected archived: boolean; + protected canEdit: boolean; + protected canShare: boolean; + protected isChild: boolean; + @Input() isRun: boolean; + @Input() project: Project; constructor( private archiveProjectService: ArchiveProjectService, + private configService: ConfigService, private dialog: MatDialog, private teacherService: TeacherService, - private userService: UserService, - private configService: ConfigService + private userService: UserService ) {} - ngOnInit() { - this.isCanEdit = this.isOwner() || this.isSharedOwnerWithEditPermission(); - this.isCanShare = this.isOwner() && !this.isRun; - this.editLink = `${this.configService.getContextPath()}/teacher/edit/unit/${this.project.id}`; + ngOnInit(): void { + this.canEdit = this.isOwner() || this.isSharedOwnerWithEditPermission(); + this.canShare = this.isOwner() && !this.isRun; this.isChild = this.project.isChild(); this.archived = this.project.hasTagWithText('archived'); } - isOwner() { + private isOwner(): boolean { return this.userService.getUserId() == this.project.owner.id; } - isSharedOwnerWithEditPermission() { + private isSharedOwnerWithEditPermission(): boolean { const userId = this.userService.getUserId(); - for (let sharedOwner of this.project.sharedOwners) { - if (userId == sharedOwner.id) { - return this.hasEditPermission(sharedOwner); - } - } - return false; + return this.project.sharedOwners.some( + (owner) => owner.id === userId && this.hasEditPermission(owner) + ); } - hasEditPermission(sharedOwner) { + private hasEditPermission(sharedOwner: any): boolean { return sharedOwner.permissions.includes(Project.EDIT_PERMISSION); } - copyProject() { + protected copyProject(): void { this.teacherService.copyProject(this.project, this.dialog); } - editProject() { + protected editProject(): void { this.teacherService.getProjectLastRun(this.project.id).subscribe((projectRun) => { if (projectRun != null) { projectRun.project = this.project; @@ -75,12 +70,12 @@ export class LibraryProjectMenuComponent { panelClass: 'dialog-sm' }); } else { - window.location.href = this.editLink; + window.location.href = `${this.configService.getContextPath()}/teacher/edit/unit/${this.project.id}`; } }); } - shareProject() { + protected shareProject(): void { this.dialog.open(ShareProjectDialogComponent, { data: { project: this.project }, panelClass: 'dialog-md' diff --git a/src/app/modules/library/library.module.ts b/src/app/modules/library/library.module.ts index 6f0f6d62721..d35f1fc3a5c 100644 --- a/src/app/modules/library/library.module.ts +++ b/src/app/modules/library/library.module.ts @@ -89,6 +89,7 @@ const materialModules = [ FlexLayoutModule, FormsModule, LibraryProjectDisciplinesComponent, + LibraryProjectMenuComponent, ReactiveFormsModule, RouterModule, materialModules, @@ -104,7 +105,6 @@ const materialModules = [ LibraryGroupThumbsComponent, LibraryProjectComponent, LibraryProjectDetailsComponent, - LibraryProjectMenuComponent, LibraryFiltersComponent, HomePageProjectLibraryComponent, TeacherProjectLibraryComponent, diff --git a/src/messages.xlf b/src/messages.xlf index 35cb9b8ebc0..42520ffffb9 100644 --- a/src/messages.xlf +++ b/src/messages.xlf @@ -5676,7 +5676,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/app/modules/library/library-project-menu/library-project-menu.component.html - 11,13 + 11,14 src/assets/wise5/authoringTool/project-authoring/project-authoring.component.html @@ -5934,7 +5934,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.Edit src/app/modules/library/library-project-menu/library-project-menu.component.html - 14,16 + 15,19 src/app/teacher/manage-tags-dialog/manage-tags-dialog.component.html @@ -5961,41 +5961,41 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.Share src/app/modules/library/library-project-menu/library-project-menu.component.html - 17,19 + 20,24 - - Archive + + Restore src/app/modules/library/library-project-menu/library-project-menu.component.html - 21,23 + 26,29 + + + src/app/notebook/notebook-report/notebook-report.component.html + 51,52 src/app/teacher/archive-projects-button/archive-projects-button.component.html - 6,9 + 16,19 src/app/teacher/run-menu/run-menu.component.html - 34,36 + 38,42 - - Restore + + Archive src/app/modules/library/library-project-menu/library-project-menu.component.html - 25,29 - - - src/app/notebook/notebook-report/notebook-report.component.html - 51,52 + 31,36 src/app/teacher/archive-projects-button/archive-projects-button.component.html - 16,19 + 6,9 src/app/teacher/run-menu/run-menu.component.html - 38,42 + 34,36 @@ -17168,7 +17168,7 @@ Are you ready to receive feedback on this answer? src/assets/wise5/directives/summary-display/summary-display.component.ts - 672 + 548 @@ -19359,11 +19359,11 @@ Warning: This will delete all existing choices and buckets in this component. src/assets/wise5/directives/summary-display/summary-display.component.ts - 378 + 293 src/assets/wise5/directives/summary-display/summary-display.component.ts - 480 + 356 @@ -19390,11 +19390,11 @@ Warning: This will delete all existing choices and buckets in this component. src/assets/wise5/directives/summary-display/summary-display.component.ts - 378 + 293 src/assets/wise5/directives/summary-display/summary-display.component.ts - 484 + 360 @@ -21245,56 +21245,56 @@ If this problem continues, let your teacher know and move on to the next activit Your Response src/assets/wise5/directives/summary-display/summary-display.component.ts - 509 + 385 Your Score src/assets/wise5/directives/summary-display/summary-display.component.ts - 511 + 387 Period Responses src/assets/wise5/directives/summary-display/summary-display.component.ts - 518 + 394 Period Scores src/assets/wise5/directives/summary-display/summary-display.component.ts - 523 + 399 Class Responses src/assets/wise5/directives/summary-display/summary-display.component.ts - 532 + 408 Class Scores src/assets/wise5/directives/summary-display/summary-display.component.ts - 537 + 413 % Responded (/) src/assets/wise5/directives/summary-display/summary-display.component.ts - 548 + 424 The student will see a graph of their individual data here. src/assets/wise5/directives/teacher-summary-display/teacher-summary-display.component.ts - 50 + 46