diff --git a/src/app/core/data.service.ts b/src/app/core/data.service.ts index 5a3c476f1503992f3b4af2dc4bccc339079d0909..7bd43d868e4b4b133af9231980d8e55cbcc27fa9 100644 --- a/src/app/core/data.service.ts +++ b/src/app/core/data.service.ts @@ -68,28 +68,28 @@ export class DataService { .pipe(catchError(this.errorHandler)); } - getAllNotes(): Observable<Note[]> { - return this.http.get<Note[]>(this.plannerApiUrl + '/degreePlan/520224/notes') + getAllNotes(planId: number): Observable<Note[]> { + return this.http.get<Note[]>(this.plannerApiUrl + '/degreePlan/' + planId + '/notes') .pipe(catchError(this.errorHandler)); } - getNote(noteId): Observable<Note[]> { - return this.http.get<Note[]>(this.plannerApiUrl + '/degreePlan/520224/notes/' + noteId) + getNote(planId, noteId): Observable<Note[]> { + return this.http.get<Note[]>(this.plannerApiUrl + '/degreePlan/' + planId + '/notes/' + noteId) .pipe(catchError(this.errorHandler)); } - updateNote(note): Observable<Note[]> { - return this.http.put<Note[]>(this.plannerApiUrl + '/degreePlan/520224/notes/' + note.id, note, httpOptions) + updateNote(planId, note): Observable<Note[]> { + return this.http.put<Note[]>(this.plannerApiUrl + '/degreePlan/' + planId + '/notes/' + note.id, note, httpOptions) .pipe(catchError(this.errorHandler)); } - createNote(note): Observable<Note[]> { - return this.http.post<Note[]>(this.plannerApiUrl + '/degreePlan/520224/notes/', note, httpOptions) + createNote(planId, note): Observable<Note[]> { + return this.http.post<Note[]>(this.plannerApiUrl + '/degreePlan/' + planId + '/notes/', note, httpOptions) .pipe(catchError(this.errorHandler)); } - removeNote(noteId): Observable<Note[]> { - return this.http.delete<Note[]>(this.plannerApiUrl + '/degreePlan/520224/notes/' + noteId, httpOptions) + removeNote(planId, noteId): Observable<Note[]> { + return this.http.delete<Note[]>(this.plannerApiUrl + '/degreePlan/' + planId + '/notes/' + noteId, httpOptions) .pipe(catchError(this.errorHandler)); } @@ -103,21 +103,27 @@ export class DataService { .pipe(catchError(this.errorHandler)); } - addCourse(subjectCode, courseId, termCode) { - return this.http.post(this.plannerApiUrl + '/degreePlan/520224/courses', {subjectCode, courseId, termCode }, httpOptions) + addCourse(planId, subjectCode, courseId, termCode) { + return this.http.post(this.plannerApiUrl + '/degreePlan/' + planId + '/courses', {subjectCode, courseId, termCode }, httpOptions) .pipe(catchError(this.errorHandler)); } - removeCourse(recordId) { - return this.http.delete(this.plannerApiUrl + '/degreePlan/520224/courses/' + recordId, httpOptions) + removeCourse(planId, recordId) { + return this.http.delete(this.plannerApiUrl + '/degreePlan/' + planId + '/courses/' + recordId, httpOptions) .pipe(catchError(this.errorHandler)); } - updateCourseTerm(recordId, termCode): Observable<Course> { - return this.http.put<Course>(this.plannerApiUrl + '/degreePlan/520224/courses/' + recordId + '?termCode=' + termCode, httpOptions) + updateCourseTerm(planId, recordId, termCode): Observable<Course> { + return this.http.put<Course>(this.plannerApiUrl + '/degreePlan/' + planId + '/courses/' + recordId + '?termCode=' + termCode, httpOptions) .pipe(catchError(this.errorHandler)); } +test() { +// return this.http.delete(this.plannerApiUrl + '/degreePlan/519260/courses/259445', httpOptions) +return this.http.put(this.plannerApiUrl + '/degreePlan/519260/courses/259465?termCode=1174', httpOptions) + .pipe(catchError(this.errorHandler)); +} + private errorHandler(error: HttpErrorResponse) { return throwError(error || 'Server Error'); } diff --git a/src/app/core/service/degree-planner-data.service.ts b/src/app/core/service/degree-planner-data.service.ts index 87f513d3fdd07d4a0cd077c67c20d1cb3fab8844..12cdb1e1170fbaa4d79c5565f8c8c5b19a9a81fa 100644 --- a/src/app/core/service/degree-planner-data.service.ts +++ b/src/app/core/service/degree-planner-data.service.ts @@ -1,20 +1,25 @@ +import { Course } from '@app/core/models/course'; +import { Note } from './../models/note'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { groupBy, toArray, mergeMap, tap, mergeAll, map } from 'rxjs/operators'; +import { groupBy, toArray, mergeMap, flatMap, tap, mergeAll, map, distinct } from 'rxjs/operators'; import { DataService } from '@app/core/data.service'; - @Injectable({ providedIn: 'root' }) export class DegreePlannerDataService { degreePlannerData: Observable<any>; coursesData$: any; + planId: number; constructor(private dataService: DataService) { } getDegreePlanDataById(planId: number) { + this.planId = planId; + // this.dataService.test().subscribe(() => { }); + this.degreePlannerData = this.dataService.getDegreePlannerCourseData(planId).pipe( map(courses => courses.sort((a, b) => Number(a.termCode) - Number(b.termCode))), mergeAll() @@ -27,7 +32,7 @@ export class DegreePlannerDataService { return { termCode: course[0].termCode, year: course[0].termCode.substring(1, 3), - courses: course.slice(1) + courses: course }; }), groupBy(terms => terms.year), @@ -40,8 +45,12 @@ export class DegreePlannerDataService { return this.coursesData$; } - getDegreePlanData() { - return this.coursesData$; + getAllNotes(): Observable<Note[]> { + return this.dataService.getAllNotes(this.planId); + } + + getPlanId(): number { + return this.planId; } } diff --git a/src/app/degree-planner/degree-planner.component.ts b/src/app/degree-planner/degree-planner.component.ts index 3fbcfa589c17d728899633c52042aa6536f47ef8..32c2d83d411fde0fd1a30112e646be70700fa534 100644 --- a/src/app/degree-planner/degree-planner.component.ts +++ b/src/app/degree-planner/degree-planner.component.ts @@ -22,7 +22,7 @@ export class DegreePlannerComponent { selectedDegreePlan: number; terms: any; termsByAcademicYear: Object; - notes: Observable<Note[]>; + notes$: Observable<Note[]>; firstCurrentTerm: null|string; mobileView: MediaQueryList; favoriteCourses: FavoriteCourse[]; @@ -37,7 +37,8 @@ export class DegreePlannerComponent { this.degreePlans = route.snapshot.data.requiredData.degreePlans; this.selectedDegreePlan = this.degreePlans[0].roadmapId; - this.coursesData$ = degreePlannerDataSvc.getDegreePlanDataById(this.selectedDegreePlan); + this.coursesData$ = this.degreePlannerDataSvc.getDegreePlanDataById(this.selectedDegreePlan); + this.degreePlannerDataSvc.getAllNotes().subscribe(notes => { route.snapshot.data.requiredData.notes = notes; }); // this.coursesData$.subscribe(x => console.log(x)); // this.dataService.getDegreePlans() diff --git a/src/app/degree-planner/degree-planner.resolver.ts b/src/app/degree-planner/degree-planner.resolver.ts index 8135d8a1b54218cbbcdea8f1c6e5cc6877764d79..651a6f8d8e96b170a5c89ec00c34d3da9bb93cdb 100644 --- a/src/app/degree-planner/degree-planner.resolver.ts +++ b/src/app/degree-planner/degree-planner.resolver.ts @@ -16,7 +16,6 @@ export class DegreePlannerResolver implements Resolve<Observable<string>> { this.dataService.getSubjectsMap(), this.dataService.getTerms(), this.dataService.getFavoriteCourses(), - this.dataService.getAllNotes(), this.dataService.getDegreePlans() ).pipe( map((allResponses) => { @@ -24,8 +23,7 @@ export class DegreePlannerResolver implements Resolve<Observable<string>> { subjects: allResponses[0], terms: allResponses[1], favorites: allResponses[2], - notes: allResponses[3], - degreePlans: allResponses[4] + degreePlans: allResponses[3] }; }) ); diff --git a/src/app/degree-planner/dialogs/notes-dialog/notes-dialog.component.ts b/src/app/degree-planner/dialogs/notes-dialog/notes-dialog.component.ts index 422e5ec49b59aaf46f302664467bfd9b2aae1cf0..64d36b18a4590dcd81d164af012c6e7067196f02 100644 --- a/src/app/degree-planner/dialogs/notes-dialog/notes-dialog.component.ts +++ b/src/app/degree-planner/dialogs/notes-dialog/notes-dialog.component.ts @@ -1,3 +1,4 @@ +import { DegreePlannerDataService } from './../../../core/service/degree-planner-data.service'; import { Component, OnInit, Inject } from '@angular/core'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; import { DataService } from '../../../core/data.service'; @@ -16,8 +17,11 @@ export class NotesDialogComponent implements OnInit { termCode: string; noteData: object; - // tslint:disable-next-line:max-line-length - constructor(private dataService: DataService, private fb: FormBuilder, private dialogRef: MatDialogRef<NotesDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: any) { + constructor(private dataService: DataService, + private fb: FormBuilder, + private degreePlannerDataSvc: DegreePlannerDataService, + private dialogRef: MatDialogRef<NotesDialogComponent>, + @Inject(MAT_DIALOG_DATA) public data: any) { this.id = data.id; this.termCode = data.termCode; this.note = data.note; @@ -33,7 +37,7 @@ export class NotesDialogComponent implements OnInit { } removeNote() { - this.dataService.removeNote(this.id).subscribe(() => {}); + this.dataService.removeNote(this.degreePlannerDataSvc.getPlanId(), this.id).subscribe(() => {}); this.dialogRef.close({ event: 'remove' }); } @@ -41,12 +45,12 @@ export class NotesDialogComponent implements OnInit { const note = this.noteForm.value; if (note.id) { - this.dataService.updateNote(note) + this.dataService.updateNote(this.degreePlannerDataSvc.getPlanId(), note) .subscribe(result => { this.dialogRef.close({ event: 'save'}); }); } else { - this.dataService.createNote(note) + this.dataService.createNote(this.degreePlannerDataSvc.getPlanId(), note) .subscribe(result => { this.dialogRef.close({ event: 'save'}); }); diff --git a/src/app/degree-planner/dialogs/remove-course-confirm-dialog/remove-course-confirm-dialog.component.ts b/src/app/degree-planner/dialogs/remove-course-confirm-dialog/remove-course-confirm-dialog.component.ts index 4abb2623716216a3dba634dec53b000de16cbd63..7a1be3a4332999f3534e4917e2f11dca1523f590 100644 --- a/src/app/degree-planner/dialogs/remove-course-confirm-dialog/remove-course-confirm-dialog.component.ts +++ b/src/app/degree-planner/dialogs/remove-course-confirm-dialog/remove-course-confirm-dialog.component.ts @@ -1,3 +1,4 @@ +import { DegreePlannerDataService } from './../../../core/service/degree-planner-data.service'; import { Component, OnInit, Input, Inject } from '@angular/core'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; import { DataService } from '../../../core/data.service'; @@ -16,7 +17,10 @@ export class RemoveCourseConfirmDialogComponent implements OnInit { favoriteCourses: FavoriteCourse[]; // tslint:disable-next-line:max-line-length - constructor(private dataService: DataService, private dialogRef: MatDialogRef<RemoveCourseConfirmDialogComponent>, @Inject(MAT_DIALOG_DATA) data) { + constructor(private dataService: DataService, + private dialogRef: MatDialogRef<RemoveCourseConfirmDialogComponent>, + private degreePlannerDataSvc: DegreePlannerDataService, + @Inject(MAT_DIALOG_DATA) data: any) { this.course = data.course; this.courses = data.courses; this.favoriteCourses = data.favoriteCourses; @@ -41,7 +45,7 @@ export class RemoveCourseConfirmDialogComponent implements OnInit { this.removeCourseFromUI(this.favoriteCourses); }); } else { - this.dataService.removeCourse(this.course.id) + this.dataService.removeCourse(this.degreePlannerDataSvc.getPlanId(), this.course.id) .subscribe(data => { this.removeCourseFromUI(this.courses); }); diff --git a/src/app/degree-planner/favorites-container/favorites-container.component.ts b/src/app/degree-planner/favorites-container/favorites-container.component.ts index 66bb9db1bc314656523f117898a8e4ff6e191d2a..d826e8734adc0e909e991c89d936c98ce56e7cbb 100644 --- a/src/app/degree-planner/favorites-container/favorites-container.component.ts +++ b/src/app/degree-planner/favorites-container/favorites-container.component.ts @@ -3,6 +3,7 @@ import { Component, OnInit, Input } from '@angular/core'; import { DataService } from '../../core/data.service'; import { FavoriteCourse } from '../../core/models/favorite-course'; import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop'; +import { DegreePlannerDataService } from '@app/core/service/degree-planner-data.service'; @Component({ selector: 'cse-favorites-container', @@ -15,7 +16,9 @@ export class FavoritesContainerComponent { @Input() favoriteDropZone: []; favoriteCourses: FavoriteCourse[]; - constructor(private route: ActivatedRoute, private dataService: DataService) { + constructor(private route: ActivatedRoute, + private degreePlannerDataSvc: DegreePlannerDataService, + private dataService: DataService) { this.favoriteCourses = route.snapshot.data.requiredData.favorites; } @@ -33,7 +36,7 @@ export class FavoritesContainerComponent { }); // Remove this course from the degree plan - this.dataService.removeCourse(event.item.data.id) + this.dataService.removeCourse(this.degreePlannerDataSvc.getPlanId(), event.item.data.id) .subscribe(data => { console.log(data); }); diff --git a/src/app/degree-planner/shared/course-item/course-item.component.ts b/src/app/degree-planner/shared/course-item/course-item.component.ts index 2e06d0bd78cd86ea8cb44dda0b5ed0ddcd8829b4..50c381ef58e568f130363b0a8538ca6df791e9b8 100644 --- a/src/app/degree-planner/shared/course-item/course-item.component.ts +++ b/src/app/degree-planner/shared/course-item/course-item.component.ts @@ -1,3 +1,4 @@ +import { DegreePlannerDataService } from './../../../core/service/degree-planner-data.service'; import { ActivatedRoute } from '@angular/router'; import { Component, Input, ChangeDetectorRef, OnInit } from '@angular/core'; import { Course } from '../../../core/models/course'; @@ -35,6 +36,7 @@ export class CourseItemComponent implements OnInit { private dataService: DataService, public dialog: MatDialog, private route: ActivatedRoute, + private degreePlannerDataSvc: DegreePlannerDataService, private cdRef: ChangeDetectorRef) { this.subjects = route.snapshot.data.requiredData.subjects; } @@ -72,7 +74,7 @@ export class CourseItemComponent implements OnInit { }); // Remove this course from term - this.dataService.removeCourse(course.id) + this.dataService.removeCourse(this.degreePlannerDataSvc.getPlanId(), course.id) .subscribe(data => { this.removeCourseFromUI(this.courses); }); @@ -80,7 +82,7 @@ export class CourseItemComponent implements OnInit { // Add Favorite course to term addToTerm(newTermCode) { - this.dataService.addCourse( this.course.subjectCode, this.course.courseId, newTermCode) + this.dataService.addCourse( this.course.subjectCode, this.course.courseId, newTermCode, this.degreePlannerDataSvc.getPlanId) .subscribe( data => { const yearCode = newTermCode.substring(0, 3); const termCode = newTermCode.substring(3); @@ -96,7 +98,7 @@ export class CourseItemComponent implements OnInit { // Move course to another term switchTerm(newTermCode) { - this.dataService.updateCourseTerm(this.course.id, newTermCode) + this.dataService.updateCourseTerm(this.degreePlannerDataSvc.getPlanId, this.course.id, newTermCode) .subscribe( data => { const index = this.courses.indexOf(this.course, 0); if (index > -1) { diff --git a/src/app/degree-planner/term-container/term-container.component.html b/src/app/degree-planner/term-container/term-container.component.html index da9e48d80d92f5198b583b4407bc29bbd89659a7..9de5e2b544648af3de90aeba8a3f84b0c4c60049 100644 --- a/src/app/degree-planner/term-container/term-container.component.html +++ b/src/app/degree-planner/term-container/term-container.component.html @@ -5,8 +5,18 @@ <div fxLayout="row" fxLayoutAlign="end center"> <p class="text-right semi-bold credits">{{ getTotalCredits() }} Cr</p> <button mat-icon-button> - <mat-icon aria-label="Open dialog with notes in this term" class="add-note-icon" (click)="openNotesDialog(false, courses[0].termCode)" matTooltip="Add Note" matTooltipPosition="above">note_add</mat-icon> - <!-- <mat-icon aria-label="Open dialog with notes in this term" class="add-note-icon" (click)="openNotesDialog(false, term.termCode)" matTooltip="Edit Note" matTooltipPosition="above">insert_drive_file</mat-icon> --> + <ng-container *ngIf="termsWithNotes?.indexOf(courses[0].termCode) === -1; then newNote; else editNote"> + </ng-container> + <ng-template #newNote> + <div> + <mat-icon aria-label="Open dialog with notes in this term" class="add-note-icon" (click)="openNotesDialog(false, courses[0].termCode)" matTooltip="Add Note" matTooltipPosition="above">note_add</mat-icon> + </div> + </ng-template> + <ng-template #editNote> + <div> + <mat-icon aria-label="Open dialog with notes in this term" class="add-note-icon" (click)="openNotesDialog(false, courses[0].termCode)" matTooltip="Edit Note" matTooltipPosition="above">insert_drive_file</mat-icon> + </div> + </ng-template> </button> </div> </div> diff --git a/src/app/degree-planner/term-container/term-container.component.ts b/src/app/degree-planner/term-container/term-container.component.ts index 40ee92003205da94848985f25569a59953c546ed..e5602b3e2c9bad745f83c768940d6a40ca37fa37 100644 --- a/src/app/degree-planner/term-container/term-container.component.ts +++ b/src/app/degree-planner/term-container/term-container.component.ts @@ -1,15 +1,14 @@ import { ActivatedRoute } from '@angular/router'; -import { DegreePlannerDataService } from './../../core/service/degree-planner-data.service'; import { Component, Input, ChangeDetectorRef, OnInit } from '@angular/core'; import { CdkDragDrop, transferArrayItem } from '@angular/cdk/drag-drop'; import { MatDialog } from '@angular/material'; -import { Observable } from 'rxjs'; import { DataService } from '../../core/data.service'; +import { DegreePlannerDataService } from './../../core/service/degree-planner-data.service'; +import { SidenavService } from './../../core/service/sidenav.service'; import { CourseDetailsDialogComponent } from '../dialogs/course-details-dialog/course-details-dialog.component'; import { NotesDialogComponent } from '../dialogs/notes-dialog/notes-dialog.component'; import { Note } from '../../core/models/note'; -import { SidenavService } from './../../core/service/sidenav.service'; @Component({ selector: 'cse-term-container', @@ -28,8 +27,8 @@ export class TermContainerComponent implements OnInit { terms: any[]; notes: Note[]; - notes$: Observable<Note[]>; myNote: any; + termsWithNotes: any[]; noteLookup: Object; constructor( @@ -39,22 +38,25 @@ export class TermContainerComponent implements OnInit { public dialog: MatDialog, private sidenavService: SidenavService, private cdRef: ChangeDetectorRef) { - } + this.notes = route.snapshot.data.requiredData.notes; + } ngOnInit() { - this.notes = this.route.snapshot.data.requiredData.notes; + this.termsWithNotes = this.notes.map(note => note.termCode); } openAddSidenav() { this.sidenavService.open(); } + openNotesDialog(note, termCode) { let dialogRef; if (!note) { this.myNote = this.notes.filter(singleNote => (singleNote.termCode === termCode))[0]; + if (this.myNote) { dialogRef = this.dialog.open(NotesDialogComponent, { - data: { note: this.myNote.note, termCode: this.myNote.termCode } + data: { note: this.myNote.note, termCode: this.myNote.termCode, id: this.myNote.id } }); } else { dialogRef = this.dialog.open(NotesDialogComponent, { data: { termCode: termCode } }); @@ -63,14 +65,14 @@ export class TermContainerComponent implements OnInit { dialogRef = this.dialog.open(NotesDialogComponent, { data: note }); } dialogRef.afterClosed().subscribe(result => { - if (result.event === 'save') { - this.dataService.getAllNotes().subscribe(notes => this.notes = notes); - } else if (result.event === 'remove') { - this.notes.forEach((singleNote, i) => { - if (singleNote.termCode === termCode) { - this.notes.splice(i, 1); - } - }); + if (result) { + if (result.event === 'save') { + this.termsWithNotes.push(termCode); + this.degreePlannerDataSvc.getAllNotes().subscribe(notes => this.notes = notes); + } else if (result.event === 'remove') { + this.termsWithNotes = this.termsWithNotes.filter(n => n !== termCode); + this.notes = this.notes.filter(n => n.termCode !== termCode); + } } }); } @@ -106,7 +108,7 @@ export class TermContainerComponent implements OnInit { if (event.previousContainer.id === 'favoriteCourse-dropZone' && event.container.id !== 'favoriteCourse-dropZone') { // If moving from favorites to term - this.dataService.addCourse(event.item.data.subjectCode, event.item.data.courseId, newTermCode) + this.dataService.addCourse(event.item.data.subjectCode, event.item.data.courseId, newTermCode, this.degreePlannerDataSvc.getPlanId()) .subscribe(data => { const yearCode = newTermCode.substring(0, 3); const termCode = newTermCode.substring(3); @@ -131,7 +133,7 @@ export class TermContainerComponent implements OnInit { event.currentIndex); // Tell the API this course updated - this.dataService.updateCourseTerm(event.item.data.id, newTermCode) + this.dataService.updateCourseTerm(this.degreePlannerDataSvc.getPlanId(), event.item.data.id, newTermCode) .subscribe( data => { // TODO Handle errors });