Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Course addition functionality, new YacsStagingService option #176

Merged
merged 4 commits into from
Apr 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 1 addition & 3 deletions yacs-admin-angular/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@ import { DepartmentListComponent } from './department/department-list/department
import { DepartmentDetailComponent } from './department/department-detail/department-detail.component';
import { CourseListComponent } from './course/course-list/course-list.component';
import { SectionListComponent } from './section/section-list/section-list.component';
import { FakeYacsService } from './services/fake-yacs.service';
import {YacsService} from './services/yacs.service';
//YACS API uses older http module
import { HttpInMemoryWebApiModule, HttpClientInMemoryWebApiModule } from 'angular-in-memory-web-api';
import { InMemoryDataService } from './services/in-memory-data.service';
import { HttpModule, XHRBackend } from '@angular/http';
import { HttpClientModule } from '@angular/common/http';
import { SchoolDetailComponent } from './school/school-detail/school-detail.component';
import {YacsProdService} from './services/yacs-prod.service';
import {environment} from '../environments/environment';
import { CourseDetailComponent } from './course/course-detail/course-detail.component';

Expand Down Expand Up @@ -47,7 +45,7 @@ import { CourseDetailComponent } from './course/course-detail/course-detail.comp
* If we are in production, use YacsProdService,
* otherwise use FakeYacsService */
{provide: YacsService,
useClass: environment.useRealData ? YacsProdService : FakeYacsService}],
useClass: environment.yacsService}],
bootstrap: [AppComponent]
})
export class AppModule { }
Original file line number Diff line number Diff line change
@@ -1,8 +1,66 @@
<div *ngIf="!error">
<div id="newCourse" *ngIf="creatingCourse">
<h3>New Course</h3>
<div class="form-row justify-content-start">
<div id="deptField" class="form-group form-inline ">
<label>Department: </label>
<select class="form-control" id="depts-dropdown" #newCode>
<option *ngFor="let dept of departments" ngValue="dept.id">{{dept.code}}</option>
</select>
&nbsp;
<label for="numInput">Course #: </label>
<input id="numInput" class="form-control" placeholder="Course number" #newNum>
</div>

</div>
<div class="form-row">
<div id="nameField" class="form-group form-inline">
<label for="nameInput">Name: </label>
<input id="nameInput" class="form-control" style ="width:95% !important;" placeholder="Name" #newName>
</div>
</div>
<div class="form-row">
<div id="credField" class="form-group form-inline">
<label for="minCredInput">Min Credits: </label>
<input id="minCredInput" class="form-control" style="width: 70px !important" #newMinCred>
&nbsp;
<label for="maxCredInput">Max Credits: </label>
<input id="maxCredInput" class="form-control" style="width: 70px !important" #newMaxCred>

</div>


</div>
<div class="form-row">
<div id="descField" class="form-group form-inline">
<label for="descInput">Description: &nbsp;</label>
<textarea id="descInput" class="form-control" style="width: 90% !important" rows="5" #newDesc></textarea>
</div>
</div>
<div id="buttonHolder">
<button class="btn btn-search" (click)="createCourse(newCode.value, newName.value, newNum.value, newMinCred.value, newMaxCred.value, newDesc.value)" id="createBtn">Create Course</button>
<button class="btn btn-search" (click)="cancelNewCourse()" id="cancelBtn">Cancel</button>
</div>
<!--

<div id = "codeField" class="form-group form-inline">
<label for = "codeInput">Code: &nbsp;</label>
<input id ="codeInput" class="form-control" style="width:100px !important;" placeholder="CODE" #newCode/>
</div>




-->

</div>

<!-- Get department id param-->
<h2 *ngIf="!selectedDept">All Courses</h2>
<h2 *ngIf="selectedDept">Courses in the {{selectedDept.name}} Department</h2>
<div class="row">
<div class="col-xs-6">
<h2 *ngIf="!selectedDept">All Courses</h2>
<h2 *ngIf="selectedDept">Courses in the {{selectedDept.name}} Department</h2></div>
<div class="col-xs-6 new-object-link" ><h3><a (click) = "showCourseForm()"id="newCourseBtn"><i class="fa fa-plus" aria-hidden="true"></i> New Course</a></h3></div></div>
<table class="table" *ngIf ="courses">
<thead>
<tr>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,90 @@ describe('no query parameters', () => {
it('should display the table',() => {
expect(document.getElementsByClassName('table')).toBeTruthy();
});

it('should not display the form', () => {
expect(document.getElementById('newCourse')).toBeNull();
});

it('should display \'New Course\'',() => {
expect(document.getElementsByClassName('new-object-link')[0]).toBeTruthy();
});
describe('after clicking \'New Course\'', () => {
beforeEach(async()=>{
const newBtn=document.getElementById('newCourseBtn');
newBtn.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
});

});

beforeEach(()=>{
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
});
});

it('should set creatingCourse to true', async() => {
tick();
expect(component.creatingCourse).toEqual(true);
});
it('should render the form', async() => {
tick();
expect(document.getElementById('newCourse')).toBeTruthy();
//expect(component.selectedDept).toEqual(expectedDept);
});

describe('when \'Cancel\' is pressed', () => {
beforeEach(async()=>{
const cancelBtn=document.getElementById('cancelBtn');
cancelBtn.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
});
});

beforeEach(()=>{
spyOn(component, 'cancelNewCourse').and.callThrough();
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
});
});

/*This spec is pending until we can replace
* this dialog with a Bootstrap modal.*/

xit('displays the dialog', async()=>{
tick();
expect(component.cancelNewCourse).toHaveBeenCalled();
});

});


describe('When \'Create Course\' is pressed', () => {
beforeEach(async()=>{
const createBtn=document.getElementById('createBtn');
createBtn.click();
});

beforeEach(()=>{
spyOn(component,'createCourse');
});

it('should call createDept', async()=>{
tick();
expect(component.createCourse).toHaveBeenCalled();
});
});

});


});
describe('invalid department id is passed', () => {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export class CourseListComponent implements OnInit {
error: boolean;
courses: Course[];
selectedDept: Department;
creatingCourse: boolean;
departments: Department[];
//ActivatedRoute is used to access parameters
constructor(private route: ActivatedRoute, private yacsService: YacsService) {}
Expand Down Expand Up @@ -99,10 +100,52 @@ export class CourseListComponent implements OnInit {
});


}
showCourseForm(): void{
this.creatingCourse=true;
}
cancelNewCourse(): void{
if(confirm('Are you sure you want to cancel?')){
this.creatingCourse=false;
}
}
createCourse(code, name, num, min_cred, max_cred, desc): void{
console.log(code);
let newCourse: Course;
console.log(this.courses.length);
//Get school id
let dept: Department;
dept = this.departments.filter(department => department.code == code)[0];
console.log(dept);
let dept_id=dept.id;
let dept_code = dept.code;
newCourse = new Course((this.courses.length +1), name, num, dept_code, dept_id, min_cred, max_cred, desc, []);
this.yacsService.addCourse(newCourse)
.subscribe( ()=>{
//Get departments with new dept
if(this.department_id){
this.getCoursesInDept(this.department_id);
}
else{
this.getAllCourses();
}
this.creatingCourse=false;
}
);
/*this.yacsService.getDeptByID(String(code))
.subscribe(dept=>{
console.log(dept);


});*/


}

ngOnInit() {

this.creatingCourse=false;

this.getAllDepts();
//Filter the courses if department id is not null
this.setDeptId();
Expand Down
17 changes: 17 additions & 0 deletions yacs-admin-angular/src/app/services/fake-yacs.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,29 @@ export class FakeYacsService implements YacsService{
//return of(COURSES.filter(course => course.department_id === dept_id));

}

addCourse(course: Course): Observable<any>{
console.log(course);
return this.http.post(this.coursesUrl, course, cudOptions).pipe(
tap(_=>console.log(course)),
catchError(this.handleError<any>('addCourse'))
);
}

updateCourse(course: Course): Observable<any>{
return this.http.put(this.coursesUrl, course, cudOptions).pipe(
tap(_=>console.log(course),
catchError(this.handleError<any>('updateCourse')))
);
}
getDeptByCode(code: string): Observable<Department>{
return this.http.get<Department[]>(this.deptsUrl)
.map(depts=>{
let results=depts.filter(dept=> dept.code == code);
return results;
})[0];
}


getDeptsBySchoolID(school_id: number): Observable<Department[]>{
return this.http.get<Department[]>(this.deptsUrl)
Expand Down
26 changes: 20 additions & 6 deletions yacs-admin-angular/src/app/services/yacs-prod.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import { of } from 'rxjs/observable/of';
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
import { catchError, map, tap} from 'rxjs/operators';
import 'rxjs/add/operator/map';
const cudOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json' })};

const cudOptions = { headers: new HttpHeaders({ 'Content-Type': 'x-www-form-urlencoded' }), withCredentials: true};
@Injectable()
export class YacsProdService implements YacsService{
baseUrl='https://yacs.cs.rpi.edu/api/v5';
Expand Down Expand Up @@ -49,7 +48,7 @@ export class YacsProdService implements YacsService{

updateSchool(school: School): Observable<any>{
//TODO: implement admin token
return this.http.put(this.baseUrl+'/schools', school, cudOptions).pipe(
return this.http.put(this.baseUrl+`/schools/${school.id}`, school, cudOptions).pipe(
//TODO: send to an actual logging system instead of console.log
tap(_=>console.log(school)),
catchError(this.handleError<any>('updateSchool'))
Expand Down Expand Up @@ -88,7 +87,15 @@ export class YacsProdService implements YacsService{
return((results.length==1) ? results[0] : null);
});
}

getDeptByCode(code: string): Observable<Department>{
return this.http.get<Department[]>(this.baseUrl+'/departments', {
params: new HttpParams().set('code', code)
})
.map(depts=>{
let results = depts['departments'].filter(dept => dept.code == code);
return((results.length==1) ? results[0] : null);
});
}
getDeptsBySchoolID(school_id: number): Observable<Department[]>{
return this.http.get<Department[]>(this.baseUrl+'/departments', {
params: new HttpParams().set('school_id', String(school_id))
Expand All @@ -97,7 +104,7 @@ export class YacsProdService implements YacsService{
}

updateDepartment(dept: Department): Observable<any>{
return this.http.put(this.baseUrl+'/departments', dept, cudOptions).pipe(
return this.http.put(this.baseUrl+`/departments/${dept.id}`, dept, cudOptions).pipe(
tap(_=> console.log(dept)),
catchError(this.handleError<any>('updateDepartment'))
);
Expand Down Expand Up @@ -134,6 +141,13 @@ export class YacsProdService implements YacsService{
});

}
addCourse(course: Course): Observable<any>{
return this.http.post(this.baseUrl+'/courses', course, cudOptions).pipe(
tap(_=> console.log(course)),
catchError(this.handleError<any>('addCourse'))
);
}



deleteCourse(course: Course | number): Observable<Course>{
Expand All @@ -146,7 +160,7 @@ export class YacsProdService implements YacsService{
}

updateCourse(course: Course): Observable<any>{
return this.http.put(this.baseUrl+'/courses', course, cudOptions).pipe(
return this.http.put(this.baseUrl+`/courses/${course.id}`, course, cudOptions).pipe(
tap(_=> console.log(course)),
catchError(this.handleError<any>('updateCourse'))
);
Expand Down
7 changes: 7 additions & 0 deletions yacs-admin-angular/src/app/services/yacs-staging.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {Injectable} from '@angular/core';
import {YacsProdService} from './yacs-prod.service';

@Injectable()
export class YacsStagingService extends YacsProdService{
baseUrl='https://127.0.0.1/api/v5';
}
3 changes: 2 additions & 1 deletion yacs-admin-angular/src/app/services/yacs.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export abstract class YacsService {
/* HTTP GET method
* Return a singular department by ID */
abstract getDeptByID(id: number): Observable<Department>;

abstract getDeptByCode(code: string): Observable<Department>;
//HTTP GET method
//Return all departments in a school
abstract getDeptsBySchoolID(school_id: number): Observable<Department[]>;
Expand All @@ -54,6 +54,7 @@ export abstract class YacsService {

abstract getCourses(): Observable<Course[]>;
abstract getCoursesByDeptID(dept_id: number): Observable<Course[]>;
abstract addCourse(course: Course): Observable<any>;
//PUT method for courses
abstract updateCourse(course: Course): Observable<any>;
abstract deleteCourse(course: Course | number): Observable<Course>;
Expand Down
5 changes: 4 additions & 1 deletion yacs-admin-angular/src/environments/environment.prod.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { YacsProdService } from '../app/services/yacs-prod.service';

export const environment = {
production: true,
useRealData: true
yacsService: YacsProdService,
useRealData: true,
};
5 changes: 4 additions & 1 deletion yacs-admin-angular/src/environments/environment.staging.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { YacsStagingService } from '../app/services/yacs-staging.service';

export const environment = {
production: false,
useRealData: true
yacsService: YacsStagingService,
useRealData: true,
};
5 changes: 4 additions & 1 deletion yacs-admin-angular/src/environments/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
// `ng build --env=prod` then `environment.prod.ts` will be used instead.
// The list of which env maps to which file can be found in `.angular-cli.json`.

import { FakeYacsService } from '../app/services/fake-yacs.service';

export const environment = {
production: false,
useRealData: false
yacsService: FakeYacsService,
useRealData: false,
};