Skip to content

Commit ea68715

Browse files
committed
Got Lab Adding to Work
1 parent af38149 commit ea68715

File tree

11 files changed

+156
-85
lines changed

11 files changed

+156
-85
lines changed

both/collections/course.collection.ts

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77

88
import { CourseSchema } from '../schemas/course.schema';
99
import { Course } from '../models/course.model';
10-
import { Role } from '../models/user.model';
11-
import { Lab } from '../models/lab.model';
1210

11+
import { Role } from '../models/user.model';
1312
import { Users } from '../collections/user.collection';
13+
14+
import { Lab, LabFileImportOpts } from '../models/lab.model';
1415
import { Labs } from '../collections/lab.collection';
1516

1617
// Array of Fields that can be Updated
@@ -50,41 +51,14 @@
5051
});
5152
}
5253

53-
public addInstructor(course_id : string, user_id : string){
54-
super.update({ _id: course_id }, { '$addToSet' : { instructors : user_id}});
55-
}
56-
57-
public removeInstructor(course_id : string, user_id : string){
58-
super.update({ _id: course_id }, { '$pull' : { instructors : user_id}});
59-
}
60-
61-
public addLab(course_id : string, lab_id : string){
62-
super.update({ _id: course_id }, { '$addToSet' : { labs : lab_id }});
63-
}
64-
65-
public removeLab(course_id : string, lab_id : string){
66-
super.update({ _id: course_id }, { '$pull' : { instructors : lab_id}});
67-
}
68-
6954
public getLabs(course_id : string){
7055
var course;
71-
7256
if(typeof (course = super.findOne({ _id: course_id })) !== "undefined"){
7357
return Labs.observable.find({ _id : { '$in' : course.labs }});
7458
}
7559
}
7660

77-
public reorderLabs(course_id : string, labs : string[]) : Promise<any>{
78-
return new Promise((resolve, reject) => {
79-
super.rawCollection().findAndModify({ _id : course_id, labs : { $all : labs }},{},{ $set : { labs : labs } }, (err, res) => {
80-
if(err){
81-
reject(err);
82-
} else {
83-
resolve();
84-
}
85-
});
86-
})
87-
}
61+
8862

8963
}
9064
export const Courses = new CourseCollection();

both/collections/course_record.collection.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/**
22
IMPORTS
33
**/
4+
import * as _ from 'lodash';
45
import { Mongo } from 'meteor/mongo';
56
import { MongoObservable } from 'meteor-rxjs';
67

@@ -24,16 +25,12 @@
2425
// Create Observable
2526
this.observable = new MongoObservable.Collection(this);
2627

27-
// Set Editing Permissions
28+
// Permissions
29+
const allowed_fields = [];
2830
super.allow({
29-
insert: function(user_id, course) {
30-
return Users.getRoleFor(user_id, course._id) >= Role.instructor;
31-
},
32-
update: function(user_id, course, fields) {
33-
return Users.getRoleFor(user_id, course._id) >= Role.instructor;
34-
},
35-
remove: function(user_id, course) {
36-
return Users.getRoleFor(user_id, course._id) >= Role.instructor;
31+
update: function(user_id, course_record : CourseRecord, fields) {
32+
return _.intersection(fields, allowed_fields).length === 0 &&
33+
Users.getRoleFor(user_id, course_record.course_id) >= Role.instructor;
3734
},
3835
fetch: []
3936
});

both/collections/lab.collection.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
/**
33
IMPORTS
44
**/
5+
import * as _ from 'lodash';
56
import { Meteor } from 'meteor/meteor';
67
import { Mongo } from 'meteor/mongo'
78
import { MongoObservable } from 'meteor-rxjs';
@@ -24,15 +25,13 @@
2425
// Create Observable
2526
this.observable = new MongoObservable.Collection(this);
2627

27-
// Set Editing Permissions
28-
let isAuthorized = function(user_id : string, lab : Lab){
29-
return Users.getRoleFor(lab.course_id, user_id) >= Role.course_admin;
30-
}
31-
28+
// Permissions
29+
const allowed_fields = ['name', 'description', 'status'];
3230
super.allow({
33-
insert: isAuthorized,
34-
update: isAuthorized,
35-
remove: isAuthorized,
31+
update: (user_id : string, lab : Lab, fields : string[]) => {
32+
return _.intersection(fields, allowed_fields).length === 0 &&
33+
Users.getRoleFor(user_id, lab.course_id) >= Role.instructor;
34+
},
3635
fetch: ["course_id"]
3736
});
3837
}

both/models/lab.model.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@
1717
md: string;
1818
}
1919

20+
/* LAB FILE IMPORT OPTS */
21+
export interface LabFileImportOpts{
22+
_id?: string;
23+
course_id: string;
24+
file: string;
25+
}
26+
2027
/* LAB MODEL */
2128
export interface Lab {
2229
_id?: string;

client/imports/course/course_view.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ <h2> Labs </h2>
3737
<!-- Add Lab -->
3838
<section class="add_lab">
3939
<div fxLayout="row" fxLayoutAlign="center center" class="file_drop"
40-
(drop)="onDrop($event)" (dragover)="onDragOver($event)" (dragenter)="dragActive = true" (dragleave)="dragActive = false" (dragend)="dragActive = false"
40+
(drop)="onDrop($event)" (dragover)="onDragOver($event)" (dragenter)="dragActive = true" (dragleave)="dragActive = false"
4141
[class.active]="dragActive">
4242

4343
<md-icon>file_upload</md-icon>

client/imports/course/course_view.component.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -100,18 +100,8 @@
100100

101101
this.labs = this.course
102102
.mergeMap((course) => {
103-
return Observable.fromPromise(
104-
new Promise((resolve, reject) => {
105-
Meteor.subscribe('labs.course', course._id, () => {
106-
var labs = Labs.find({ course_id : course._id });
107-
if(_.isNull(labs)){
108-
reject("Course Record Not Found");
109-
} else {
110-
resolve(labs.fetch());
111-
}
112-
});
113-
})
114-
);
103+
Meteor.subscribe('labs.course', course._id);
104+
return Labs.observable.find({ course_id : course._id });
115105
});
116106
}
117107

@@ -134,13 +124,25 @@
134124
private dragActive = false;
135125
@HostListener('drop', ['$event'])
136126
onDrop(event) {
127+
event.stopPropagation();
137128
event.preventDefault();
138129
this.dragActive = false;
139130

140131
// Get File
141-
var fileReader = new FileReader();
142-
_.each(event.dataTransfer.files, (file) => {
143-
var lab_file = fileReader.readAsText(file);
132+
_.each(event.dataTransfer.files, (fileTarget) => {
133+
var fileReader = new FileReader();
134+
fileReader.onload = (fileEvent) => {
135+
var lab_file = ((<any>fileEvent.target).result);
136+
Meteor.call('Courses.createLab',{ course_id : this.route.snapshot.params['course_id'], lab_file : lab_file }, (err, res) => {
137+
if(err){
138+
console.error("COULD NOT UPLOAD LAB");
139+
console.error(err);
140+
} else {
141+
142+
}
143+
})
144+
}
145+
fileReader.readAsText(fileTarget,"UTF-8");
144146
});
145147
}
146148

client/imports/course/course_view_lab.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,11 @@
9191
}
9292

9393
private delete(){
94-
Labs.remove(this.lab._id, (err, res) => {
94+
Meteor.call('Courses.removeLab', this.lab._id, this.lab.course_id, (err, res) => {
9595
if(err){
9696
console.error(err);
9797
}
98-
});
98+
})
9999
}
100100

101101
}

imports/fixtures/index.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@
1414

1515
import { Course, ContentPermissions, EnrollPermissions } from '../../both/models/course.model';
1616
import { Courses } from '../../both/collections/course.collection';
17+
import { createLab } from '../../server/methods/course.methods';
1718

1819
import { Lab, LabStatus } from '../../both/models/lab.model';
1920
import { Labs } from '../../both/collections/lab.collection';
21+
import { Example1 } from "./example_labs";
2022

2123
import { User, Role } from '../../both/models/user.model';
2224
import { Users } from '../../both/collections/user.collection';
2325

24-
import { Example1 } from "./example_labs";
2526

2627
/*
2728
* cleanupDatabase
@@ -174,8 +175,8 @@
174175
]
175176
})
176177
};
177-
Courses.addLab(this.courses['gpi'], this.labs['gpi/git']);
178-
Courses.addLab(this.courses['gpi'], this.labs['gpi/apache']);
178+
createLab(this.courses['gpi'], this.labs['gpi/git']);
179+
createLab(this.courses['gpi'], this.labs['gpi/apache']);
179180

180181
}
181182

imports/test/server/api/lab.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
import { DefaultFixtures } from '../../../fixtures';
1111
import { Example1 } from '../../../fixtures/example_labs';
1212

13-
import { Lab } from '../../../../both/models/lab.model';
13+
import { Lab, LabFileImportOpts } from '../../../../both/models/lab.model';
1414
import { Labs } from '../../../../both/collections/lab.collection';
15-
import { LabRuntime, LabFileImportOpts } from '../../../../server/imports/runtime/lab_runtime';
15+
import { LabRuntime } from '../../../../server/imports/runtime/lab_runtime';
1616

1717
export function LabRuntimeTests(){
1818
describe('Lab Runtime', function(){

server/imports/runtime/lab_runtime.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import { Cache } from '../service/cache';
1212
import { log } from '../service/log';
1313

14-
import { Lab as LabModel, Task as TaskModel, LabStatus } from '../../../both/models/lab.model';
14+
import { Lab as LabModel, Task as TaskModel, LabStatus, LabFileImportOpts } from '../../../both/models/lab.model';
1515
import { Labs } from '../../../both/collections/lab.collection';
1616

1717
import { VMConfig, VMResolveConfig, VMConfigCustom } from '../api/vmconfig';
@@ -30,16 +30,6 @@
3030
console: console
3131
}
3232

33-
/*
34-
labFileImportOpts
35-
Sets options for creating a labfile
36-
*/
37-
export interface LabFileImportOpts{
38-
_id?: string;
39-
course_id: string;
40-
file: string;
41-
}
42-
4333
export class LabRuntime extends Cache implements LabModel {
4434
// LabCache Elements
4535
protected static _TTL : number = Meteor.settings['private']['labvm']['labruntime_idle_timeout'];

server/methods/course.methods.ts

Lines changed: 105 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
import { Course, ContentPermissions } from '../../both/models/course.model';
66
import { Courses } from '../../both/collections/course.collection';
7+
8+
import { Lab, LabFileImportOpts } from '../../both/models/lab.model';
9+
import { LabRuntime } from '../../server/imports/runtime/lab_runtime';
10+
import { Labs } from '../../both/collections/lab.collection';
11+
712
import { Role } from '../../both/models/user.model';
813
import { Users } from '../../both/collections/user.collection';
914

@@ -47,12 +52,108 @@
4752
Meteor.publish('courses.id', coursesId);
4853

4954
/* METHODS */
55+
export function addInstructor(course_id : string, user_id : string) {
56+
Courses.update({ _id: course_id }, { '$addToSet' : { instructors : user_id}});
57+
}
58+
59+
export function removeInstructor(course_id : string, user_id : string){
60+
Courses.update({ _id: course_id }, { '$pull' : { instructors : user_id}});
61+
}
62+
63+
/* CREATE LAB */
64+
export function createLab(course_id : string, lab_file : string) : Promise<any>{
65+
66+
// Create Lab Runtime
67+
return LabRuntime.createLabRuntime({
68+
course_id : course_id,
69+
file: lab_file
70+
})
71+
72+
// Create Lab Record
73+
.then((labRuntime : LabRuntime) => {
74+
return labRuntime._id;
75+
76+
// Insert into Course Record
77+
}).then((lab_id) => {
78+
return new Promise((resolve, reject) => {
79+
Courses.update({
80+
_id: course_id
81+
}, {
82+
'$addToSet' : { labs : lab_id}
83+
}, (err, res) => {
84+
if(err){
85+
reject(err);
86+
} else {
87+
resolve(res);
88+
}
89+
});
90+
});
91+
})
92+
}
93+
94+
/* REMOVE LAB */
95+
export function removeLab(course_id : string, lab_id : string) : Promise<any>{
96+
// Remove Lab
97+
return new Promise((resolve, reject) => {
98+
Labs.remove({
99+
_id : lab_id
100+
}, (err, res) => {
101+
if(err){
102+
reject(err);
103+
} else {
104+
resolve(res);
105+
}
106+
});
107+
108+
// Remove from Course Record
109+
}).then(() => {
110+
return new Promise((resolve, reject) => {
111+
Courses.update({
112+
_id: course_id
113+
}, {
114+
'$pull' : { instructors : lab_id}
115+
},(err, res) => {
116+
if(err){
117+
reject(err);
118+
} else {
119+
resolve(res);
120+
}
121+
});
122+
});
123+
});
124+
}
125+
126+
export function reorderLabs(course_id : string, labs : string[]) : Promise<any>{
127+
return new Promise((resolve, reject) => {
128+
Courses.rawCollection().findAndModify({ _id : course_id, labs : { $all : labs }},{},{ $set : { labs : labs } }, (err, res) => {
129+
if(err){
130+
reject(err);
131+
} else {
132+
resolve();
133+
}
134+
});
135+
})
136+
}
137+
50138
Meteor.methods({
51-
'Courses.reorderLabs'(course_id : string, labs : string[]){
52-
return Courses.reorderLabs(course_id, labs)
139+
'Courses.createLab'({course_id, lab_file}){
140+
return createLab(course_id, lab_file)
141+
.catch((err) => {
142+
throw new Meteor.Error("Could not add lab.")
143+
})
144+
},
145+
146+
'Courses.removeLab'({course_id, lab_id}){
147+
return removeLab(course_id, lab_id)
148+
.catch((err) => {
149+
throw new Meteor.Error("Could not remove lab.")
150+
})
151+
},
152+
153+
'Courses.reorderLabs'({course_id, labs}){
154+
return reorderLabs(course_id, labs)
53155
.catch((err) => {
54-
console.error(err);
55-
throw new Meteor.Error("Redorder Conflict");
156+
throw new Meteor.Error("Could not reorder labs.");
56157
});
57158
}
58159
})

0 commit comments

Comments
 (0)