diff --git a/client/imports/ui/components/mdeditor/mdeditor.ts b/client/imports/ui/components/mdeditor/mdeditor.ts
index 8c17ffe6..15428f16 100644
--- a/client/imports/ui/components/mdeditor/mdeditor.ts
+++ b/client/imports/ui/components/mdeditor/mdeditor.ts
@@ -29,7 +29,7 @@
ngAfterViewInit(){
var self = this;
// Instantiate SimpleMDE
- this.mde = new SimpleMDE({ element: this.elementRef.nativeElement.value });
+ this.mde = new SimpleMDE({ element: this.textarea.nativeElement });
// Read initial data from task markdown
this.mde.value(self.mdData);
// Catch changes
diff --git a/client/imports/ui/pages/course/course.html b/client/imports/ui/pages/course/course.html
index b5f2b45e..af2cae0b 100644
--- a/client/imports/ui/pages/course/course.html
+++ b/client/imports/ui/pages/course/course.html
@@ -9,6 +9,7 @@
Labs
Grades
Students
+ Upload
@@ -17,7 +18,8 @@
{{ courseNumber }} Home
Labs
Grades
- Students
+ Students
+ Upload
diff --git a/client/imports/ui/pages/course/course.ts b/client/imports/ui/pages/course/course.ts
index 1ae23984..df6e5eb7 100644
--- a/client/imports/ui/pages/course/course.ts
+++ b/client/imports/ui/pages/course/course.ts
@@ -41,7 +41,9 @@
this.subscribe('user-courses', () => {
this.autorun(() => {
- this.courseNumber = Collections.courses.findOne({ _id: this.courseId }).course_number;
+ if(typeof Collections.courses.findOne({ _id: this.courseId }) !== "undefined") {
+ this.courseNumber = Collections.courses.findOne({ _id: this.courseId }).course_number;
+ }
});
}, true);
}
diff --git a/client/imports/ui/pages/dashboard/dashboard.html b/client/imports/ui/pages/dashboard/dashboard.html
index bc4d5d51..04c6e0c3 100644
--- a/client/imports/ui/pages/dashboard/dashboard.html
+++ b/client/imports/ui/pages/dashboard/dashboard.html
@@ -62,13 +62,51 @@
-
-
-
- Welcome to TuxLab!
-
-
-
-
-
-
+
+
+
+
+
+
+
Welcome to TuxLab!
+
+
+
+
+
+
+
+
+
+
+
+
+
About TuxLab
+
+ TuxLab is an opensource platform for creating interactive Linux courses.
+ Click on the link below to read more about TuxLab!
+ Come back if you like what you see, go away if you do not.
+ Scroll down to browse some of the available courses on the site!
+
+
+
+
+
+
+
+
+
Explore Courses
+
+ These are some courses that you will be able to enroll
+ in once you have registered.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/imports/ui/pages/dashboard/dashboard.ts b/client/imports/ui/pages/dashboard/dashboard.ts
index 251a8fdf..e6db27d9 100644
--- a/client/imports/ui/pages/dashboard/dashboard.ts
+++ b/client/imports/ui/pages/dashboard/dashboard.ts
@@ -15,30 +15,38 @@
import { courses } from '../../../../../collections/courses.ts';
import { course_records } from '../../../../../collections/course_records.ts';
+// Explore
+ import { ExploreView } from '../../components/explore/explore.ts';
+
+// Login
+ import Login from '../account/login.ts';
+
// Define Dashboard Component
@Component({
- selector: 'tuxlab-dashboard',
- templateUrl: '/client/imports/ui/pages/dashboard/dashboard.html',
- directives: [
- MATERIAL_DIRECTIVES,
- MD_SIDENAV_DIRECTIVES,
- ROUTER_DIRECTIVES
- ]
+ selector: 'tuxlab-dashboard',
+ templateUrl: '/client/imports/ui/pages/dashboard/dashboard.html',
+ directives: [
+ MATERIAL_DIRECTIVES,
+ MD_SIDENAV_DIRECTIVES,
+ ROUTER_DIRECTIVES,
+ Login,
+ ExploreView
+ ]
})
// Export Dashboard Class
@InjectUser('user')
export default class Dashboard extends MeteorComponent {
- user : Meteor.User;
+ user : Meteor.User;
private courses = [];
private grades = [];
constructor() {
super();
- this.subscribe('user-courses', () => {
- this.courses = courses.find({}, { limit: 5 }).fetch();
- }, true);
+ this.subscribe('user-courses', () => {
+ this.courses = courses.find({}, { limit: 5 }).fetch();
+ }, true);
this.subscribe('course-records', () => {
let records = course_records.find().fetch();
for(let i = 0; i < records.length; i++) {
diff --git a/client/imports/ui/pages/lab/labcreate.ts b/client/imports/ui/pages/lab/labcreate.ts
index 004cf100..a622f41a 100644
--- a/client/imports/ui/pages/lab/labcreate.ts
+++ b/client/imports/ui/pages/lab/labcreate.ts
@@ -46,6 +46,8 @@ export default class LabCreate extends MeteorComponent {
this.lab.file = "";
this.uploaded = false;
this.output = "Compiling... Errors will display below.";
+
+ document.getElementById('course-content').style.maxWidth = "100%";
}
/* UPLOAD HANDLER */
diff --git a/client/imports/ui/routes/course.routes.ts b/client/imports/ui/routes/course.routes.ts
index d30d3ac2..b38a1cd5 100644
--- a/client/imports/ui/routes/course.routes.ts
+++ b/client/imports/ui/routes/course.routes.ts
@@ -12,6 +12,7 @@ import { GradeList } from '../pages/course/gradelist.ts';
import { LabList } from '../pages/course/lablist.ts';
import { CourseDashboard } from '../pages/course/course_dashboard.ts';
import { GradeView } from '../pages/course/gradeview.ts';
+import LabCreate from '../pages/lab/labcreate.ts'
import LabView from '../pages/lab/labview.ts';
export const courseRoutes: RouterConfig = [
@@ -23,7 +24,8 @@ export const courseRoutes: RouterConfig = [
{ path: 'grades', component: GradeList },
{ path: 'labs', component: LabList },
{ path: 'labs/:labid', canActivate: [ GuardAuth, CourseGuardRecord ], component: LabView },
- { path: 'grades/:gradeid', canActivate: [ GuardAuth ], component: GradeView }
+ { path: 'grades/:gradeid', canActivate: [ GuardAuth ], component: GradeView },
+ { path: 'lab-create', component: LabCreate }
// { path: 'users', as: 'UserList', component: UserList },
// { path: 'user/:userid', as: 'UserView', component: UserView },
// { path: 'labs', as: 'LabList', component: LabList },
diff --git a/client/imports/ui/routes/routes.ts b/client/imports/ui/routes/routes.ts
index dbead183..da2bdea5 100644
--- a/client/imports/ui/routes/routes.ts
+++ b/client/imports/ui/routes/routes.ts
@@ -14,9 +14,6 @@ import { provideRouter, RouterConfig } from '@angular/router';
// Error
import ErrorPage from '../pages/error/error.ts'
- // Lab
- import LabCreate from '../pages/lab/labcreate.ts'
-
// Course
import { courseRoutes } from './course.routes.ts';
import { CourseGuardRecord } from './course.guard.record.ts';
@@ -40,7 +37,6 @@ const routes : RouterConfig = [
{ path: 'login', component: Login },
{ path: 'terms', component: Terms },
{ path: 'privacy', component: Privacy },
- { path: 'lab-create', component: LabCreate },
{ path: 'explore', component: Explore },
{ path: 'courses', component: CourseList },
{ path: 'error/:code', component: ErrorPage },
diff --git a/client/style/dashboard/_dashboard.scss b/client/style/dashboard/_dashboard.scss
index 52e54932..ba60e5b5 100644
--- a/client/style/dashboard/_dashboard.scss
+++ b/client/style/dashboard/_dashboard.scss
@@ -63,3 +63,67 @@
}
}
}
+
+.tuxlab-dashboard-nonuser {
+ .login-section {
+ background-image: $university-splash-image;
+ background-repeat: no-repeat;
+ background-size: cover;
+ box-shadow: inset 0 0 0 1000px rgba(0, 0, 0, 0.5);
+ height: 55vh;
+ padding-top: 15vh;
+ .login-wrapper {
+ max-width: $tuxlab-max-width;
+ margin: 0 auto;
+ .login-card {
+ width: 500px;
+ margin:0;
+ h1 {
+ color: #e5e5e6;
+ font-family: "Open Sans";
+ font-weight: 300;
+ font-size: 46px;
+ text-align: center;
+ }
+ md-card {
+ margin: 0;
+ background-color: rgba(255, 255, 255, 0.6);
+ md-card-content {
+ margin: 0;
+ padding: 0;
+ }
+ }
+ .tuxlab-login {
+ height: 250px;
+ }
+ }
+ }
+ }
+ .section-text {
+ h1 {
+ color: #444444;
+ font-family: "Open Sans";
+ font-weight: 300;
+ font-size: 46px;
+ padding: 15px;
+ }
+ .button-wrapper {
+ margin-top: 20px;
+ margin-bottom: 15px;
+ text-align: center;
+ a {
+ color: white;
+ background-color: #4fafef;
+ }
+ }
+ }
+ .about-section {
+ background-color: white;
+ padding: 15px;
+ @extend .section-text;
+ }
+ .courses-section {
+ padding: 15px;
+ @extend .section-text;
+ }
+}
\ No newline at end of file
diff --git a/client/style/explore/_explore.scss b/client/style/explore/_explore.scss
index b5994aa3..5d0b32bb 100644
--- a/client/style/explore/_explore.scss
+++ b/client/style/explore/_explore.scss
@@ -2,21 +2,6 @@
width:100%;
max-width:$tuxlab-max-width;
margin:0 auto;
-
- md-tab-group {
- background-color: white;
- margin: 30px;
- .md-active.md-tab-label {
- background-color: #ffd54f;
- }
- md-ink-bar {
- background-color: white;
- }
- }
- .md-tab-header {
- background-color: #ffc400;
- }
-
#search-view {
display: none;
}
@@ -143,4 +128,17 @@
float: left;
}
}
+ md-tab-group {
+ background-color: white;
+ margin: 30px;
+ .md-active.md-tab-label {
+ background-color: #ffd54f;
+ }
+ md-ink-bar {
+ background-color: white;
+ }
+ }
+ .md-tab-header {
+ background-color: #ffc400;
+ }
}
\ No newline at end of file
diff --git a/client/style/theme/_cmu.scss b/client/style/theme/_cmu.scss
index 47bdbfa6..f968fd88 100644
--- a/client/style/theme/_cmu.scss
+++ b/client/style/theme/_cmu.scss
@@ -7,4 +7,5 @@ $primary-color-dark: #960e24;
// Images
$university_logo : url("https://upload.wikimedia.org/wikipedia/commons/thumb/9/9b/Carnegie_Mellon_wordmark.svg/2000px-Carnegie_Mellon_wordmark.svg.png");
$university_picture: url("http://engineering.cmu.edu/files/images/maker-wing/hamerschlag-large.jpg");
+$university_splash_image : url('http://www.asergeev.com/pictures/archives/2013/1212/jpeg/12.jpg');
$err_image : url("http://i.imgur.com/qI1CIwp.gif");
diff --git a/client/tuxlab.html b/client/tuxlab.html
index 6331f6ca..3fe149d0 100644
--- a/client/tuxlab.html
+++ b/client/tuxlab.html
@@ -16,7 +16,7 @@
Announcements
-
+
Terminal
diff --git a/client/tuxlab.ts b/client/tuxlab.ts
index 41e54e92..70d932e2 100644
--- a/client/tuxlab.ts
+++ b/client/tuxlab.ts
@@ -1,58 +1,75 @@
/* TuxLab - TuxLab.ts */
// Meteor Imports
- import { Meteor } from 'meteor/meteor';
- import { Mongo } from 'meteor/mongo';
- import 'reflect-metadata';
- import 'zone.js/dist/zone';
- import './startup.js';
+ import { Meteor } from 'meteor/meteor';
+ import { Mongo } from 'meteor/mongo';
+ import 'reflect-metadata';
+ import 'zone.js/dist/zone';
+ import './startup.js';
// Angular Imports
- import { MeteorComponent } from 'angular2-meteor';
- import { Component, ViewEncapsulation, provide, PLATFORM_DIRECTIVES} from '@angular/core';
- import { APP_BASE_HREF, CORE_DIRECTIVES } from '@angular/common';
- import { HTTP_PROVIDERS } from '@angular/http';
- import { bootstrap } from '@angular/platform-browser-dynamic';
- import { InjectUser } from 'angular2-meteor-accounts-ui';
+ import { MeteorComponent } from 'angular2-meteor';
+ import { Component, ViewEncapsulation, provide, PLATFORM_DIRECTIVES} from '@angular/core';
+ import { APP_BASE_HREF, CORE_DIRECTIVES } from '@angular/common';
+ import { HTTP_PROVIDERS } from '@angular/http';
+ import { bootstrap } from '@angular/platform-browser-dynamic';
+ import { InjectUser } from 'angular2-meteor-accounts-ui';
// Angular Material Imports
- import { MATERIAL_PROVIDERS, MATERIAL_DIRECTIVES } from 'ng2-material';
- import { ResponsiveState, RESPONSIVE_DIRECTIVES } from 'responsive-directives-angular2';
- import { disableDeprecatedForms, provideForms } from '@angular/forms';
- import { MD_ICON_DIRECTIVES, MdIconRegistry } from '@angular2-material/icon'
- import { MD_SIDENAV_DIRECTIVES } from '@angular2-material/sidenav';
- import { MD_TOOLBAR_DIRECTIVES } from '@angular2-material/toolbar';
+ import { MATERIAL_PROVIDERS, MATERIAL_DIRECTIVES } from 'ng2-material';
+ import { ResponsiveState, RESPONSIVE_DIRECTIVES } from 'responsive-directives-angular2';
+ import { disableDeprecatedForms, provideForms } from '@angular/forms';
+ import { MD_ICON_DIRECTIVES, MdIconRegistry } from '@angular2-material/icon'
+ import { MD_SIDENAV_DIRECTIVES } from '@angular2-material/sidenav';
+ import { MD_TOOLBAR_DIRECTIVES } from '@angular2-material/toolbar';
// Routes
- import { ROUTER_DIRECTIVES, RouterConfig, Router } from '@angular/router';
- import { ROUTE_PROVIDERS } from './imports/ui/routes/routes.ts'
+ import { ROUTER_DIRECTIVES, RouterConfig, Router } from '@angular/router';
+ import { ROUTE_PROVIDERS } from './imports/ui/routes/routes.ts'
// Define TuxLab Component
@Component({
- selector: 'tuxlab',
- templateUrl: '/client/tuxlab.html',
- directives: [ ROUTER_DIRECTIVES,
- MATERIAL_DIRECTIVES,
- MD_TOOLBAR_DIRECTIVES,
- MD_ICON_DIRECTIVES,
- MD_SIDENAV_DIRECTIVES
- ],
- viewProviders: [MdIconRegistry]
+ selector: 'tuxlab',
+ templateUrl: '/client/tuxlab.html',
+ directives: [
+ ROUTER_DIRECTIVES,
+ MATERIAL_DIRECTIVES,
+ MD_TOOLBAR_DIRECTIVES,
+ MD_ICON_DIRECTIVES,
+ MD_SIDENAV_DIRECTIVES
+ ],
+ viewProviders: [MdIconRegistry]
})
@InjectUser('user')
class TuxLab extends MeteorComponent {
- user: Meteor.User;
- constructor(mdIconRegistry: MdIconRegistry, private router: Router) {
- super();
- // Create Icon Font
- mdIconRegistry.registerFontClassAlias('tux', 'tuxicon');
- mdIconRegistry.setDefaultFontSetClass('tuxicon');
- }
- tuxLogout() {
- Meteor.logout();
- this.router.navigate(['/']);
- }
+ user: Meteor.User;
+ lastLabId: string;
+ lastCourseId: string;
+
+ constructor(mdIconRegistry: MdIconRegistry, private router: Router) {
+ super();
+ // Create Icon Font
+ mdIconRegistry.registerFontClassAlias('tux', 'tuxicon');
+ mdIconRegistry.setDefaultFontSetClass('tuxicon');
+ }
+
+ tuxLogout() {
+ Meteor.logout();
+ this.router.navigate(['/']);
+ }
+
+ toLastLab() {
+ var self = this;
+ Meteor.call('getLastLab', function(err, res) {
+ if (err) {
+ self.router.navigate(['/']);
+ }
+ else {
+ self.router.navigate(['/course/' + res.courseId + '/labs/' + res.labId]);
+ }
+ });
+ }
}
bootstrap(TuxLab, [
diff --git a/server/imports/lab/methods.ts b/server/imports/lab/methods.ts
index a7c515f6..ad09c102 100644
--- a/server/imports/lab/methods.ts
+++ b/server/imports/lab/methods.ts
@@ -14,7 +14,7 @@ import{ prepLab, next, verify } from './labMethods.ts';
import{ markdown_editor } from './export_markdown.ts';
Meteor.methods({
-
+
/**prepareLab: prepares a labExec object for the current user
* takes the id of the lab and a callback as parameter
* callback: (err,pass)
@@ -24,7 +24,7 @@ Meteor.methods({
TuxLog.log("trace","preparing lab");
- Meteor.user().sessions.push({labId: labId,started: Date.now()});
+ // Meteor.user().sessions.push({labId: labId,started: Date.now()});
// Collections.users.update({_id: Meteor.userId()},{$set:{sessions: this.user.sessions}});
//get course Id
@@ -53,7 +53,7 @@ Meteor.methods({
//get user nick
var uId = Meteor.user().profile.nickname;
-
+
//wrap sync functions
var verifyAsync = Meteor.wrapAsync(verify);
@@ -81,7 +81,7 @@ Meteor.methods({
var courseId = Collections.labs.findOne({_id: labId}).course_id;
//wrap sync functions
var nextAsync = Meteor.wrapAsync(next);
-
+
try{
var res = nextAsync(uId,labId,courseId);
return res;
@@ -105,22 +105,22 @@ Meteor.methods({
SessionCache.get(uId,labId,function(err,res){
if(err){
TuxLog.log("warn",err);
- throw new Meteor.Error("Internal Service Error");
+ throw new Meteor.Error("Internal Service Error");
}
else if(!res){
TuxLog.log("warn",new Meteor.Error("SessionCache.get failed to return a session instance"));
- throw new Meteor.Error("Internal Service Error");
+ throw new Meteor.Error("Internal Service Error");
}
else{
var endAsync = Meteor.wrapAsync(res.end,res);
- try{
- var result = endAsync();
- return "success" //TODO: @Derek what to return here?
- }
- catch(e){
- TuxLog.log("warn",e);
- throw new Meteor.Error("Internal Service Error");
- }
+ try{
+ var result = endAsync();
+ return "success" //TODO: @Derek what to return here?
+ }
+ catch(e){
+ TuxLog.log("warn",e);
+ throw new Meteor.Error("Internal Service Error");
+ }
}
});
},
diff --git a/server/imports/startup/docker.js b/server/imports/startup/docker.js
index ee466379..b08df197 100644
--- a/server/imports/startup/docker.js
+++ b/server/imports/startup/docker.js
@@ -3,9 +3,9 @@ var fs = require('fs');
var dockerode_options = {
host: nconf.get('swarm_node_ip'),
- port: nconf.get('swarm_node_port'),
- ca: fs.readFileSync(nconf.get('swarm_cert_dir')+"/ca.pem"),
- cert: fs.readFileSync(nconf.get('swarm_cert_dir')+"/cert.pem"),
- key: fs.readFileSync(nconf.get('swarm_cert_dir')+"/key.pem")
+ port: nconf.get('swarm_node_port')//,
+ // ca: fs.readFileSync(nconf.get('swarm_cert_dir')+"/ca.pem"),
+ // cert: fs.readFileSync(nconf.get('swarm_cert_dir')+"/cert.pem"),
+ //key: fs.readFileSync(nconf.get('swarm_cert_dir')+"/key.pem")
};
docker = new dockerode(dockerode_options);
diff --git a/tsconfig.json b/tsconfig.json
index ef0803c5..5d798445 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -56,6 +56,7 @@
"server/imports/course/methods.ts",
"server/imports/course/search.ts",
"server/imports/lab/checkLab.d.ts",
+ "server/imports/lab/export_markdown.ts",
"server/imports/lab/labMethods.ts",
"server/imports/lab/markdown.ts",
"server/imports/lab/methods.ts",