Skip to content

Commit

Permalink
refactor(Archive): Make archive unit menu items use archive service (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
geoffreykwan authored Mar 12, 2024
1 parent 4f4d2b6 commit 5bfd1fb
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 208 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ 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 { ArchiveProjectResponse } from '../../../domain/archiveProjectResponse';

@Component({
selector: 'app-library-project-menu',
Expand Down Expand Up @@ -88,16 +87,6 @@ export class LibraryProjectMenuComponent {
}

protected archive(archive: boolean): void {
this.archiveProjectService[archive ? 'archiveProject' : 'unarchiveProject'](
this.project
).subscribe({
next: (response: ArchiveProjectResponse) => {
this.archiveProjectService.updateProjectArchivedStatus(this.project, response.archived);
this.archiveProjectService.showArchiveProjectSuccessMessage(this.project, archive);
},
error: () => {
this.archiveProjectService.showArchiveProjectErrorMessage(archive);
}
});
this.archiveProjectService.archiveProject(this.project, archive);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,6 @@ export class PersonalLibraryComponent extends LibraryComponent {
}
}

protected refreshProjects(): void {
this.unselectAllProjects();
this.archiveProjectService.refreshProjects();
}

protected unselectAllProjects(): void {
this.projects.forEach((project) => (project.selected = false));
this.selectedProjects.set([]);
Expand Down
113 changes: 48 additions & 65 deletions src/app/services/archive-project.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,83 +12,47 @@ export class ArchiveProjectService {

constructor(private http: HttpClient, private snackBar: MatSnackBar) {}

archiveProject(project: Project): Observable<ArchiveProjectResponse> {
return this.http.put<ArchiveProjectResponse>(`/api/project/${project.id}/archived`, null);
}

private makeArchiveProjectsRequest(projects: Project[]): Observable<ArchiveProjectResponse[]> {
const projectIds = projects.map((project) => project.id);
return this.http.put<ArchiveProjectResponse[]>(`/api/projects/archived`, projectIds);
}

unarchiveProject(project: Project): Observable<ArchiveProjectResponse> {
return this.http.delete<ArchiveProjectResponse>(`/api/project/${project.id}/archived`);
}

private makeUnarchiveProjectsRequest(projects: Project[]): Observable<ArchiveProjectResponse[]> {
let params = new HttpParams();
for (const project of projects) {
params = params.append('projectIds', project.id);
}
return this.http.delete<ArchiveProjectResponse[]>(`/api/projects/archived`, {
params: params
});
}

refreshProjects(): void {
this.refreshProjectsEventSource.next();
}

showArchiveProjectSuccessMessage(project: Project, archive: boolean): void {
this.snackBar
.open($localize`Successfully ${archive ? 'archived' : 'restored'} unit.`, $localize`Undo`)
.onAction()
.subscribe(() => {
this.undoArchiveProjectAction(project, archive ? 'unarchiveProject' : 'archiveProject');
});
}

undoArchiveProjectAction(project: Project, archiveFunctionName: string): void {
this[archiveFunctionName](project).subscribe({
archiveProject(project: Project, archive: boolean): void {
this[archive ? 'makeArchiveProjectRequest' : 'makeUnarchiveProjectRequest'](project).subscribe({
next: (response: ArchiveProjectResponse) => {
this.updateProjectArchivedStatus(project, response.archived);
this.snackBar.open($localize`Action undone.`);
this.showArchiveProjectSuccessMessage(project, archive);
},
error: () => {
this.snackBar.open($localize`Error undoing action.`);
this.showArchiveProjectErrorMessage(archive);
}
});
}

updateProjectArchivedStatus(project: Project, archived: boolean): void {
private makeArchiveProjectRequest(project: Project): Observable<ArchiveProjectResponse> {
return this.http.put<ArchiveProjectResponse>(`/api/project/${project.id}/archived`, null);
}

private makeUnarchiveProjectRequest(project: Project): Observable<ArchiveProjectResponse> {
return this.http.delete<ArchiveProjectResponse>(`/api/project/${project.id}/archived`);
}

private updateProjectArchivedStatus(project: Project, archived: boolean): void {
project.updateArchivedStatus(archived);
this.refreshProjects();
}

showArchiveProjectsSuccessMessage(projects: Project[], archived: boolean): void {
private showArchiveProjectSuccessMessage(project: Project, archive: boolean): void {
this.snackBar
.open(
archived
? $localize`Successfully archived ${projects.length} unit(s).`
: $localize`Successfully restored ${projects.length} unit(s).`,
$localize`Undo`
)
.open($localize`Successfully ${archive ? 'archived' : 'restored'} unit.`, $localize`Undo`)
.onAction()
.subscribe(() => {
this.undoArchiveProjects(
projects,
archived ? 'makeUnarchiveProjectsRequest' : 'makeArchiveProjectsRequest'
this.undoArchiveProjectAction(
project,
archive ? 'makeUnarchiveProjectRequest' : 'makeArchiveProjectRequest'
);
});
}

undoArchiveProjects(projects: Project[], archiveFunctionName: string): void {
this[archiveFunctionName](projects).subscribe({
next: (response: ArchiveProjectResponse[]) => {
for (const projectResponse of response) {
const project = projects.find((project) => project.id === projectResponse.id);
this.updateProjectArchivedStatus(project, projectResponse.archived);
}
private undoArchiveProjectAction(project: Project, archiveFunctionName: string): void {
this[archiveFunctionName](project).subscribe({
next: (response: ArchiveProjectResponse) => {
this.updateProjectArchivedStatus(project, response.archived);
this.snackBar.open($localize`Action undone.`);
},
error: () => {
Expand All @@ -97,7 +61,7 @@ export class ArchiveProjectService {
});
}

showArchiveProjectErrorMessage(archive: boolean): void {
private showArchiveProjectErrorMessage(archive: boolean): void {
this.snackBar.open(
archive ? $localize`Error archiving unit.` : $localize`Error restoring unit.`
);
Expand All @@ -117,6 +81,21 @@ export class ArchiveProjectService {
});
}

private makeArchiveProjectsRequest(projects: Project[]): Observable<ArchiveProjectResponse[]> {
const projectIds = projects.map((project) => project.id);
return this.http.put<ArchiveProjectResponse[]>(`/api/projects/archived`, projectIds);
}

private makeUnarchiveProjectsRequest(projects: Project[]): Observable<ArchiveProjectResponse[]> {
let params = new HttpParams();
for (const project of projects) {
params = params.append('projectIds', project.id);
}
return this.http.delete<ArchiveProjectResponse[]>(`/api/projects/archived`, {
params: params
});
}

private updateProjectsArchivedStatus(
projects: Project[],
archiveProjectsResponse: ArchiveProjectResponse[]
Expand Down Expand Up @@ -152,12 +131,6 @@ export class ArchiveProjectService {
});
}

private showErrorSnackBar(archive: boolean): void {
this.snackBar.open(
archive ? $localize`Error archiving unit(s).` : $localize`Error restoring unit(s).`
);
}

private undoArchiveAction(projects: Project[], archiveFunctionName: string): void {
this[archiveFunctionName](projects).subscribe({
next: (archiveProjectsResponse: ArchiveProjectResponse[]) => {
Expand All @@ -170,4 +143,14 @@ export class ArchiveProjectService {
}
});
}

private showErrorSnackBar(archive: boolean): void {
this.snackBar.open(
archive ? $localize`Error archiving unit(s).` : $localize`Error restoring unit(s).`
);
}

private refreshProjects(): void {
this.refreshProjectsEventSource.next();
}
}
3 changes: 2 additions & 1 deletion src/app/teacher/run-menu/run-menu.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ function setRun(archived: boolean): void {
archived: archived,
id: 1,
owner: owner,
sharedOwners: []
sharedOwners: [],
tags: []
}
});
}
Expand Down
56 changes: 2 additions & 54 deletions src/app/teacher/run-menu/run-menu.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ import { ConfigService } from '../../services/config.service';
import { RunSettingsDialogComponent } from '../run-settings-dialog/run-settings-dialog.component';
import { EditRunWarningDialogComponent } from '../edit-run-warning-dialog/edit-run-warning-dialog.component';
import { Router } from '@angular/router';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ArchiveProjectService } from '../../services/archive-project.service';
import { ArchiveProjectResponse } from '../../domain/archiveProjectResponse';

@Component({
selector: 'app-run-menu',
Expand All @@ -28,8 +26,7 @@ export class RunMenuComponent implements OnInit {
private dialog: MatDialog,
private userService: UserService,
private configService: ConfigService,
private router: Router,
private snackBar: MatSnackBar
private router: Router
) {}

ngOnInit() {
Expand Down Expand Up @@ -85,55 +82,6 @@ export class RunMenuComponent implements OnInit {
}

protected archive(archive: boolean): void {
this.archiveProjectService[archive ? 'archiveProject' : 'unarchiveProject'](
this.run.project
).subscribe({
next: (response: ArchiveProjectResponse) => {
this.updateArchivedStatus(this.run, response.archived);
this.showSuccessMessage(this.run, archive);
},
error: () => {
this.showErrorMessage(archive);
}
});
}

private showSuccessMessage(run: TeacherRun, archive: boolean): void {
this.openSnackBar(
run,
$localize`Successfully ${archive ? 'archived' : 'restored'} unit.`,
archive ? 'unarchiveProject' : 'archiveProject'
);
}

private showErrorMessage(archive: boolean): void {
this.snackBar.open($localize`Error ${archive ? 'archiving' : 'unarchiving'} unit.`);
}

private updateArchivedStatus(run: TeacherRun, archived: boolean): void {
run.project.archived = archived;
this.runArchiveStatusChangedEvent.emit();
}

private openSnackBar(run: TeacherRun, message: string, undoFunctionName: string): void {
this.snackBar
.open(message, $localize`Undo`)
.onAction()
.subscribe(() => {
this.undoArchiveAction(run, undoFunctionName);
});
}

private undoArchiveAction(run: TeacherRun, archiveFunctionName: string): void {
this.archiveProjectService[archiveFunctionName](run.project).subscribe({
next: (response: ArchiveProjectResponse) => {
run.project.archived = response.archived;
this.archiveProjectService.refreshProjects();
this.snackBar.open($localize`Action undone.`);
},
error: () => {
this.snackBar.open($localize`Error undoing action.`);
}
});
this.archiveProjectService.archiveProject(this.run.project, archive);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,10 @@ function render() {
function runArchiveStatusChanged() {
describe('run is not archived and archive menu button is clicked', () => {
it('should archive run and emit events', async () => {
const runSelectedSpy = spyOn(component.runSelectedStatusChangedEvent, 'emit');
const runArchiveSpy = spyOn(component.runArchiveStatusChangedEvent, 'emit');
expect(await runListItemHarness.isArchived()).toBeFalse();
spyOn(http, 'put').and.returnValue(of(new ArchiveProjectResponse(1, true)));
await runListItemHarness.clickArchiveMenuButton();
expect(await runListItemHarness.isArchived()).toBeTrue();
expect(runSelectedSpy).toHaveBeenCalled();
expect(runArchiveSpy).toHaveBeenCalled();
});
});
}
Loading

0 comments on commit 5bfd1fb

Please sign in to comment.