Skip to content

Commit cac1f4e

Browse files
Merge Dan and Kyle changes
2 parents 3e052f8 + b4e9a23 commit cac1f4e

File tree

11 files changed

+296
-92
lines changed

11 files changed

+296
-92
lines changed

app/assets/stylesheets/project4.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ form button:hover, form button:active {
6262
background-color: #7b9095;
6363
}
6464

65+
.dataTables_scrollHeadInner{
66+
padding: 0 !important;
67+
}
68+
6569
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default, .ui-button, html .ui-button.ui-state-disabled:hover, html .ui-button.ui-state-disabled:active{
6670
background-color: #b4bfba;
6771
}
@@ -191,6 +195,11 @@ table div, .dataTables_scrollHead, .dataTables_scrollHeadInner, .dataTables_scro
191195
color: green;
192196
}
193197

198+
#upperPanel {
199+
text-align: center;
200+
flex-direction: column;
201+
}
202+
194203
#trash{
195204
font-size: 64px;
196205
}

app/controllers/plans_controller.rb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,19 @@ class PlansController < ApplicationController
55
# GET /plans
66
# GET /plans.json
77
def index
8-
@plans = Plan.where(user_id: current_user.id)
8+
if current_user.role == "admin"
9+
@plans = Plan.all
10+
else
11+
@plans = Plan.where(user_id: current_user.id)
12+
end
913
end
1014

1115
# GET /plans/1
1216
# GET /plans/1.json
1317
def show
18+
if @plan.user_id != current_user.id
19+
redirect_to plans_path
20+
end
1421
end
1522

1623
# GET /plans/new

app/javascript/packs/myjs.js

Lines changed: 156 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
var currPlan = false;
2-
var plan = false;
1+
var currPlan = null;
2+
var plan = null;
33
var selectedMajor = "Comp. Sci.";
44
var selectedCatalogYear = 2017;
55
var catalogLoaded = false;
6-
var draggedCourse = false;
7-
var draggedReqOrigin = false;
8-
var draggedPlanOrigin = false;
9-
10-
$(getPlans);
6+
var planTableLoaded = false;
7+
var draggedCourse = null;
8+
var draggedReqOrigin = null;
9+
var draggedPlanOrigin = null;
10+
var draggedCatOrigin = null;
1111

1212
// changes plan, triggered on selection of new plan in dropdown
1313
$(document).on('change', '#planSelect', function (){
@@ -19,15 +19,45 @@ $(document).on('change', '#planSelect', function (){
1919
selectedCatalogYear = parseInt(selected[1]);
2020

2121
// send request to load new plan
22-
getPlans();
22+
getPlan();
2323

2424
});
2525

26-
function getPlans(){
27-
$.get("plans.json", function(plans){
26+
// For loading the table of plans
27+
window.getAllPlans = function(){
28+
$.get("/plans.json", function(plans){
2829
//console.log(plans);
29-
plan = false;
30+
let buttons = [];
31+
let colObjects = [];
32+
for (let p in plans){
33+
let openHtml = "<a href='/plans/" + plans[p].id + "'>Open</a>";
34+
colObjects.push({"plan": plans[p], "open": openHtml });
35+
}
36+
if (!planTableLoaded){
37+
$("#plansTable").DataTable( {
38+
"dom": '<"top"if>t',
39+
"data": colObjects,
40+
"columns": [
41+
{ "data": "plan.user.login" },
42+
{ "data": "plan.plan_name" },
43+
{ "data": "plan.major" },
44+
{ "data": "plan.catalog.year"},
45+
{ "data": "open" }
46+
],
47+
"paging": false,
48+
});
49+
$('.dataTables_scrollHeadInner').css('padding', '0');
50+
planTableLoaded = true;
51+
}
52+
});
53+
}
54+
55+
// For loading a single plan
56+
window.getPlan = function(){
57+
$.get("/plans.json", function(plans){
58+
plan = null;
3059
$(".dropdown").html("<option selected disabled>Change Plan</option>");
60+
// set current plan
3161
for (let i in plans){
3262
if (plans[i].major === selectedMajor && plans[i].catalog.year === selectedCatalogYear){
3363
plan = plans[i];
@@ -37,10 +67,11 @@ function getPlans(){
3767
$(".dropdown").append("<option>" + plans[i].major + ", " + plans[i].catalog.year + "</option>");
3868
}
3969
}
40-
if (plan === false){
70+
if (plan == null){
4171
console.log("Error: did not find selected plan");
4272
}
4373

74+
// dynamically generate years, terms, semesters on page
4475
currPlan = new Plan(plan.user.login, plan.plan_name, plan.major, plan.curr_year, plan.curr_term, plan.courses, plan.catalog.year);
4576
currPlan.sortCourses();
4677
currPlan.generateHTML();
@@ -52,6 +83,7 @@ function getPlans(){
5283
$("#hrsFuture").html("Remaining Hours: " + currPlan.hrsFuture);
5384
$("#hrsTotal").html("Total Hours Planned: " + currPlan.hrsTotal);
5485

86+
// load catalog table
5587
let courses = [];
5688
for (let c in plan.catalog.courses){
5789
courses.push(plan.catalog.courses[c]);
@@ -68,7 +100,7 @@ function getPlans(){
68100
],
69101
"scrollY": "95px",
70102
"paging": false,
71-
"scrollCollapse": false
103+
"scrollCollapse": false
72104
});
73105
$('.dataTables_scrollHeadInner').css('padding', '0');
74106
catalogLoaded = true;
@@ -79,12 +111,11 @@ function getPlans(){
79111
}
80112

81113

114+
// load accordion with requirements
82115
var requirements = plan.requirements;
83-
84116
$( function() {
85117
$( "#accordion" ).accordion({collapsible: true, active: false});
86118
});
87-
88119
$('#accordion').empty();
89120
for (let i in requirements){
90121
let reqCourses = requirements[i].courses;
@@ -129,75 +160,118 @@ function checkMissingReqs() {
129160
}
130161

131162
function courseInPlan(designator){
132-
let c = plan.courses[designator];
163+
let c = currPlan.courses[designator];
133164
return c !== undefined;
134165
}
135166

167+
// check if course is already in the semester being dropped on
168+
function courseInSemester(designator, droppedTerm){
169+
for (let i=0; i < droppedTerm.children.length; i++){
170+
if (droppedTerm.children[i].innerText.includes(designator)){
171+
return true;
172+
}
173+
}
174+
return false;
175+
}
176+
177+
// set source course when dragging from requiremetns accordion
136178
window.dragFromReq = function(event){
137179
let desig = event.target.innerText.split(": ")[0];
138180
draggedCourse = plan.catalog.courses[desig];
139181
draggedPlanOrigin = null;
182+
draggedCatOrigin = null;
140183
draggedReqOrigin = event.target;
141184
}
142185

186+
// set source course when dragging from catalog table
143187
window.dragFromCat = function(event){
144188
let desig = event.target.children[0].innerText
145189
draggedCourse = plan.catalog.courses[desig];
146190
draggedPlanOrigin = null;
147191
draggedReqOrigin = null;
192+
draggedCatOrigin = event.target;
148193
}
149194

195+
// set source course when dragging from plan
150196
window.dragFromPlan = function(event){
151197
let desig = event.target.innerText.split(": ")[0];
152198
draggedCourse = plan.catalog.courses[desig];
153199
draggedReqOrigin = null;
200+
draggedPlanOrigin = event.target;
201+
draggedCatOrigin = null;
154202
draggedPlanOrigin = event.target;
155203
checkMissingReqs();
156204
}
157205

206+
// indicate valid drop when hovering over plan
158207
window.hoverOverPlan = function(event){
159208
event.preventDefault();
160209
}
161210

211+
// update db when dropping course on plan
162212
window.dropOnPlan = function(event){
163213
event.preventDefault();
164-
event.target.children[1].innerHTML += "<li draggable='true' ondragstart='dragFromPlan(event)'>" + draggedCourse.designator + ": " + draggedCourse.name + "</li>";
165-
if (event.target.classList.contains('current')){
166-
currPlan.hrsCurrent += draggedCourse.credits;
167-
}
168-
else if (event.target.classList.contains('notStarted')){
169-
currPlan.hrsFuture += draggedCourse.credits;
170-
}
171-
else{
172-
currPlan.hrsCompleted += draggedCourse.credits;
173-
}
174-
let hours = parseInt(event.target.children[0].children[1].innerText.split(": ")[1]);
175-
event.target.children[0].children[1].innerText = "Hours: " + (hours + draggedCourse.credits);
176-
if (draggedReqOrigin !== null){
177-
// From requirements accordion
178-
currPlan.hrsTotal += draggedCourse.credits;
179-
draggedReqOrigin.hidden = true;
180-
draggedReqOrigin = null;
181-
}
182-
else if (draggedPlanOrigin !== null){
183-
// From another term
184-
if (draggedPlanOrigin.parentElement.parentElement.classList.contains('current')){
185-
currPlan.hrsCurrent -= draggedCourse.credits;
214+
if (!(courseInSemester(draggedCourse.designator, event.target.children[1]) || (courseInPlan(draggedCourse.designator) && draggedCatOrigin != null))) {
215+
event.target.children[1].innerHTML += "<li draggable='true' ondragstart='dragFromPlan(event)'>" + draggedCourse.designator + ": " + draggedCourse.name + "</li>";
216+
if (event.target.classList.contains('current')){
217+
currPlan.hrsCurrent += draggedCourse.credits;
186218
}
187-
else if (draggedPlanOrigin.parentElement.parentElement.classList.contains('notStarted')){
188-
currPlan.hrsFuture -= draggedCourse.credits;
219+
else if (event.target.classList.contains('notStarted')){
220+
currPlan.hrsFuture += draggedCourse.credits;
189221
}
190222
else{
191-
currPlan.hrsCompleted -= draggedCourse.credits;
223+
currPlan.hrsCompleted += draggedCourse.credits;
192224
}
193-
let originHours = parseInt(draggedPlanOrigin.parentElement.previousSibling.children[1].innerText.split(": ")[1]);
194-
draggedPlanOrigin.parentElement.previousSibling.children[1].innerText = "Hours: " + (originHours - draggedCourse.credits);
195-
draggedPlanOrigin.remove();
196-
draggedPlanOrigin = null;
197-
}
198-
else{
199-
// From catalog table
200-
currPlan.hrsTotal += draggedCourse.credits;
225+
let hours = parseInt(event.target.children[0].children[1].innerText.split(": ")[1]);
226+
event.target.children[0].children[1].innerText = "Hours: " + (hours + draggedCourse.credits);
227+
if (draggedReqOrigin !== null){
228+
// From requirements accordion
229+
currPlan.hrsTotal += draggedCourse.credits;
230+
draggedReqOrigin.hidden = true;
231+
draggedReqOrigin = null;
232+
}
233+
else if (draggedPlanOrigin !== null){
234+
// From another term
235+
if (draggedPlanOrigin.parentElement.parentElement.classList.contains('current')){
236+
currPlan.hrsCurrent -= draggedCourse.credits;
237+
}
238+
else if (draggedPlanOrigin.parentElement.parentElement.classList.contains('notStarted')){
239+
currPlan.hrsFuture -= draggedCourse.credits;
240+
}
241+
else{
242+
currPlan.hrsCompleted -= draggedCourse.credits;
243+
}
244+
let originHours = parseInt(draggedPlanOrigin.parentElement.previousSibling.children[1].innerText.split(": ")[1]);
245+
draggedPlanOrigin.parentElement.previousSibling.children[1].innerText = "Hours: " + (originHours - draggedCourse.credits);
246+
draggedPlanOrigin.remove();
247+
draggedPlanOrigin = null;
248+
}
249+
else{
250+
// From catalog table
251+
currPlan.hrsTotal += draggedCourse.credits;
252+
removeFromRequirements(draggedCourse.designator);
253+
}
254+
// add to javascript plan object
255+
let destTerm = event.target.children[0].children[0].innerText.split(" ")[0];
256+
let destYear = parseInt(event.target.children[0].children[0].innerText.split(" ")[1]);
257+
let newCourse = {
258+
"designator": draggedCourse.designator,
259+
"term": destTerm,
260+
"year": destYear
261+
};
262+
currPlan.courses[draggedCourse.designator] = newCourse;
263+
//update db
264+
$.post("/plan_courses", {
265+
plan: plan.plan_name,
266+
user: plan.user.id,
267+
designator: draggedCourse.designator,
268+
term: destTerm,
269+
year: destYear
270+
});
271+
$("#hrsCompleted").html("Hours Completed: " + currPlan.hrsCompleted);
272+
$("#hrsCurrent").html("Current Hours: " + currPlan.hrsCurrent);
273+
$("#hrsFuture").html("Remaining Hours: " + currPlan.hrsFuture);
274+
$("#hrsTotal").html("Total Hours Planned: " + currPlan.hrsTotal);
201275
}
202276
$.post("/plan_courses", {
203277
plan: plan.plan_name,
@@ -234,6 +308,7 @@ window.dropInTrash = function(event){
234308
let originHours = parseInt(draggedPlanOrigin.parentElement.previousSibling.children[1].innerText.split(": ")[1]);
235309
draggedPlanOrigin.parentElement.previousSibling.children[1].innerText = "Hours: " + (originHours - draggedCourse.credits);
236310
draggedPlanOrigin.remove();
311+
delete currPlan.courses[draggedCourse.designator];
237312
draggedPlanOrigin = null;
238313

239314
$.get("/plan_courses", {
@@ -245,10 +320,42 @@ window.dropInTrash = function(event){
245320
$("#hrsCurrent").html("Current Hours: " + currPlan.hrsCurrent);
246321
$("#hrsFuture").html("Remaining Hours: " + currPlan.hrsFuture);
247322
$("#hrsTotal").html("Total Hours Planned: " + currPlan.hrsTotal);
323+
324+
addToRequirements(draggedCourse.designator);
248325
}
249326
draggedCourse = null;
250327
}
251328

329+
// Unhide requirement if removed from plan
330+
window.addToRequirements = function(designator){
331+
let acc = $('#accordion').get()[0];
332+
for (let i=1; i<acc.children.length; i+=2){
333+
let accChild = acc.children[i];
334+
for (let j = 0; j<accChild.children.length; j++){
335+
let req = accChild.children[j];
336+
if (req.innerText.includes(designator)){
337+
req.removeAttribute('hidden');
338+
return;
339+
}
340+
}
341+
}
342+
}
343+
344+
// Hide requirement if added from catalog table
345+
window.removeFromRequirements = function(designator){
346+
let acc = $('#accordion').get()[0];
347+
for (let i=1; i<acc.children.length; i+=2){
348+
let accChild = acc.children[i];
349+
for (let j = 0; j<accChild.children.length; j++){
350+
let req = accChild.children[j];
351+
if (req.innerText.includes(designator)){
352+
req.setAttribute('hidden', true);
353+
return;
354+
}
355+
}
356+
}
357+
}
358+
252359
class Course {
253360
constructor(desig, year, term){
254361
this.term = term;

app/models/user.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ class User < ApplicationRecord
44
devise :database_authenticatable, :registerable,
55
:recoverable, :rememberable, :validatable
66
has_many :plans
7-
belongs_to :major
7+
belongs_to :major, optional: true
88
end

app/views/plans/_plan.json.jbuilder

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ json.user do
33
json.login plan.user.login
44
json.role plan.user.role
55
end
6+
json.id plan.id
67
json.plan_name plan.name
78
json.major plan.major.name
89
json.curr_year plan.curr_year

0 commit comments

Comments
 (0)