From bef274eed7f250bafb85cfef1208adc9b13036dd Mon Sep 17 00:00:00 2001 From: James Halladay Date: Wed, 29 Apr 2020 16:30:34 -0600 Subject: [PATCH 01/17] initial commit --- src/readme.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/readme.txt b/src/readme.txt index 7102c9a..9cc7cec 100644 --- a/src/readme.txt +++ b/src/readme.txt @@ -11,6 +11,7 @@ There are 1 execution path: + To Use the planner App: The app is fairly simple on the surface From e839f594877fbf4e075e384f27556075632bc7b1 Mon Sep 17 00:00:00 2001 From: James Halladay Date: Wed, 29 Apr 2020 20:04:42 -0600 Subject: [PATCH 02/17] worked on server templates, broke mvc.js to prepare for reWrite --- backup/plannerbackup.ejs | 83 +++ {src => backup}/public/admin.html | 0 backup/public/index.html | 96 +++ backup/public/mvcWorking.js | 681 ++++++++++++++++++ backup/public/mvcbackup.js | 677 +++++++++++++++++ {src => backup}/public/planner.html | 0 .../public}/scoreboard.js | 0 {src => backup}/public/states/state2.html | 0 {src => backup}/public/states/state3.html | 0 .../javascript => backup/public}/templates.js | 0 {src => backup}/public/test.html | 0 src/public/css/main.css | 28 +- src/public/css/reset.css | 108 +++ src/public/javascript/app.js | 0 src/public/javascript/controller.js | 0 .../javascript/controller/controller.js | 130 +--- src/public/javascript/models/model.js | 90 +-- src/public/javascript/models/scoreboard.js | 1 + src/public/javascript/mvc.js | 680 ----------------- src/routes/index.js | 6 +- src/routes/user.js | 2 +- src/views/layout.ejs | 28 +- src/views/login.ejs | 5 +- src/views/planner.ejs | 122 +--- src/views/welcome.ejs | 14 +- 25 files changed, 1788 insertions(+), 963 deletions(-) create mode 100644 backup/plannerbackup.ejs rename {src => backup}/public/admin.html (100%) create mode 100644 backup/public/index.html create mode 100644 backup/public/mvcWorking.js create mode 100644 backup/public/mvcbackup.js rename {src => backup}/public/planner.html (100%) rename {src/public/javascript => backup/public}/scoreboard.js (100%) rename {src => backup}/public/states/state2.html (100%) rename {src => backup}/public/states/state3.html (100%) rename {src/public/javascript => backup/public}/templates.js (100%) rename {src => backup}/public/test.html (100%) create mode 100644 src/public/css/reset.css delete mode 100644 src/public/javascript/app.js delete mode 100644 src/public/javascript/controller.js diff --git a/backup/plannerbackup.ejs b/backup/plannerbackup.ejs new file mode 100644 index 0000000..3607d66 --- /dev/null +++ b/backup/plannerbackup.ejs @@ -0,0 +1,83 @@ + + +
+ + + +
+ +
+ +

+
+ +
+
+
+
+ +
+
+

Subject Control Panel

+

Add New Subject

+
+ + +
+
+
+
+
+ +
+ +
+ + +
+ +
+
+ +
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+ +
+ + + +
+
+
+ +
+

+ +
+ + + diff --git a/src/public/admin.html b/backup/public/admin.html similarity index 100% rename from src/public/admin.html rename to backup/public/admin.html diff --git a/backup/public/index.html b/backup/public/index.html new file mode 100644 index 0000000..3a93227 --- /dev/null +++ b/backup/public/index.html @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + +
+ +

+
+ +
+
+
+
+ +
+
+

Subject Control Panel

+

Add New Subject

+
+ + +
+
+
+
+
+ +
+ +
+ + +
+ +
+
+ +
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+ +
+ + + +
+
+
+ +
+

+ +
+ + + diff --git a/backup/public/mvcWorking.js b/backup/public/mvcWorking.js new file mode 100644 index 0000000..0b738dc --- /dev/null +++ b/backup/public/mvcWorking.js @@ -0,0 +1,681 @@ +/* +************************************************************************** +Assignment: Project 2 - Planner App +Author: James Halladay +Advanced Programming with JavaScript +Date: 3/30/2020 + + +************************************************************************** + +I wanted to build a model view controller to get a better understanding of + the design pattern. I had once tried to use Django for python, which uses + the model-template-view pattern, and was completely lost and overwhelmed. + Since the MTV pattern is descended from the MVC, and the MVC seems to be + a pervasive pattern in the industry so I went about building one instead + of a MTV. + +The project itself is a planner that adds todo items organized first by custom + subjects and then by individual todo categories. The user allocates points + to give weight to larger todo items. When a Todo item is completed, the + points are added to a score that is maintained by the Model Class. The + scoreboard displays totals for points earned both daily and weekly, going + back 1 week. It also shows the users historic high scores. + +The point system allows users to quantitatively measure their productivity in a + meaningful way, and provides the user with motivation in a game-like fashion. + A user may strive to cram in as many items as possible to exceed previous + scores. + +There are 3 classes in this file as well as one IIFE that serves to initialize + the classes. + +The Model Class is composed of the Scoreboard class created in the scoreboard.js + file and controls the data for the planner app. + +The View Class imports templates from function stored in the templates.js file + and controls all changes to the appearance of Planner App through HTML + modifications. + +The Controller Class is composed of the Model and View Classes and facilitates + all interactions between the user and the program + + +I Think I accomplished most of my goals, but Initially I had planned for the app + to use server side storage so I could use this for school. The mvc.js itself + needs refactored to use more loops because of the huge blocks of code that + creates HTML selectors are both not aesthetic and just bad code. + +I had some problems getting local storage built in after building the app. It seems + that I need to refactor the Controller Class methods in order to have the app + restart with all the Panels active. + +I also need to create a set of methods for the Model Class to fetch old data from + the server and send data to the server. I would like to do this because it + would allow me to rely on the data being present in the case of a browser + update that clears the cache or some other incident that results in the + browser data being unrecoverable. + +************************************************************************** +*/ + +import {Scoreboard} from "./models/scoreboard.js"; +import {template, queTemplate} from "./views/templates.js"; + +'use strict' + + +/** + * Class stores all of the data for the planner app + * contains methods for manipulating the data + * using the scoreboard object in its composition + * located in ./scoreboard.js + */ +class Model{ + constructor() { + this.sb = new Scoreboard; + this.subjects = []; + this.categories = ['Homework', 'Projects', 'Reading', 'Tests', 'Videos']; + this.data ={}; + this.que = {Homework: [], Projects: [], Reading: [], Tests: [], Videos: []}; + this.completedQue = {Homework: [], Projects: [], Reading: [], Tests: [], Videos: []}; + this.deletedQue = {Homework: [], Projects: [], Reading: [], Tests: [], Videos: []}; + }; + + + /** + * function creates a new set of arrays inside the + * data object to represent a new subject + */ + subjectFactory(subject) { + return this.data[subject] = { + Homework: [], + Projects: [], + Reading: [], + Tests: [], + Videos: [] + }; + }; + + + /** + * Function adds new todo item to the Ques and + * sorts them by due date + */ + queBuilder(subject, category) { + var incoming = this.data[subject][category]; + var newItem = incoming[incoming.length - 1]; + var section = this.que[category]; + section.push(newItem); + section.sort((a, b) => { + if (a['due'] < b['due']) { + return -1; + } else if (a['due'] > b['due']) { + return 1; + } else { + return 0; + }; + }); + console.log(section); + console.log("Queue: ",this.que) + return this; + }; + + + /** + * function gives a point multiplier that + * depends on how soon the todo item is due + */ + checkMultiplier(dueDate) { + var output = dueDate === ''? 0: 1; + if (output = 0) { + return output + }; + var today = Date.parse(new Date); + var item = Date.parse(dueDate); + var difference = (item - today)/3600000; + if (difference < 6) { + var output = 2; + } else if (difference < 12) { + var output = 1.5; + }; + return output; + }; + + + queHandler(category, action) { + var data = this.que[category].shift(); + if (action == 'delete') { + console.log("deleted") + this.deletedQue[category].push(data); + + } else if (action == 'complete') { + this.completedQue[category].push(data); + var points = parseInt(data.points) * this.checkMultiplier(data.due); + this.sb.setPoints(points); + console.table(this.sb.score); + }; + } + + +}; + + + + + +/** + * Class controls all user interface manipulations + * instantiates selectors for the controller to access + * and passes data from the UI to the controller + */ +class View { + constructor() { + this.que = {}; + this.needed = {}; + this.scoreboard = {}; + this.createSubject = document.querySelector('#create-subject'); + this.subjectControl = document.querySelector('#control'); + this.subjectCategories = document.querySelector('#add-items') || ''; + this.scoreboard.id = document.getElementById('score'); + this.que.id = document.getElementById('que-list'); + this.needed.due = 0; + this.needed.que = 0; + }; + + + /** + * Function constructs the subject list drop down and appends an option for + * each subject created by the user + */ + subjectList(subjects) { + var displayArea = document.getElementById('subject-subcategories') + if (subjects.length == 0) { + while (displayArea.firstChild) { + displayArea.removeChild(displayArea.firstChild) + }; + return this; + } else if (!(document.getElementById('subject-list'))) { + if (!document.getElementById('subject-list-label')) { + var label = document.createElement('label'); + label.innerText = "Subject: "; + label.htmlFor = 'subjects'; + label.id = 'subject-list-label'; + displayArea.append(label); + }; + + var list = document.createElement('select'); + list.name = "subjects"; + list.id = 'subject-list'; + displayArea.append(list); + } else { + var list = document.getElementById('subject-list'); + }; + + while (list.firstChild) { + list.removeChild(list.firstChild); + }; + + subjects.forEach((x)=>{ + var option = document.createElement("option"); + option.textContent = x; + option.value = x; + option.className = x; + list.append(option); + }); + + this.createSubjectItems() + this.subjectCategories = document.querySelector('#add-items') + return this; + }; + + + /** + * function creates input fields to add items to + * the que under their subjects and categories + */ + createSubjectItems() { + if (document.getElementById('subject-list') && !document.getElementById('add-items')) { + var displayArea = document.getElementById('subject-subcategories'); + + var newDiv = document.createElement('div'); + newDiv.className = "subcategories"; + newDiv.innerHTML = template('subject-panel'); + newDiv.id = 'addToDo'; + displayArea.append(newDiv); + this.subjectToDo = document.getElementById('addToDo') + + var button = document.createElement('button'); + button.id = "add-items"; + button.textContent = 'Submit'; + displayArea.append(button); + }; + this.categorySelectors(); + return this; + }; + + + /** + * function checks to make sure the input fields on the subject panel + * have been properly entered. If not appends a message to guide the + * user to the bottom of the panel + */ + checkToDoInput() { + var parsedDate = Date.parse(this.dueSelector.value); + if (isNaN(parsedDate) || this.todoSelector.value == '') { + if (this.needed.due == 0) { + var needDue = document.createElement("p"); + needDue.innerText = 'Item and Due Date are required to create new Todo'; + this.subjectToDo.append(needDue); + this.needed.due = 1; + }; + return false; + } else if (this.needed.due == 1) { + this.needed.due = 0; + this.subjectToDo.removeChild(this.subjectToDo.lastChild); + }; + return true; + }; + + + /** + * function constructs each categories cell in the que interface + * using the queTemplate from ./templates.js + */ + constructQue(category) { + var newQue = document.createElement('div'); + newQue.id = 'que'; + newQue.innerHTML = queTemplate(category); + this.que.id.append(newQue); + this.queSelectors(); + return this; + }; + + + /** + * Function creates the scoreboard interface using + * the scoreboard template from ./template.js + */ + constructScoreboard() { + var sb = document.createElement('div'); + sb.id = "scoreboard"; + sb.innerHTML = template('scoreboard'); + this.scoreboard.id.append(sb); + this.sbSelectors(); + return this; + }; + + + populateQue(data){ + var categories = data.categories; + var tableData = data.que; + + + for (var x of categories) { + var quePanel = this.que[x] + if (tableData[x][0]) { + var queData = tableData[x][0]; + quePanel.due.innerText = "Due Date: " + ` ${queData.due.getMonth() +1}/${queData.due.getDate()}`; + quePanel.subject.innerText = `${queData.subject}`; + quePanel.todo.innerText = `${queData.todo}`; + quePanel.details.innerText = `${queData.details}`; + quePanel.points.innerText = `${queData.points}`; + quePanel.multiplier.innerText = `x${data.checkMultiplier(queData.due)}`; + }; + }; + }; + + /** + * Function populates the scoreboard with the + * score stored in the model.sb.score object + * passed in from the controller object + * + * NEEDS REFACTORED TO USE LOOPS + */ + populateSB(score) { + this.scoreboard.monday.points.innerText = score.Monday.Points; + this.scoreboard.tuesday.points.innerText = score.Tuesday.Points; + this.scoreboard.wednesday.points.innerText = score.Wednesday.Points; + this.scoreboard.thursday.points.innerText = score.Thursday.Points; + this.scoreboard.friday.points.innerText = score.Friday.Points; + this.scoreboard.saturday.points.innerText = score.Saturday.Points; + this.scoreboard.sunday.points.innerText = score.Sunday.Points; + this.scoreboard.total.points.innerText = score.Total.Points; + this.scoreboard.historic.points.innerText = score['Historic Total'].Points; + + this.scoreboard.monday.lastWeek.innerText = score.Monday['Last Week']; + this.scoreboard.tuesday.lastWeek.innerText = score.Tuesday['Last Week']; + this.scoreboard.wednesday.lastWeek.innerText = score.Wednesday['Last Week']; + this.scoreboard.thursday.lastWeek.innerText = score.Thursday['Last Week']; + this.scoreboard.friday.lastWeek.innerText = score.Friday['Last Week']; + this.scoreboard.saturday.lastWeek.innerText = score.Saturday['Last Week']; + this.scoreboard.sunday.lastWeek.innerText = score.Sunday['Last Week']; + this.scoreboard.total.lastWeek.innerText = score.Total['Last Week']; + this.scoreboard.historic.lastWeek.innerText = score['Historic Total']['Last Week']; + + this.scoreboard.monday.historic.innerText = score.Monday['Historic High']; + this.scoreboard.tuesday.historic.innerText = score.Tuesday['Historic High']; + this.scoreboard.wednesday.historic.innerText = score.Wednesday['Historic High']; + this.scoreboard.thursday.historic.innerText = score.Thursday['Historic High']; + this.scoreboard.friday.historic.innerText = score.Friday['Historic High']; + this.scoreboard.saturday.historic.innerText = score.Saturday['Historic High']; + this.scoreboard.sunday.historic.innerText = score.Sunday['Historic High']; + this.scoreboard.total.historic.innerText = score.Total['Historic High']; + this.scoreboard.historic.historic.innerText = score['Historic Total']['Historic High']; + + return this; + }; + + cleanQue(category) { + var que = this.que[category]; + + que.due.innerText = "Due Date: "; + que.subject.innerText = ``; + que.todo.innerText = `Nothing`; + que.details.innerText = `None`; + que.points.innerText = `0`; + que.multiplier.innerText = `x1`; + }; + + + + /** + * Function instantiates selectors for the que + * and stores their reference in the view.que object + * + * NEEDS REFACTORED TO USE LOOPS + */ + queSelectors() { + this.que.Homework = {}; + this.que.Homework.id = document.getElementById('homework-que'); + this.que.Homework.due = document.querySelector('#homework-que .que-due'); + this.que.Homework.todo = document.querySelector('#homework-que .que-todo'); + this.que.Homework.subject = document.querySelector('#homework-que .que-subject'); + this.que.Homework.delete = document.querySelector('#homework-que .delete'); + this.que.Homework.complete = document.querySelector('#homework-que .complete'); + this.que.Homework.details = document.querySelector('#homework-que .que-details'); + this.que.Homework.points = document.querySelector('#homework-que .points'); + this.que.Homework.multiplier = document.querySelector('#homework-que .que-multiplier'); + + this.que.Projects = {}; + this.que.Projects.id = document.getElementById('project-que'); + this.que.Projects.due = document.querySelector('#project-que .que-due'); + this.que.Projects.todo = document.querySelector('#project-que .que-todo'); + this.que.Projects.subject = document.querySelector('#project-que .que-subject'); + this.que.Projects.delete = document.querySelector('#project-que .delete'); + this.que.Projects.complete = document.querySelector('#project-que .complete'); + this.que.Projects.details = document.querySelector('#project-que .que-details'); + this.que.Projects.points = document.querySelector('#project-que .points'); + this.que.Projects.multiplier = document.querySelector('#project-que .que-multiplier'); + + this.que.Reading = {}; + this.que.Reading.id = document.getElementById('reading-que'); + this.que.Reading.due = document.querySelector('#reading-que .que-due'); + this.que.Reading.todo = document.querySelector('#reading-que .que-todo'); + this.que.Reading.subject = document.querySelector('#reading-que .que-subject'); + this.que.Reading.delete = document.querySelector('#reading-que .delete'); + this.que.Reading.complete = document.querySelector('#reading-que .complete'); + this.que.Reading.details = document.querySelector('#reading-que .que-details'); + this.que.Reading.points = document.querySelector('#reading-que .points'); + this.que.Reading.multiplier = document.querySelector('#reading-que .que-multiplier'); + + this.que.Tests = {}; + this.que.Tests.id = document.getElementById('test-que'); + this.que.Tests.due = document.querySelector('#test-que .que-due'); + this.que.Tests.todo = document.querySelector('#test-que .que-todo'); + this.que.Tests.subject = document.querySelector('#test-que .que-subject'); + this.que.Tests.delete = document.querySelector('#test-que .delete'); + this.que.Tests.complete = document.querySelector('#test-que .complete'); + this.que.Tests.details = document.querySelector('#test-que .que-details'); + this.que.Tests.points = document.querySelector('#test-que .points'); + this.que.Tests.multiplier = document.querySelector('#test-que .que-multiplier'); + + this.que.Videos = {}; + this.que.Videos.id = document.getElementById('video-que'); + this.que.Videos.due = document.querySelector('#video-que .que-due'); + this.que.Videos.todo = document.querySelector('#video-que .que-todo'); + this.que.Videos.subject = document.querySelector('#video-que .que-subject'); + this.que.Videos.delete = document.querySelector('#video-que .delete'); + this.que.Videos.complete = document.querySelector('#video-que .complete'); + this.que.Videos.details = document.querySelector('#video-que .que-details'); + this.que.Videos.points = document.querySelector('#video-que .points'); + this.que.Videos.multiplier = document.querySelector('#video-que .que-multiplier'); + + return this; + }; + + + /** + * Function instantiates selectors for the scoreboard + * and stores their reference in the view.scoreboard object + * + * NEEDS REFACTORED TO USE LOOPS + */ + sbSelectors() { + this.scoreboard.monday = {}; + this.scoreboard.tuesday = {}; + this.scoreboard.wednesday = {}; + this.scoreboard.thursday = {}; + this.scoreboard.friday = {}; + this.scoreboard.saturday = {}; + this.scoreboard.sunday = {}; + this.scoreboard.total = {}; + this.scoreboard.historic = {}; + + this.scoreboard.monday.id = document.querySelector('#monday'); + this.scoreboard.tuesday.id = document.querySelector('#tuesday'); + this.scoreboard.wednesday.id = document.querySelector('#wednesday'); + this.scoreboard.thursday.id = document.querySelector('#thursday'); + this.scoreboard.friday.id = document.querySelector('#friday'); + this.scoreboard.saturday.id = document.querySelector('#saturday'); + this.scoreboard.sunday.id = document.querySelector('#sunday'); + this.scoreboard.total.id = document.querySelector('#totals_row'); + this.scoreboard.historic.id = document.querySelector('#totals_historic_row'); + + this.scoreboard.monday.points = document.querySelector('#monday .points'); + this.scoreboard.tuesday.points = document.querySelector('#tuesday .points'); + this.scoreboard.wednesday.points = document.querySelector('#wednesday .points'); + this.scoreboard.thursday.points = document.querySelector('#thursday .points'); + this.scoreboard.friday.points = document.querySelector('#friday .points'); + this.scoreboard.saturday.points = document.querySelector('#saturday .points'); + this.scoreboard.sunday.points = document.querySelector('#sunday .points'); + this.scoreboard.total.points = document.querySelector('#totals_row .points'); + this.scoreboard.historic.points = document.querySelector('#totals_historic_row .points'); + + this.scoreboard.monday.lastWeek = document.querySelector('#monday .totals_prev'); + this.scoreboard.tuesday.lastWeek = document.querySelector('#tuesday .totals_prev'); + this.scoreboard.wednesday.lastWeek = document.querySelector('#wednesday .totals_prev'); + this.scoreboard.thursday.lastWeek = document.querySelector('#thursday .totals_prev'); + this.scoreboard.friday.lastWeek = document.querySelector('#friday .totals_prev'); + this.scoreboard.saturday.lastWeek = document.querySelector('#saturday .totals_prev'); + this.scoreboard.sunday.lastWeek = document.querySelector('#sunday .totals_prev'); + this.scoreboard.total.lastWeek = document.querySelector('#totals_row .totals_prev'); + this.scoreboard.historic.lastWeek = document.querySelector('#totals_historic_row .totals_prev'); + + this.scoreboard.monday.historic = document.querySelector('#monday .totals_historic_column'); + this.scoreboard.tuesday.historic = document.querySelector('#tuesday .totals_historic_column'); + this.scoreboard.wednesday.historic = document.querySelector('#wednesday .totals_historic_column'); + this.scoreboard.thursday.historic = document.querySelector('#thursday .totals_historic_column'); + this.scoreboard.friday.historic = document.querySelector('#friday .totals_historic_column'); + this.scoreboard.saturday.historic = document.querySelector('#saturday .totals_historic_column'); + this.scoreboard.sunday.historic = document.querySelector('#sunday .totals_historic_column'); + this.scoreboard.total.historic = document.querySelector('#totals_row .totals_historic_column'); + this.scoreboard.historic.historic = document.querySelector('#totals_historic_row .totals_historic_column'); + + return this; + }; + + + /** + * function instantiates selectors for newly created + * dom elements for the controller to access + */ + categorySelectors() { + this.subjectSelector = document.getElementById('subject-list'); + this.categorySelector = document.getElementById('category-list'); + this.todoSelector = document.getElementById("category-input"); + this.detailSelector = document.getElementById('category-details'); + this.dueSelector = document.getElementById('category-due'); + this.pointSelector = document.getElementById('points-dropdown'); + return this; + }; +}; + + + + + +/** + * Class controls all user interactions and + * is composed of a model and view object + * sends user interface manipulations to + * the view object + * sends data interactions to the model object + */ +class Controller { + constructor(model, view) { + this.model = model; + this.view = view; + this.needed = {}; + this.needed.ran = 0; + if (localStorage.key(1)==null) { + this.watcher(); + } else { + this.restoreState(); + }; + }; + + + /** + * Function initializes event listeners + */ + watcher() { + this.controlListener(); + return this; + }; + + saveState() { + return this; + }; + + + restoreState() { + return this; + }; + + clearState() { + localStorage.clear() + return this; + }; + + + /** + * function controls the event listener attached to the submit button + * for the Add New Subject area of the Subject Control Panel + */ + controlListener() { + this.view.createSubject.children[1].addEventListener('click', (event) => { + var subjects = this.model.subjects; + var value = this.view.createSubject.children[0].value; + if (!(subjects.some((x) => x == value)) && value != '') { + subjects.push(value); + this.model.subjectFactory(subjects[subjects.length - 1]) + } else { + this.view.createSubject.children[0].value = ''; + }; + console.log("The subjects array:",subjects); + this.view.subjectList(subjects); + this.subjectListener(); + }); + return this; + }; + + + /** + * Function adds an event listener to the Subject Control Panel + * after its body has been instantiated + */ + subjectListener() { + if (this.needed.ran > 0) { + return this; + }; + if (this.view.subjectCategories && this.needed.ran === 0) { + this.needed.ran = 1; + this.view.subjectCategories.addEventListener('click', (event) => { + if (this.needed.ran < 2) { + this.view.categorySelectors(); + this.needed.ran = 2; + }; + if(!this.view.checkToDoInput()) { + return this; + } + + var parsedDate = Date.parse(this.view.dueSelector.value); + var date = new Date(parsedDate+21600000); + + this.model.data[this.view.subjectSelector.value][this.view.categorySelector.value].push({ + subject: this.view.subjectSelector.value, + todo: this.view.todoSelector.value, + details: this.view.detailSelector.value, + due: date, + points: this.view.pointSelector.value + }); + console.log(this.model.data[this.view.subjectSelector.value][this.view.categorySelector.value]) + this.model.queBuilder(this.view.subjectSelector.value, this.view.categorySelector.value); + + if (this.view.needed.que == 0) { + this.view.needed.que = 1; + this.model.categories.forEach((x) => { + this.view.constructQue(x); + }); + this.view.constructScoreboard(); + this.view.populateSB(this.model.sb.score); + this.view.populateQue(this.model) + this.queListener(); + + } else if (this.view.needed.que == 1) { + this.view.populateSB(this.model.sb.score); + this.view.populateQue(this.model) + }; + }); + }; + return this; + }; + + + + queListener() { + var categories = this.model.categories; + + categories.forEach((x) => { + var deleteButton = this.view.que[x].delete + var completeButton = this.view.que[x].complete + deleteButton.addEventListener('click', (event) => { + this.model.queHandler(x, 'delete'); + this.view.cleanQue(x); + this.view.populateQue(this.model); + }); + completeButton.addEventListener('click', (event) => { + this.model.queHandler(x, 'complete'); + this.view.cleanQue(x); + this.view.populateSB(this.model.sb.score); + this.view.populateQue(this.model); + }); + }); + + return this; + }; + +}; + + + + + +/** + * IIFE Function initializes a controller composed with + * a model and a view object + */ +;(function() { + const app = new Controller(new Model, new View); +}()); \ No newline at end of file diff --git a/backup/public/mvcbackup.js b/backup/public/mvcbackup.js new file mode 100644 index 0000000..36c2d50 --- /dev/null +++ b/backup/public/mvcbackup.js @@ -0,0 +1,677 @@ +/* +************************************************************************** +Assignment: Project 2 - Planner App +Author: James Halladay +Advanced Programming with JavaScript +Date: 3/30/2020 + + +************************************************************************** + +I wanted to build a model view controller to get a better understanding of + the design pattern. I had once tried to use Django for python, which uses + the model-template-view pattern, and was completely lost and overwhelmed. + Since the MTV pattern is descended from the MVC, and the MVC seems to be + a pervasive pattern in the industry so I went about building one instead + of a MTV. + +The project itself is a planner that adds todo items organized first by custom + subjects and then by individual todo categories. The user allocates points + to give weight to larger todo items. When a Todo item is completed, the + points are added to a score that is maintained by the Model Class. The + scoreboard displays totals for points earned both daily and weekly, going + back 1 week. It also shows the users historic high scores. + +The point system allows users to quantitatively measure their productivity in a + meaningful way, and provides the user with motivation in a game-like fashion. + A user may strive to cram in as many items as possible to exceed previous + scores. + +There are 3 classes in this file as well as one IIFE that serves to initialize + the classes. + +The Model Class is composed of the Scoreboard class created in the scoreboard.js + file and controls the data for the planner app. + +The View Class imports templates from function stored in the templates.js file + and controls all changes to the appearance of Planner App through HTML + modifications. + +The Controller Class is composed of the Model and View Classes and facilitates + all interactions between the user and the program + + +I Think I accomplished most of my goals, but Initially I had planned for the app + to use server side storage so I could use this for school. The mvc.js itself + needs refactored to use more loops because of the huge blocks of code that + creates HTML selectors are both not aesthetic and just bad code. + +I had some problems getting local storage built in after building the app. It seems + that I need to refactor the Controller Class methods in order to have the app + restart with all the Panels active. + +I also need to create a set of methods for the Model Class to fetch old data from + the server and send data to the server. I would like to do this because it + would allow me to rely on the data being present in the case of a browser + update that clears the cache or some other incident that results in the + browser data being unrecoverable. + +************************************************************************** +*/ + +import {Scoreboard} from "./scoreboard.js"; +import {template, queTemplate} from "./templates.js"; + +'use strict' + + +/** + * Class stores all of the data for the planner app + * contains methods for manipulating the data + * using the scoreboard object in its composition + * located in ./scoreboard.js + */ +class Model{ + constructor() { + this.sb = new Scoreboard; + this.subjects = []; + this.categories = ['Homework', 'Projects', 'Reading', 'Tests', 'Videos']; + this.data ={}; + this.que = {Homework: [], Projects: [], Reading: [], Tests: [], Videos: []}; + this.completedQue = {Homework: [], Projects: [], Reading: [], Tests: [], Videos: []}; + this.deletedQue = {Homework: [], Projects: [], Reading: [], Tests: [], Videos: []}; + }; + + + /** + * function creates a new set of arrays inside the + * data object to represent a new subject + */ + subjectFactory(subject) { + return this.data[subject] = { + Homework: [], + Projects: [], + Reading: [], + Tests: [], + Videos: [] + }; + }; + + + /** + * Function adds new todo item to the Ques and + * sorts them by due date + */ + queBuilder(subject, category) { + var incoming = this.data[subject][category]; + var newItem = incoming[incoming.length - 1]; + var section = this.que[category]; + section.push(newItem); + section.sort((a, b) => { + if (a['due'] < b['due']) { + return -1; + } else if (a['due'] > b['due']) { + return 1; + } else { + return 0; + }; + }); + console.log(section); + return this; + }; + + + /** + * function gives a point multiplier that + * depends on how soon the todo item is due + */ + checkMultiplier(dueDate) { + var today = Date.parse(new Date); + var item = Date.parse(dueDate); + var difference = (item - today)/3600000; + if (difference < 6) { + return 2; + } else if (difference < 12) { + return 1.5; + } else { + return 1; + }; + }; + + + queHandler(category, action) { + var data = this.que[category].shift(); + if (action == 'delete') { + console.log("deleted") + this.deletedQue[category].push(data); + + } else if (action == 'complete') { + this.completedQue[category].push(data); + var points = parseInt(data.points) * this.checkMultiplier(data.due); + this.sb.setPoints(points); + console.table(this.sb.score) + }; + } + + +}; + + + + + +/** + * Class controls all user interface manipulations + * instantiates selectors for the controller to access + * and passes data from the UI to the controller + */ +class View { + constructor() { + this.que = {}; + this.needed = {}; + this.scoreboard = {}; + this.createSubject = document.querySelector('#create-subject'); + this.subjectControl = document.querySelector('#control'); + this.subjectCategories = document.querySelector('#add-items') || ''; + this.scoreboard.id = document.getElementById('score'); + this.que.id = document.getElementById('que-list'); + this.needed.due = 0; + this.needed.que = 0; + }; + + + /** + * Function constructs the subject list drop down and appends an option for + * each subject created by the user + */ + subjectList(subjects) { + var displayArea = document.getElementById('subject-subcategories') + if (subjects.length == 0) { + while (displayArea.firstChild) { + displayArea.removeChild(displayArea.firstChild) + }; + return this; + } else if (!(document.getElementById('subject-list'))) { + if (!document.getElementById('subject-list-label')) { + var label = document.createElement('label'); + label.innerText = "Subject: "; + label.htmlFor = 'subjects'; + label.id = 'subject-list-label'; + displayArea.append(label); + }; + + var list = document.createElement('select'); + list.name = "subjects"; + list.id = 'subject-list'; + displayArea.append(list); + } else { + var list = document.getElementById('subject-list'); + }; + + while (list.firstChild) { + list.removeChild(list.firstChild); + }; + + subjects.forEach((x)=>{ + var option = document.createElement("option"); + option.textContent = x; + option.value = x; + option.className = x; + list.append(option); + }); + + this.createSubjectItems() + this.subjectCategories = document.querySelector('#add-items') + return this; + }; + + + /** + * function creates input fields to add items to + * the que under their subjects and categories + */ + createSubjectItems() { + if (document.getElementById('subject-list') && !document.getElementById('add-items')) { + var displayArea = document.getElementById('subject-subcategories'); + + var newDiv = document.createElement('div'); + newDiv.className = "subcategories"; + newDiv.innerHTML = template('subject-panel'); + newDiv.id = 'addToDo'; + displayArea.append(newDiv); + this.subjectToDo = document.getElementById('addToDo') + + var button = document.createElement('button'); + button.id = "add-items"; + button.textContent = 'Submit'; + displayArea.append(button); + }; + this.categorySelectors(); + return this; + }; + + + /** + * function checks to make sure the input fields on the subject panel + * have been properly entered. If not appends a message to guide the + * user to the bottom of the panel + */ + checkToDoInput() { + var parsedDate = Date.parse(this.dueSelector.value); + if (isNaN(parsedDate) || this.todoSelector.value == '') { + if (this.needed.due == 0) { + var needDue = document.createElement("p"); + needDue.innerText = 'Item and Due Date are required to create new Todo'; + this.subjectToDo.append(needDue); + this.needed.due = 1; + }; + return false; + } else if (this.needed.due == 1) { + this.needed.due = 0; + this.subjectToDo.removeChild(this.subjectToDo.lastChild); + }; + return true; + }; + + + /** + * function constructs each categories cell in the que interface + * using the queTemplate from ./templates.js + */ + constructQue(category) { + var newQue = document.createElement('div'); + newQue.id = 'que'; + newQue.innerHTML = queTemplate(category); + this.que.id.append(newQue); + this.queSelectors(); + return this; + }; + + + /** + * Function creates the scoreboard interface using + * the scoreboard template from ./template.js + */ + constructScoreboard() { + var sb = document.createElement('div'); + sb.id = "scoreboard"; + sb.innerHTML = template('scoreboard'); + this.scoreboard.id.append(sb); + this.sbSelectors(); + return this; + }; + + + populateQue(data){ + var categories = data.categories; + var tableData = data.que; + + + for (var x of categories) { + var quePanel = this.que[x] + if (tableData[x][0]) { + var queData = tableData[x][0]; + quePanel.due.innerText = "Due Date: " + ` ${queData.due.getMonth() +1}/${queData.due.getDate()}`; + quePanel.subject.innerText = `${queData.subject}`; + quePanel.todo.innerText = `${queData.todo}`; + quePanel.details.innerText = `${queData.details}`; + quePanel.points.innerText = `${queData.points}`; + quePanel.multiplier.innerText = `x${data.checkMultiplier(queData.due)}`; + }; + }; + }; + + /** + * Function populates the scoreboard with the + * score stored in the model.sb.score object + * passed in from the controller object + * + * NEEDS REFACTORED TO USE LOOPS + */ + populateSB(score) { + this.scoreboard.monday.points.innerText = score.Monday.Points; + this.scoreboard.tuesday.points.innerText = score.Tuesday.Points; + this.scoreboard.wednesday.points.innerText = score.Wednesday.Points; + this.scoreboard.thursday.points.innerText = score.Thursday.Points; + this.scoreboard.friday.points.innerText = score.Friday.Points; + this.scoreboard.saturday.points.innerText = score.Saturday.Points; + this.scoreboard.sunday.points.innerText = score.Sunday.Points; + this.scoreboard.total.points.innerText = score.Total.Points; + this.scoreboard.historic.points.innerText = score['Historic Total'].Points; + + this.scoreboard.monday.lastWeek.innerText = score.Monday['Last Week']; + this.scoreboard.tuesday.lastWeek.innerText = score.Tuesday['Last Week']; + this.scoreboard.wednesday.lastWeek.innerText = score.Wednesday['Last Week']; + this.scoreboard.thursday.lastWeek.innerText = score.Thursday['Last Week']; + this.scoreboard.friday.lastWeek.innerText = score.Friday['Last Week']; + this.scoreboard.saturday.lastWeek.innerText = score.Saturday['Last Week']; + this.scoreboard.sunday.lastWeek.innerText = score.Sunday['Last Week']; + this.scoreboard.total.lastWeek.innerText = score.Total['Last Week']; + this.scoreboard.historic.lastWeek.innerText = score['Historic Total']['Last Week']; + + this.scoreboard.monday.historic.innerText = score.Monday['Historic High']; + this.scoreboard.tuesday.historic.innerText = score.Tuesday['Historic High']; + this.scoreboard.wednesday.historic.innerText = score.Wednesday['Historic High']; + this.scoreboard.thursday.historic.innerText = score.Thursday['Historic High']; + this.scoreboard.friday.historic.innerText = score.Friday['Historic High']; + this.scoreboard.saturday.historic.innerText = score.Saturday['Historic High']; + this.scoreboard.sunday.historic.innerText = score.Sunday['Historic High']; + this.scoreboard.total.historic.innerText = score.Total['Historic High']; + this.scoreboard.historic.historic.innerText = score['Historic Total']['Historic High']; + + return this; + }; + + cleanQue(category) { + var que = this.que[category]; + + que.due.innerText = "Due Date: "; + que.subject.innerText = ``; + que.todo.innerText = `Nothing`; + que.details.innerText = `None`; + que.points.innerText = `0`; + que.multiplier.innerText = `x1`; + }; + + + + /** + * Function instantiates selectors for the que + * and stores their reference in the view.que object + * + * NEEDS REFACTORED TO USE LOOPS + */ + queSelectors() { + this.que.Homework = {}; + this.que.Homework.id = document.getElementById('homework-que'); + this.que.Homework.due = document.querySelector('#homework-que .que-due'); + this.que.Homework.todo = document.querySelector('#homework-que .que-todo'); + this.que.Homework.subject = document.querySelector('#homework-que .que-subject'); + this.que.Homework.delete = document.querySelector('#homework-que .delete'); + this.que.Homework.complete = document.querySelector('#homework-que .complete'); + this.que.Homework.details = document.querySelector('#homework-que .que-details'); + this.que.Homework.points = document.querySelector('#homework-que .points'); + this.que.Homework.multiplier = document.querySelector('#homework-que .que-multiplier'); + + this.que.Projects = {}; + this.que.Projects.id = document.getElementById('project-que'); + this.que.Projects.due = document.querySelector('#project-que .que-due'); + this.que.Projects.todo = document.querySelector('#project-que .que-todo'); + this.que.Projects.subject = document.querySelector('#project-que .que-subject'); + this.que.Projects.delete = document.querySelector('#project-que .delete'); + this.que.Projects.complete = document.querySelector('#project-que .complete'); + this.que.Projects.details = document.querySelector('#project-que .que-details'); + this.que.Projects.points = document.querySelector('#project-que .points'); + this.que.Projects.multiplier = document.querySelector('#project-que .que-multiplier'); + + this.que.Reading = {}; + this.que.Reading.id = document.getElementById('reading-que'); + this.que.Reading.due = document.querySelector('#reading-que .que-due'); + this.que.Reading.todo = document.querySelector('#reading-que .que-todo'); + this.que.Reading.subject = document.querySelector('#reading-que .que-subject'); + this.que.Reading.delete = document.querySelector('#reading-que .delete'); + this.que.Reading.complete = document.querySelector('#reading-que .complete'); + this.que.Reading.details = document.querySelector('#reading-que .que-details'); + this.que.Reading.points = document.querySelector('#reading-que .points'); + this.que.Reading.multiplier = document.querySelector('#reading-que .que-multiplier'); + + this.que.Tests = {}; + this.que.Tests.id = document.getElementById('test-que'); + this.que.Tests.due = document.querySelector('#test-que .que-due'); + this.que.Tests.todo = document.querySelector('#test-que .que-todo'); + this.que.Tests.subject = document.querySelector('#test-que .que-subject'); + this.que.Tests.delete = document.querySelector('#test-que .delete'); + this.que.Tests.complete = document.querySelector('#test-que .complete'); + this.que.Tests.details = document.querySelector('#test-que .que-details'); + this.que.Tests.points = document.querySelector('#test-que .points'); + this.que.Tests.multiplier = document.querySelector('#test-que .que-multiplier'); + + this.que.Videos = {}; + this.que.Videos.id = document.getElementById('video-que'); + this.que.Videos.due = document.querySelector('#video-que .que-due'); + this.que.Videos.todo = document.querySelector('#video-que .que-todo'); + this.que.Videos.subject = document.querySelector('#video-que .que-subject'); + this.que.Videos.delete = document.querySelector('#video-que .delete'); + this.que.Videos.complete = document.querySelector('#video-que .complete'); + this.que.Videos.details = document.querySelector('#video-que .que-details'); + this.que.Videos.points = document.querySelector('#video-que .points'); + this.que.Videos.multiplier = document.querySelector('#video-que .que-multiplier'); + + return this; + }; + + + /** + * Function instantiates selectors for the scoreboard + * and stores their reference in the view.scoreboard object + * + * NEEDS REFACTORED TO USE LOOPS + */ + sbSelectors() { + this.scoreboard.monday = {}; + this.scoreboard.tuesday = {}; + this.scoreboard.wednesday = {}; + this.scoreboard.thursday = {}; + this.scoreboard.friday = {}; + this.scoreboard.saturday = {}; + this.scoreboard.sunday = {}; + this.scoreboard.total = {}; + this.scoreboard.historic = {}; + + this.scoreboard.monday.id = document.querySelector('#monday'); + this.scoreboard.tuesday.id = document.querySelector('#tuesday'); + this.scoreboard.wednesday.id = document.querySelector('#wednesday'); + this.scoreboard.thursday.id = document.querySelector('#thursday'); + this.scoreboard.friday.id = document.querySelector('#friday'); + this.scoreboard.saturday.id = document.querySelector('#saturday'); + this.scoreboard.sunday.id = document.querySelector('#sunday'); + this.scoreboard.total.id = document.querySelector('#totals_row'); + this.scoreboard.historic.id = document.querySelector('#totals_historic_row'); + + this.scoreboard.monday.points = document.querySelector('#monday .points'); + this.scoreboard.tuesday.points = document.querySelector('#tuesday .points'); + this.scoreboard.wednesday.points = document.querySelector('#wednesday .points'); + this.scoreboard.thursday.points = document.querySelector('#thursday .points'); + this.scoreboard.friday.points = document.querySelector('#friday .points'); + this.scoreboard.saturday.points = document.querySelector('#saturday .points'); + this.scoreboard.sunday.points = document.querySelector('#sunday .points'); + this.scoreboard.total.points = document.querySelector('#totals_row .points'); + this.scoreboard.historic.points = document.querySelector('#totals_historic_row .points'); + + this.scoreboard.monday.lastWeek = document.querySelector('#monday .totals_prev'); + this.scoreboard.tuesday.lastWeek = document.querySelector('#tuesday .totals_prev'); + this.scoreboard.wednesday.lastWeek = document.querySelector('#wednesday .totals_prev'); + this.scoreboard.thursday.lastWeek = document.querySelector('#thursday .totals_prev'); + this.scoreboard.friday.lastWeek = document.querySelector('#friday .totals_prev'); + this.scoreboard.saturday.lastWeek = document.querySelector('#saturday .totals_prev'); + this.scoreboard.sunday.lastWeek = document.querySelector('#sunday .totals_prev'); + this.scoreboard.total.lastWeek = document.querySelector('#totals_row .totals_prev'); + this.scoreboard.historic.lastWeek = document.querySelector('#totals_historic_row .totals_prev'); + + this.scoreboard.monday.historic = document.querySelector('#monday .totals_historic_column'); + this.scoreboard.tuesday.historic = document.querySelector('#tuesday .totals_historic_column'); + this.scoreboard.wednesday.historic = document.querySelector('#wednesday .totals_historic_column'); + this.scoreboard.thursday.historic = document.querySelector('#thursday .totals_historic_column'); + this.scoreboard.friday.historic = document.querySelector('#friday .totals_historic_column'); + this.scoreboard.saturday.historic = document.querySelector('#saturday .totals_historic_column'); + this.scoreboard.sunday.historic = document.querySelector('#sunday .totals_historic_column'); + this.scoreboard.total.historic = document.querySelector('#totals_row .totals_historic_column'); + this.scoreboard.historic.historic = document.querySelector('#totals_historic_row .totals_historic_column'); + + return this; + }; + + + /** + * function instantiates selectors for newly created + * dom elements for the controller to access + */ + categorySelectors() { + this.subjectSelector = document.getElementById('subject-list'); + this.categorySelector = document.getElementById('category-list'); + this.todoSelector = document.getElementById("category-input"); + this.detailSelector = document.getElementById('category-details'); + this.dueSelector = document.getElementById('category-due'); + this.pointSelector = document.getElementById('points-dropdown'); + return this; + }; +}; + + + + + +/** + * Class controls all user interactions and + * is composed of a model and view object + * sends user interface manipulations to + * the view object + * sends data interactions to the model object + */ +class Controller { + constructor(model, view) { + this.model = model; + this.view = view; + this.needed = {}; + this.needed.ran = 0; + if (localStorage.key(1)==null) { + this.watcher(); + } else { + this.restoreState(); + }; + }; + + + /** + * Function initializes event listeners + */ + watcher() { + this.controlListener(); + return this; + }; + + saveState() { + return this; + }; + + + restoreState() { + return this; + }; + + clearState() { + localStorage.clear() + return this; + }; + + + /** + * function controls the event listener attached to the submit button + * for the Add New Subject area of the Subject Control Panel + */ + controlListener() { + this.view.createSubject.children[1].addEventListener('click', (event) => { + var subjects = this.model.subjects; + var value = this.view.createSubject.children[0].value; + if (!(subjects.some((x) => x == value)) && value != '') { + subjects.push(value); + this.model.subjectFactory(subjects[subjects.length - 1]) + } else { + this.view.createSubject.children[0].value = ''; + }; + console.log("The subjects array:",subjects); + this.view.subjectList(subjects); + this.subjectListener(); + }); + return this; + }; + + + /** + * Function adds an event listener to the Subject Control Panel + * after its body has been instantiated + */ + subjectListener() { + if (this.needed.ran > 0) { + return this; + }; + if (this.view.subjectCategories && this.needed.ran === 0) { + this.needed.ran = 1; + this.view.subjectCategories.addEventListener('click', (event) => { + if (this.needed.ran < 2) { + this.view.categorySelectors(); + this.needed.ran = 2; + }; + if(!this.view.checkToDoInput()) { + return this; + } + + var parsedDate = Date.parse(this.view.dueSelector.value); + var date = new Date(parsedDate+21600000); + + this.model.data[this.view.subjectSelector.value][this.view.categorySelector.value].push({ + subject: this.view.subjectSelector.value, + todo: this.view.todoSelector.value, + details: this.view.detailSelector.value, + due: date, + points: this.view.pointSelector.value + }); + console.log(this.model.data[this.view.subjectSelector.value][this.view.categorySelector.value]) + this.model.queBuilder(this.view.subjectSelector.value, this.view.categorySelector.value); + + if (this.view.needed.que == 0) { + this.view.needed.que = 1; + this.model.categories.forEach((x) => { + this.view.constructQue(x); + }); + this.view.constructScoreboard(); + this.view.populateSB(this.model.sb.score); + this.view.populateQue(this.model) + this.queListener(); + + } else if (this.view.needed.que == 1) { + this.view.populateSB(this.model.sb.score); + this.view.populateQue(this.model) + }; + }); + }; + return this; + }; + + + + queListener() { + var categories = this.model.categories; + + categories.forEach((x) => { + var deleteButton = this.view.que[x].delete + var completeButton = this.view.que[x].complete + deleteButton.addEventListener('click', (event) => { + this.model.queHandler(x, 'delete'); + this.view.cleanQue(x); + this.view.populateQue(this.model); + }); + completeButton.addEventListener('click', (event) => { + this.model.queHandler(x, 'complete'); + this.view.cleanQue(x); + this.view.populateSB(this.model.sb.score); + this.view.populateQue(this.model); + }); + }); + + return this; + }; + +}; + + + + + +/** + * IIFE Function initializes a controller composed with + * a model and a view object + */ +;(function() { + const app = new Controller(new Model, new View); +}()); \ No newline at end of file diff --git a/src/public/planner.html b/backup/public/planner.html similarity index 100% rename from src/public/planner.html rename to backup/public/planner.html diff --git a/src/public/javascript/scoreboard.js b/backup/public/scoreboard.js similarity index 100% rename from src/public/javascript/scoreboard.js rename to backup/public/scoreboard.js diff --git a/src/public/states/state2.html b/backup/public/states/state2.html similarity index 100% rename from src/public/states/state2.html rename to backup/public/states/state2.html diff --git a/src/public/states/state3.html b/backup/public/states/state3.html similarity index 100% rename from src/public/states/state3.html rename to backup/public/states/state3.html diff --git a/src/public/javascript/templates.js b/backup/public/templates.js similarity index 100% rename from src/public/javascript/templates.js rename to backup/public/templates.js diff --git a/src/public/test.html b/backup/public/test.html similarity index 100% rename from src/public/test.html rename to backup/public/test.html diff --git a/src/public/css/main.css b/src/public/css/main.css index 79f0a24..36cf5ef 100644 --- a/src/public/css/main.css +++ b/src/public/css/main.css @@ -20,7 +20,9 @@ rgb(156, 95, 61) subdued orange .navIn { padding:.5rem; - background-color: #31465a; + /* background-color: #31465a; */ + background-color: #323232; + } .navIn p { @@ -44,19 +46,35 @@ header { #background { padding-top: 1rem; - background-color: #360f0f; + /* background-color: #360f0f; */ + /* background-color:lightseagreen; */ + background-color: #31465a; + color: #dddddd; } body { - background-color: #323232; + /* background-color: #323232; */ + + background-color: #31465a; + } button { - border: solid 1pt rgb(255, 130, 62); - background-color: rgb(255, 130, 62); + /* border: solid 1pt rgb(255, 130, 62); */ + border: solid 1pt seagreen; + /* background-color: rgb(255, 130, 62); */ + background-color:lightseagreen; + color: #323232; + border-radius: 8px; +} + +button:hover { + border: solid 1pt green; + background-color:lightgreen; color: #323232; border-radius: 8px; + } diff --git a/src/public/css/reset.css b/src/public/css/reset.css new file mode 100644 index 0000000..fef3425 --- /dev/null +++ b/src/public/css/reset.css @@ -0,0 +1,108 @@ + + +html, body, div, span, h1, h2, h3, h4, h5, h6, p, .container { + margin: 0; + margin-left: 0; + margin-right: 0; + padding: 0; + border: 0; + font-size: 100%; + font: serif; + vertical-align: baseline; +} + +:focus { + outline: 0; +} + +body { + line-height: 1; +} + +ol, ul { + list-style: none; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +textarea { + overflow: auto; + vertical-align: top; + resize: vertical; +} + +html { + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +a:focus { + outline: thin dotted; +} + +a:active, a:hover { + outline: 0; +} + +img { + border: 0; +} + +figure { + margin: 0; +} + +form { + margin: 0; +} + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +legend { + border: 0; + padding: 0; + white-space: normal; + *margin-left: -7px; +} + +button, +input, +select, +textarea { + font-size: 100%; + margin: 0; + vertical-align: baseline; + *vertical-align: middle; +} + +textarea { + overflow: auto; + vertical-align: top; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +html, button, input, select, textarea { + color: #222; +} + +img { + vertical-align: middle; +} + +fieldset { + border: 0; + margin: 0; + padding: 0; +} \ No newline at end of file diff --git a/src/public/javascript/app.js b/src/public/javascript/app.js deleted file mode 100644 index e69de29..0000000 diff --git a/src/public/javascript/controller.js b/src/public/javascript/controller.js deleted file mode 100644 index e69de29..0000000 diff --git a/src/public/javascript/controller/controller.js b/src/public/javascript/controller/controller.js index 3c01626..137b88c 100644 --- a/src/public/javascript/controller/controller.js +++ b/src/public/javascript/controller/controller.js @@ -10,138 +10,18 @@ */ class Controller { constructor(model, view) { - this.model = model; - this.view = view; - this.needed = {}; - this.needed.ran = 0; + + // Get state from local storage if (localStorage.key(1)==null) { - this.watcher(); + this.state = 0; + localStorage.setItem('planner_state', 0) } else { - this.restoreState(); + this.state = localStorage.getItem('planner_state') }; - }; - - - /** - * Function initializes event listeners - */ - watcher() { - this.controlListener(); - return this; - }; - - saveState() { - return this; - }; - - - restoreState() { - return this; - }; - - clearState() { - localStorage.clear() - return this; - }; - - - /** - * function controls the event listener attached to the submit button - * for the Add New Subject area of the Subject Control Panel - */ - controlListener() { - this.view.createSubject.children[1].addEventListener('click', (event) => { - var subjects = this.model.subjects; - var value = this.view.createSubject.children[0].value; - if (!(subjects.some((x) => x == value)) && value != '') { - subjects.push(value); - this.model.subjectFactory(subjects[subjects.length - 1]) - } else { - this.view.createSubject.children[0].value = ''; - }; - console.log("The subjects array:",subjects); - this.view.subjectList(subjects); - this.subjectListener(); - }); return this; }; - /** - * Function adds an event listener to the Subject Control Panel - * after its body has been instantiated - */ - subjectListener() { - if (this.needed.ran > 0) { - return this; - }; - if (this.view.subjectCategories && this.needed.ran === 0) { - this.needed.ran = 1; - this.view.subjectCategories.addEventListener('click', (event) => { - if (this.needed.ran < 2) { - this.view.categorySelectors(); - this.needed.ran = 2; - }; - if(!this.view.checkToDoInput()) { - return this; - } - - var parsedDate = Date.parse(this.view.dueSelector.value); - var date = new Date(parsedDate+21600000); - - this.model.data[this.view.subjectSelector.value][this.view.categorySelector.value].push({ - subject: this.view.subjectSelector.value, - todo: this.view.todoSelector.value, - details: this.view.detailSelector.value, - due: date, - points: this.view.pointSelector.value - }); - console.log(this.model.data[this.view.subjectSelector.value][this.view.categorySelector.value]) - this.model.queBuilder(this.view.subjectSelector.value, this.view.categorySelector.value); - - if (this.view.needed.que == 0) { - this.view.needed.que = 1; - this.model.categories.forEach((x) => { - this.view.constructQue(x); - }); - this.view.constructScoreboard(); - this.view.populateSB(this.model.sb.score); - this.view.populateQue(this.model) - this.queListener(); - - } else if (this.view.needed.que == 1) { - this.view.populateSB(this.model.sb.score); - this.view.populateQue(this.model) - }; - }); - }; - return this; - }; - - - - queListener() { - var categories = this.model.categories; - - categories.forEach((x) => { - var deleteButton = this.view.que[x].delete - var completeButton = this.view.que[x].complete - deleteButton.addEventListener('click', (event) => { - this.model.queHandler(x, 'delete'); - this.view.cleanQue(x); - this.view.populateQue(this.model); - }); - completeButton.addEventListener('click', (event) => { - this.model.queHandler(x, 'complete'); - this.view.cleanQue(x); - this.view.populateSB(this.model.sb.score); - this.view.populateQue(this.model); - }); - }); - - return this; - }; - }; diff --git a/src/public/javascript/models/model.js b/src/public/javascript/models/model.js index c0f5a20..f00bd61 100644 --- a/src/public/javascript/models/model.js +++ b/src/public/javascript/models/model.js @@ -1,6 +1,6 @@ -import {Scoreboard} from "./models/scoreboard.js"; -import {template, queTemplate} from "./views/templates.js"; +import {Scoreboard} from "./scoreboard.js"; +import {Queue} from "./queue.js"; 'use strict' @@ -13,15 +13,38 @@ import {template, queTemplate} from "./views/templates.js"; */ class Model{ constructor() { - this.sb = new Scoreboard; - this.subjects = []; + if (localStorage.key(1)==null) { + this.sb = new Scoreboard; + this.Q = new Queue; + this.deletedQ = new Queue; + this.completedQ = new Queue; + this.subjects = []; + this.data ={}; + + this.storeLocally(); + } else { + this.sb = new Scoreboard(localStorage.getItem('score')); + this.Q = new Queue(localStorage.getItem('queue')); + this.deletedQ = new Queue(localStorage.getItem('deleted_queue')); + this.completedQ = new Queue(localStorage.getItem('completed_queue')); + this.subjects = (localStorage.getItem('subjects')) + this.data =(localStorage.getItem('data')) + } this.categories = ['Homework', 'Projects', 'Reading', 'Tests', 'Videos']; - this.data ={}; - this.que = {Homework: [], Projects: [], Reading: [], Tests: [], Videos: []}; - this.completedQue = {Homework: [], Projects: [], Reading: [], Tests: [], Videos: []}; - this.deletedQue = {Homework: [], Projects: [], Reading: [], Tests: [], Videos: []}; + }; + storeLocally() { + localStorage.setItem('score', this.sb.score) + localStorage.setItem('queue', this.Q.queue) + localStorage.setItem('deleted_queue', this.deletedQ.queue) + localStorage.setItem('completed_queue', this.completedQ.queue) + localStorage.setItem('subjects', this.subjects) + localStorage.setItem('data', this.data) + + return this; + } + /** * function creates a new set of arrays inside the @@ -38,62 +61,25 @@ class Model{ }; - /** - * Function adds new todo item to the Ques and - * sorts them by due date - */ - queBuilder(subject, category) { - var incoming = this.data[subject][category]; - var newItem = incoming[incoming.length - 1]; - var section = this.que[category]; - section.push(newItem); - section.sort((a, b) => { - if (a['due'] < b['due']) { - return -1; - } else if (a['due'] > b['due']) { - return 1; - } else { - return 0; - }; - }); - console.log(section); - return this; - }; - - /** * function gives a point multiplier that * depends on how soon the todo item is due */ checkMultiplier(dueDate) { + var output = dueDate === ''? 0: 1; + if (output = 0) { + return output + }; var today = Date.parse(new Date); var item = Date.parse(dueDate); var difference = (item - today)/3600000; if (difference < 6) { - return 2; + var output = 2; } else if (difference < 12) { - return 1.5; - } else { - return 1; + var output = 1.5; }; + return output; }; - - - queHandler(category, action) { - var data = this.que[category].shift(); - if (action == 'delete') { - console.log("deleted") - this.deletedQue[category].push(data); - - } else if (action == 'complete') { - this.completedQue[category].push(data); - var points = parseInt(data.points) * this.checkMultiplier(data.due); - this.sb.setPoints(points); - console.table(this.sb.score); - }; - } - - }; diff --git a/src/public/javascript/models/scoreboard.js b/src/public/javascript/models/scoreboard.js index 54401f7..c6abb83 100644 --- a/src/public/javascript/models/scoreboard.js +++ b/src/public/javascript/models/scoreboard.js @@ -8,6 +8,7 @@ Date: 3/30/2020 */ 'use strict' + export {Scoreboard} /** diff --git a/src/public/javascript/mvc.js b/src/public/javascript/mvc.js index 5f5d2df..e69de29 100644 --- a/src/public/javascript/mvc.js +++ b/src/public/javascript/mvc.js @@ -1,680 +0,0 @@ -/* -************************************************************************** -Assignment: Project 2 - Planner App -Author: James Halladay -Advanced Programming with JavaScript -Date: 3/30/2020 - - -************************************************************************** - -I wanted to build a model view controller to get a better understanding of - the design pattern. I had once tried to use Django for python, which uses - the model-template-view pattern, and was completely lost and overwhelmed. - Since the MTV pattern is descended from the MVC, and the MVC seems to be - a pervasive pattern in the industry so I went about building one instead - of a MTV. - -The project itself is a planner that adds todo items organized first by custom - subjects and then by individual todo categories. The user allocates points - to give weight to larger todo items. When a Todo item is completed, the - points are added to a score that is maintained by the Model Class. The - scoreboard displays totals for points earned both daily and weekly, going - back 1 week. It also shows the users historic high scores. - -The point system allows users to quantitatively measure their productivity in a - meaningful way, and provides the user with motivation in a game-like fashion. - A user may strive to cram in as many items as possible to exceed previous - scores. - -There are 3 classes in this file as well as one IIFE that serves to initialize - the classes. - -The Model Class is composed of the Scoreboard class created in the scoreboard.js - file and controls the data for the planner app. - -The View Class imports templates from function stored in the templates.js file - and controls all changes to the appearance of Planner App through HTML - modifications. - -The Controller Class is composed of the Model and View Classes and facilitates - all interactions between the user and the program - - -I Think I accomplished most of my goals, but Initially I had planned for the app - to use server side storage so I could use this for school. The mvc.js itself - needs refactored to use more loops because of the huge blocks of code that - creates HTML selectors are both not aesthetic and just bad code. - -I had some problems getting local storage built in after building the app. It seems - that I need to refactor the Controller Class methods in order to have the app - restart with all the Panels active. - -I also need to create a set of methods for the Model Class to fetch old data from - the server and send data to the server. I would like to do this because it - would allow me to rely on the data being present in the case of a browser - update that clears the cache or some other incident that results in the - browser data being unrecoverable. - -************************************************************************** -*/ - -import {Scoreboard} from "./models/scoreboard.js"; -import {template, queTemplate} from "./views/templates.js"; - -'use strict' - - -/** - * Class stores all of the data for the planner app - * contains methods for manipulating the data - * using the scoreboard object in its composition - * located in ./scoreboard.js - */ -class Model{ - constructor() { - this.sb = new Scoreboard; - this.subjects = []; - this.categories = ['Homework', 'Projects', 'Reading', 'Tests', 'Videos']; - this.data ={}; - this.que = {Homework: [], Projects: [], Reading: [], Tests: [], Videos: []}; - this.completedQue = {Homework: [], Projects: [], Reading: [], Tests: [], Videos: []}; - this.deletedQue = {Homework: [], Projects: [], Reading: [], Tests: [], Videos: []}; - }; - - - /** - * function creates a new set of arrays inside the - * data object to represent a new subject - */ - subjectFactory(subject) { - return this.data[subject] = { - Homework: [], - Projects: [], - Reading: [], - Tests: [], - Videos: [] - }; - }; - - - /** - * Function adds new todo item to the Ques and - * sorts them by due date - */ - queBuilder(subject, category) { - var incoming = this.data[subject][category]; - var newItem = incoming[incoming.length - 1]; - var section = this.que[category]; - section.push(newItem); - section.sort((a, b) => { - if (a['due'] < b['due']) { - return -1; - } else if (a['due'] > b['due']) { - return 1; - } else { - return 0; - }; - }); - console.log(section); - console.log("Queue: ",this.que) - return this; - }; - - - /** - * function gives a point multiplier that - * depends on how soon the todo item is due - */ - checkMultiplier(dueDate) { - var output = dueDate === ''? 0: 1; - if (output = 0) { - return output - }; - var today = Date.parse(new Date); - var item = Date.parse(dueDate); - var difference = (item - today)/3600000; - if (difference < 6) { - var output = 2; - } else if (difference < 12) { - var output = 1.5; - }; - }; - - - queHandler(category, action) { - var data = this.que[category].shift(); - if (action == 'delete') { - console.log("deleted") - this.deletedQue[category].push(data); - - } else if (action == 'complete') { - this.completedQue[category].push(data); - var points = parseInt(data.points) * this.checkMultiplier(data.due); - this.sb.setPoints(points); - console.table(this.sb.score); - }; - } - - -}; - - - - - -/** - * Class controls all user interface manipulations - * instantiates selectors for the controller to access - * and passes data from the UI to the controller - */ -class View { - constructor() { - this.que = {}; - this.needed = {}; - this.scoreboard = {}; - this.createSubject = document.querySelector('#create-subject'); - this.subjectControl = document.querySelector('#control'); - this.subjectCategories = document.querySelector('#add-items') || ''; - this.scoreboard.id = document.getElementById('score'); - this.que.id = document.getElementById('que-list'); - this.needed.due = 0; - this.needed.que = 0; - }; - - - /** - * Function constructs the subject list drop down and appends an option for - * each subject created by the user - */ - subjectList(subjects) { - var displayArea = document.getElementById('subject-subcategories') - if (subjects.length == 0) { - while (displayArea.firstChild) { - displayArea.removeChild(displayArea.firstChild) - }; - return this; - } else if (!(document.getElementById('subject-list'))) { - if (!document.getElementById('subject-list-label')) { - var label = document.createElement('label'); - label.innerText = "Subject: "; - label.htmlFor = 'subjects'; - label.id = 'subject-list-label'; - displayArea.append(label); - }; - - var list = document.createElement('select'); - list.name = "subjects"; - list.id = 'subject-list'; - displayArea.append(list); - } else { - var list = document.getElementById('subject-list'); - }; - - while (list.firstChild) { - list.removeChild(list.firstChild); - }; - - subjects.forEach((x)=>{ - var option = document.createElement("option"); - option.textContent = x; - option.value = x; - option.className = x; - list.append(option); - }); - - this.createSubjectItems() - this.subjectCategories = document.querySelector('#add-items') - return this; - }; - - - /** - * function creates input fields to add items to - * the que under their subjects and categories - */ - createSubjectItems() { - if (document.getElementById('subject-list') && !document.getElementById('add-items')) { - var displayArea = document.getElementById('subject-subcategories'); - - var newDiv = document.createElement('div'); - newDiv.className = "subcategories"; - newDiv.innerHTML = template('subject-panel'); - newDiv.id = 'addToDo'; - displayArea.append(newDiv); - this.subjectToDo = document.getElementById('addToDo') - - var button = document.createElement('button'); - button.id = "add-items"; - button.textContent = 'Submit'; - displayArea.append(button); - }; - this.categorySelectors(); - return this; - }; - - - /** - * function checks to make sure the input fields on the subject panel - * have been properly entered. If not appends a message to guide the - * user to the bottom of the panel - */ - checkToDoInput() { - var parsedDate = Date.parse(this.dueSelector.value); - if (isNaN(parsedDate) || this.todoSelector.value == '') { - if (this.needed.due == 0) { - var needDue = document.createElement("p"); - needDue.innerText = 'Item and Due Date are required to create new Todo'; - this.subjectToDo.append(needDue); - this.needed.due = 1; - }; - return false; - } else if (this.needed.due == 1) { - this.needed.due = 0; - this.subjectToDo.removeChild(this.subjectToDo.lastChild); - }; - return true; - }; - - - /** - * function constructs each categories cell in the que interface - * using the queTemplate from ./templates.js - */ - constructQue(category) { - var newQue = document.createElement('div'); - newQue.id = 'que'; - newQue.innerHTML = queTemplate(category); - this.que.id.append(newQue); - this.queSelectors(); - return this; - }; - - - /** - * Function creates the scoreboard interface using - * the scoreboard template from ./template.js - */ - constructScoreboard() { - var sb = document.createElement('div'); - sb.id = "scoreboard"; - sb.innerHTML = template('scoreboard'); - this.scoreboard.id.append(sb); - this.sbSelectors(); - return this; - }; - - - populateQue(data){ - var categories = data.categories; - var tableData = data.que; - - - for (var x of categories) { - var quePanel = this.que[x] - if (tableData[x][0]) { - var queData = tableData[x][0]; - quePanel.due.innerText = "Due Date: " + ` ${queData.due.getMonth() +1}/${queData.due.getDate()}`; - quePanel.subject.innerText = `${queData.subject}`; - quePanel.todo.innerText = `${queData.todo}`; - quePanel.details.innerText = `${queData.details}`; - quePanel.points.innerText = `${queData.points}`; - quePanel.multiplier.innerText = `x${data.checkMultiplier(queData.due)}`; - }; - }; - }; - - /** - * Function populates the scoreboard with the - * score stored in the model.sb.score object - * passed in from the controller object - * - * NEEDS REFACTORED TO USE LOOPS - */ - populateSB(score) { - this.scoreboard.monday.points.innerText = score.Monday.Points; - this.scoreboard.tuesday.points.innerText = score.Tuesday.Points; - this.scoreboard.wednesday.points.innerText = score.Wednesday.Points; - this.scoreboard.thursday.points.innerText = score.Thursday.Points; - this.scoreboard.friday.points.innerText = score.Friday.Points; - this.scoreboard.saturday.points.innerText = score.Saturday.Points; - this.scoreboard.sunday.points.innerText = score.Sunday.Points; - this.scoreboard.total.points.innerText = score.Total.Points; - this.scoreboard.historic.points.innerText = score['Historic Total'].Points; - - this.scoreboard.monday.lastWeek.innerText = score.Monday['Last Week']; - this.scoreboard.tuesday.lastWeek.innerText = score.Tuesday['Last Week']; - this.scoreboard.wednesday.lastWeek.innerText = score.Wednesday['Last Week']; - this.scoreboard.thursday.lastWeek.innerText = score.Thursday['Last Week']; - this.scoreboard.friday.lastWeek.innerText = score.Friday['Last Week']; - this.scoreboard.saturday.lastWeek.innerText = score.Saturday['Last Week']; - this.scoreboard.sunday.lastWeek.innerText = score.Sunday['Last Week']; - this.scoreboard.total.lastWeek.innerText = score.Total['Last Week']; - this.scoreboard.historic.lastWeek.innerText = score['Historic Total']['Last Week']; - - this.scoreboard.monday.historic.innerText = score.Monday['Historic High']; - this.scoreboard.tuesday.historic.innerText = score.Tuesday['Historic High']; - this.scoreboard.wednesday.historic.innerText = score.Wednesday['Historic High']; - this.scoreboard.thursday.historic.innerText = score.Thursday['Historic High']; - this.scoreboard.friday.historic.innerText = score.Friday['Historic High']; - this.scoreboard.saturday.historic.innerText = score.Saturday['Historic High']; - this.scoreboard.sunday.historic.innerText = score.Sunday['Historic High']; - this.scoreboard.total.historic.innerText = score.Total['Historic High']; - this.scoreboard.historic.historic.innerText = score['Historic Total']['Historic High']; - - return this; - }; - - cleanQue(category) { - var que = this.que[category]; - - que.due.innerText = "Due Date: "; - que.subject.innerText = ``; - que.todo.innerText = `Nothing`; - que.details.innerText = `None`; - que.points.innerText = `0`; - que.multiplier.innerText = `x1`; - }; - - - - /** - * Function instantiates selectors for the que - * and stores their reference in the view.que object - * - * NEEDS REFACTORED TO USE LOOPS - */ - queSelectors() { - this.que.Homework = {}; - this.que.Homework.id = document.getElementById('homework-que'); - this.que.Homework.due = document.querySelector('#homework-que .que-due'); - this.que.Homework.todo = document.querySelector('#homework-que .que-todo'); - this.que.Homework.subject = document.querySelector('#homework-que .que-subject'); - this.que.Homework.delete = document.querySelector('#homework-que .delete'); - this.que.Homework.complete = document.querySelector('#homework-que .complete'); - this.que.Homework.details = document.querySelector('#homework-que .que-details'); - this.que.Homework.points = document.querySelector('#homework-que .points'); - this.que.Homework.multiplier = document.querySelector('#homework-que .que-multiplier'); - - this.que.Projects = {}; - this.que.Projects.id = document.getElementById('project-que'); - this.que.Projects.due = document.querySelector('#project-que .que-due'); - this.que.Projects.todo = document.querySelector('#project-que .que-todo'); - this.que.Projects.subject = document.querySelector('#project-que .que-subject'); - this.que.Projects.delete = document.querySelector('#project-que .delete'); - this.que.Projects.complete = document.querySelector('#project-que .complete'); - this.que.Projects.details = document.querySelector('#project-que .que-details'); - this.que.Projects.points = document.querySelector('#project-que .points'); - this.que.Projects.multiplier = document.querySelector('#project-que .que-multiplier'); - - this.que.Reading = {}; - this.que.Reading.id = document.getElementById('reading-que'); - this.que.Reading.due = document.querySelector('#reading-que .que-due'); - this.que.Reading.todo = document.querySelector('#reading-que .que-todo'); - this.que.Reading.subject = document.querySelector('#reading-que .que-subject'); - this.que.Reading.delete = document.querySelector('#reading-que .delete'); - this.que.Reading.complete = document.querySelector('#reading-que .complete'); - this.que.Reading.details = document.querySelector('#reading-que .que-details'); - this.que.Reading.points = document.querySelector('#reading-que .points'); - this.que.Reading.multiplier = document.querySelector('#reading-que .que-multiplier'); - - this.que.Tests = {}; - this.que.Tests.id = document.getElementById('test-que'); - this.que.Tests.due = document.querySelector('#test-que .que-due'); - this.que.Tests.todo = document.querySelector('#test-que .que-todo'); - this.que.Tests.subject = document.querySelector('#test-que .que-subject'); - this.que.Tests.delete = document.querySelector('#test-que .delete'); - this.que.Tests.complete = document.querySelector('#test-que .complete'); - this.que.Tests.details = document.querySelector('#test-que .que-details'); - this.que.Tests.points = document.querySelector('#test-que .points'); - this.que.Tests.multiplier = document.querySelector('#test-que .que-multiplier'); - - this.que.Videos = {}; - this.que.Videos.id = document.getElementById('video-que'); - this.que.Videos.due = document.querySelector('#video-que .que-due'); - this.que.Videos.todo = document.querySelector('#video-que .que-todo'); - this.que.Videos.subject = document.querySelector('#video-que .que-subject'); - this.que.Videos.delete = document.querySelector('#video-que .delete'); - this.que.Videos.complete = document.querySelector('#video-que .complete'); - this.que.Videos.details = document.querySelector('#video-que .que-details'); - this.que.Videos.points = document.querySelector('#video-que .points'); - this.que.Videos.multiplier = document.querySelector('#video-que .que-multiplier'); - - return this; - }; - - - /** - * Function instantiates selectors for the scoreboard - * and stores their reference in the view.scoreboard object - * - * NEEDS REFACTORED TO USE LOOPS - */ - sbSelectors() { - this.scoreboard.monday = {}; - this.scoreboard.tuesday = {}; - this.scoreboard.wednesday = {}; - this.scoreboard.thursday = {}; - this.scoreboard.friday = {}; - this.scoreboard.saturday = {}; - this.scoreboard.sunday = {}; - this.scoreboard.total = {}; - this.scoreboard.historic = {}; - - this.scoreboard.monday.id = document.querySelector('#monday'); - this.scoreboard.tuesday.id = document.querySelector('#tuesday'); - this.scoreboard.wednesday.id = document.querySelector('#wednesday'); - this.scoreboard.thursday.id = document.querySelector('#thursday'); - this.scoreboard.friday.id = document.querySelector('#friday'); - this.scoreboard.saturday.id = document.querySelector('#saturday'); - this.scoreboard.sunday.id = document.querySelector('#sunday'); - this.scoreboard.total.id = document.querySelector('#totals_row'); - this.scoreboard.historic.id = document.querySelector('#totals_historic_row'); - - this.scoreboard.monday.points = document.querySelector('#monday .points'); - this.scoreboard.tuesday.points = document.querySelector('#tuesday .points'); - this.scoreboard.wednesday.points = document.querySelector('#wednesday .points'); - this.scoreboard.thursday.points = document.querySelector('#thursday .points'); - this.scoreboard.friday.points = document.querySelector('#friday .points'); - this.scoreboard.saturday.points = document.querySelector('#saturday .points'); - this.scoreboard.sunday.points = document.querySelector('#sunday .points'); - this.scoreboard.total.points = document.querySelector('#totals_row .points'); - this.scoreboard.historic.points = document.querySelector('#totals_historic_row .points'); - - this.scoreboard.monday.lastWeek = document.querySelector('#monday .totals_prev'); - this.scoreboard.tuesday.lastWeek = document.querySelector('#tuesday .totals_prev'); - this.scoreboard.wednesday.lastWeek = document.querySelector('#wednesday .totals_prev'); - this.scoreboard.thursday.lastWeek = document.querySelector('#thursday .totals_prev'); - this.scoreboard.friday.lastWeek = document.querySelector('#friday .totals_prev'); - this.scoreboard.saturday.lastWeek = document.querySelector('#saturday .totals_prev'); - this.scoreboard.sunday.lastWeek = document.querySelector('#sunday .totals_prev'); - this.scoreboard.total.lastWeek = document.querySelector('#totals_row .totals_prev'); - this.scoreboard.historic.lastWeek = document.querySelector('#totals_historic_row .totals_prev'); - - this.scoreboard.monday.historic = document.querySelector('#monday .totals_historic_column'); - this.scoreboard.tuesday.historic = document.querySelector('#tuesday .totals_historic_column'); - this.scoreboard.wednesday.historic = document.querySelector('#wednesday .totals_historic_column'); - this.scoreboard.thursday.historic = document.querySelector('#thursday .totals_historic_column'); - this.scoreboard.friday.historic = document.querySelector('#friday .totals_historic_column'); - this.scoreboard.saturday.historic = document.querySelector('#saturday .totals_historic_column'); - this.scoreboard.sunday.historic = document.querySelector('#sunday .totals_historic_column'); - this.scoreboard.total.historic = document.querySelector('#totals_row .totals_historic_column'); - this.scoreboard.historic.historic = document.querySelector('#totals_historic_row .totals_historic_column'); - - return this; - }; - - - /** - * function instantiates selectors for newly created - * dom elements for the controller to access - */ - categorySelectors() { - this.subjectSelector = document.getElementById('subject-list'); - this.categorySelector = document.getElementById('category-list'); - this.todoSelector = document.getElementById("category-input"); - this.detailSelector = document.getElementById('category-details'); - this.dueSelector = document.getElementById('category-due'); - this.pointSelector = document.getElementById('points-dropdown'); - return this; - }; -}; - - - - - -/** - * Class controls all user interactions and - * is composed of a model and view object - * sends user interface manipulations to - * the view object - * sends data interactions to the model object - */ -class Controller { - constructor(model, view) { - this.model = model; - this.view = view; - this.needed = {}; - this.needed.ran = 0; - if (localStorage.key(1)==null) { - this.watcher(); - } else { - this.restoreState(); - }; - }; - - - /** - * Function initializes event listeners - */ - watcher() { - this.controlListener(); - return this; - }; - - saveState() { - return this; - }; - - - restoreState() { - return this; - }; - - clearState() { - localStorage.clear() - return this; - }; - - - /** - * function controls the event listener attached to the submit button - * for the Add New Subject area of the Subject Control Panel - */ - controlListener() { - this.view.createSubject.children[1].addEventListener('click', (event) => { - var subjects = this.model.subjects; - var value = this.view.createSubject.children[0].value; - if (!(subjects.some((x) => x == value)) && value != '') { - subjects.push(value); - this.model.subjectFactory(subjects[subjects.length - 1]) - } else { - this.view.createSubject.children[0].value = ''; - }; - console.log("The subjects array:",subjects); - this.view.subjectList(subjects); - this.subjectListener(); - }); - return this; - }; - - - /** - * Function adds an event listener to the Subject Control Panel - * after its body has been instantiated - */ - subjectListener() { - if (this.needed.ran > 0) { - return this; - }; - if (this.view.subjectCategories && this.needed.ran === 0) { - this.needed.ran = 1; - this.view.subjectCategories.addEventListener('click', (event) => { - if (this.needed.ran < 2) { - this.view.categorySelectors(); - this.needed.ran = 2; - }; - if(!this.view.checkToDoInput()) { - return this; - } - - var parsedDate = Date.parse(this.view.dueSelector.value); - var date = new Date(parsedDate+21600000); - - this.model.data[this.view.subjectSelector.value][this.view.categorySelector.value].push({ - subject: this.view.subjectSelector.value, - todo: this.view.todoSelector.value, - details: this.view.detailSelector.value, - due: date, - points: this.view.pointSelector.value - }); - console.log(this.model.data[this.view.subjectSelector.value][this.view.categorySelector.value]) - this.model.queBuilder(this.view.subjectSelector.value, this.view.categorySelector.value); - - if (this.view.needed.que == 0) { - this.view.needed.que = 1; - this.model.categories.forEach((x) => { - this.view.constructQue(x); - }); - this.view.constructScoreboard(); - this.view.populateSB(this.model.sb.score); - this.view.populateQue(this.model) - this.queListener(); - - } else if (this.view.needed.que == 1) { - this.view.populateSB(this.model.sb.score); - this.view.populateQue(this.model) - }; - }); - }; - return this; - }; - - - - queListener() { - var categories = this.model.categories; - - categories.forEach((x) => { - var deleteButton = this.view.que[x].delete - var completeButton = this.view.que[x].complete - deleteButton.addEventListener('click', (event) => { - this.model.queHandler(x, 'delete'); - this.view.cleanQue(x); - this.view.populateQue(this.model); - }); - completeButton.addEventListener('click', (event) => { - this.model.queHandler(x, 'complete'); - this.view.cleanQue(x); - this.view.populateSB(this.model.sb.score); - this.view.populateQue(this.model); - }); - }); - - return this; - }; - -}; - - - - - -/** - * IIFE Function initializes a controller composed with - * a model and a view object - */ -;(function() { - const app = new Controller(new Model, new View); -}()); \ No newline at end of file diff --git a/src/routes/index.js b/src/routes/index.js index 409bae2..b27d604 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -7,7 +7,11 @@ const{ensureAuthenticated}=require('../config/authorize') //welcome page router.get('/',(req,res)=>res.render('welcome', {title: 'Planner'})); +// //quiz page +// router.get('/quiz',ensureAuthenticated,(req,res)=>res.render('quiz',{name:req.user.name, title: 'Planner'})); + //quiz page -router.get('/quiz',ensureAuthenticated,(req,res)=>res.render('quiz',{name:req.user.name, title: 'Planner'})); +router.get('/planner',ensureAuthenticated,(req,res)=>res.render('planner',{name:req.user.name})); + module.exports=router; \ No newline at end of file diff --git a/src/routes/user.js b/src/routes/user.js index 9e3dc35..61d94c5 100644 --- a/src/routes/user.js +++ b/src/routes/user.js @@ -127,7 +127,7 @@ router.post('/register', //handling login router.post('/login',(req,res,next)=>{ passport.authenticate('local',{ - successRedirect:'/quiz', + successRedirect:'/planner', failureRedirect:'/user/login', failureFlash:true })(req,res,next); diff --git a/src/views/layout.ejs b/src/views/layout.ejs index a42c855..d3568a2 100644 --- a/src/views/layout.ejs +++ b/src/views/layout.ejs @@ -2,16 +2,38 @@ - + - quiz app + + + Planner -
+ +
+ +

+
+ +
+
+ <%- body %> +
+ +
+

+ +
diff --git a/src/views/login.ejs b/src/views/login.ejs index 23d3c39..9f68cd9 100644 --- a/src/views/login.ejs +++ b/src/views/login.ejs @@ -4,6 +4,8 @@ margin-left: 300px;}
+
+
<%- include('./partial/message') %>
@@ -27,4 +29,5 @@

Dont have an account?

Register here - \ No newline at end of file + + \ No newline at end of file diff --git a/src/views/planner.ejs b/src/views/planner.ejs index c4eddac..57033e7 100644 --- a/src/views/planner.ejs +++ b/src/views/planner.ejs @@ -1,97 +1,55 @@ - + -
- -

-
+
+ + + +
+
+
-
-
-
-
- -
-
-

Subject Control Panel

-

Add New Subject

-
- - -
-
-
-
-
- -
- -
- - -
- +
+
+
+
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
+
+ +
+
+ + -
-
-
- -
-

- -
- - - +
+ \ No newline at end of file diff --git a/src/views/welcome.ejs b/src/views/welcome.ejs index 628cde6..ff57aa0 100644 --- a/src/views/welcome.ejs +++ b/src/views/welcome.ejs @@ -1,16 +1,4 @@ - -

Welcome to quiz

+

Welcome to your Student Task Planner

Login Register From 6d50c50b74a99191c55435b9ab8e420762e55a0f Mon Sep 17 00:00:00 2001 From: James Halladay Date: Wed, 29 Apr 2020 20:21:41 -0600 Subject: [PATCH 03/17] restructuring files --- src/public/javascript/mvc.js | 0 src/public/javascript/{ => mvc}/controller/controller.js | 0 src/public/javascript/{ => mvc}/models/data_handler.js | 0 src/public/javascript/{ => mvc}/models/journal.js | 0 src/public/javascript/{ => mvc}/models/model.js | 0 src/public/javascript/{ => mvc}/models/queue.js | 0 src/public/javascript/{ => mvc}/models/schedule.js | 0 src/public/javascript/{ => mvc}/models/scoreboard.js | 0 src/public/javascript/{ => mvc}/views/index.js | 0 src/public/javascript/{ => mvc}/views/templates.js | 0 src/public/javascript/{ => mvc}/views/view.js | 0 src/public/javascript/{ => mvc}/views/view_queue.js | 0 src/public/javascript/{ => mvc}/views/view_schedule.js | 0 src/public/javascript/{ => mvc}/views/view_scoreboard.js | 0 src/public/javascript/planner.js | 5 +++++ 15 files changed, 5 insertions(+) delete mode 100644 src/public/javascript/mvc.js rename src/public/javascript/{ => mvc}/controller/controller.js (100%) rename src/public/javascript/{ => mvc}/models/data_handler.js (100%) rename src/public/javascript/{ => mvc}/models/journal.js (100%) rename src/public/javascript/{ => mvc}/models/model.js (100%) rename src/public/javascript/{ => mvc}/models/queue.js (100%) rename src/public/javascript/{ => mvc}/models/schedule.js (100%) rename src/public/javascript/{ => mvc}/models/scoreboard.js (100%) rename src/public/javascript/{ => mvc}/views/index.js (100%) rename src/public/javascript/{ => mvc}/views/templates.js (100%) rename src/public/javascript/{ => mvc}/views/view.js (100%) rename src/public/javascript/{ => mvc}/views/view_queue.js (100%) rename src/public/javascript/{ => mvc}/views/view_schedule.js (100%) rename src/public/javascript/{ => mvc}/views/view_scoreboard.js (100%) create mode 100644 src/public/javascript/planner.js diff --git a/src/public/javascript/mvc.js b/src/public/javascript/mvc.js deleted file mode 100644 index e69de29..0000000 diff --git a/src/public/javascript/controller/controller.js b/src/public/javascript/mvc/controller/controller.js similarity index 100% rename from src/public/javascript/controller/controller.js rename to src/public/javascript/mvc/controller/controller.js diff --git a/src/public/javascript/models/data_handler.js b/src/public/javascript/mvc/models/data_handler.js similarity index 100% rename from src/public/javascript/models/data_handler.js rename to src/public/javascript/mvc/models/data_handler.js diff --git a/src/public/javascript/models/journal.js b/src/public/javascript/mvc/models/journal.js similarity index 100% rename from src/public/javascript/models/journal.js rename to src/public/javascript/mvc/models/journal.js diff --git a/src/public/javascript/models/model.js b/src/public/javascript/mvc/models/model.js similarity index 100% rename from src/public/javascript/models/model.js rename to src/public/javascript/mvc/models/model.js diff --git a/src/public/javascript/models/queue.js b/src/public/javascript/mvc/models/queue.js similarity index 100% rename from src/public/javascript/models/queue.js rename to src/public/javascript/mvc/models/queue.js diff --git a/src/public/javascript/models/schedule.js b/src/public/javascript/mvc/models/schedule.js similarity index 100% rename from src/public/javascript/models/schedule.js rename to src/public/javascript/mvc/models/schedule.js diff --git a/src/public/javascript/models/scoreboard.js b/src/public/javascript/mvc/models/scoreboard.js similarity index 100% rename from src/public/javascript/models/scoreboard.js rename to src/public/javascript/mvc/models/scoreboard.js diff --git a/src/public/javascript/views/index.js b/src/public/javascript/mvc/views/index.js similarity index 100% rename from src/public/javascript/views/index.js rename to src/public/javascript/mvc/views/index.js diff --git a/src/public/javascript/views/templates.js b/src/public/javascript/mvc/views/templates.js similarity index 100% rename from src/public/javascript/views/templates.js rename to src/public/javascript/mvc/views/templates.js diff --git a/src/public/javascript/views/view.js b/src/public/javascript/mvc/views/view.js similarity index 100% rename from src/public/javascript/views/view.js rename to src/public/javascript/mvc/views/view.js diff --git a/src/public/javascript/views/view_queue.js b/src/public/javascript/mvc/views/view_queue.js similarity index 100% rename from src/public/javascript/views/view_queue.js rename to src/public/javascript/mvc/views/view_queue.js diff --git a/src/public/javascript/views/view_schedule.js b/src/public/javascript/mvc/views/view_schedule.js similarity index 100% rename from src/public/javascript/views/view_schedule.js rename to src/public/javascript/mvc/views/view_schedule.js diff --git a/src/public/javascript/views/view_scoreboard.js b/src/public/javascript/mvc/views/view_scoreboard.js similarity index 100% rename from src/public/javascript/views/view_scoreboard.js rename to src/public/javascript/mvc/views/view_scoreboard.js diff --git a/src/public/javascript/planner.js b/src/public/javascript/planner.js new file mode 100644 index 0000000..33d39a2 --- /dev/null +++ b/src/public/javascript/planner.js @@ -0,0 +1,5 @@ +import {Model} from './mvc/models/model.js'; +import {View} from './mvc/views/view.js'; +import {Controller} from './mvc/controller/controller.js'; + +const Planner = new Controller(new Model, new View); \ No newline at end of file From 55ffc7e5cd3005cab99df6f3bd79e0a57d11512f Mon Sep 17 00:00:00 2001 From: James Halladay Date: Thu, 30 Apr 2020 20:53:53 -0600 Subject: [PATCH 04/17] syncing work --- .../public}/mvc/models/data_handler.js | 0 .../public}/mvc/models/journal.js | 0 .../public}/mvc/models/schedule.js | 0 src/public/css/main.css | 75 ++- .../javascript/mvc/controller/controller.js | 153 ++++- src/public/javascript/mvc/models/model.js | 44 +- src/public/javascript/mvc/models/queue.js | 15 +- src/public/javascript/mvc/views/test.html | 68 ++ src/public/javascript/mvc/views/view.js | 586 +++++++++--------- src/public/javascript/package-lock.json | 52 +- src/public/javascript/package.json | 8 +- src/public/javascript/planner.js | 2 +- .../tests/{SBTester.js => tester.js} | 0 src/views/planner.ejs | 62 +- 14 files changed, 655 insertions(+), 410 deletions(-) rename {src/public/javascript => backup/public}/mvc/models/data_handler.js (100%) rename {src/public/javascript => backup/public}/mvc/models/journal.js (100%) rename {src/public/javascript => backup/public}/mvc/models/schedule.js (100%) create mode 100644 src/public/javascript/mvc/views/test.html rename src/public/javascript/tests/{SBTester.js => tester.js} (100%) diff --git a/src/public/javascript/mvc/models/data_handler.js b/backup/public/mvc/models/data_handler.js similarity index 100% rename from src/public/javascript/mvc/models/data_handler.js rename to backup/public/mvc/models/data_handler.js diff --git a/src/public/javascript/mvc/models/journal.js b/backup/public/mvc/models/journal.js similarity index 100% rename from src/public/javascript/mvc/models/journal.js rename to backup/public/mvc/models/journal.js diff --git a/src/public/javascript/mvc/models/schedule.js b/backup/public/mvc/models/schedule.js similarity index 100% rename from src/public/javascript/mvc/models/schedule.js rename to backup/public/mvc/models/schedule.js diff --git a/src/public/css/main.css b/src/public/css/main.css index 36cf5ef..b3b2560 100644 --- a/src/public/css/main.css +++ b/src/public/css/main.css @@ -61,17 +61,19 @@ body { } button { - /* border: solid 1pt rgb(255, 130, 62); */ - border: solid 1pt seagreen; - /* background-color: rgb(255, 130, 62); */ - background-color:lightseagreen; + border: solid 1pt rgb(255, 130, 62); + background-color: rgb(255, 130, 62); color: #323232; border-radius: 8px; + margin-left: .2rem; + margin-right: .2rem; } button:hover { - border: solid 1pt green; - background-color:lightgreen; + border: solid 1pt seagreen; + background-color:lightseagreen; + /* border: solid 1pt green; + background-color:lightgreen; */ color: #323232; border-radius: 8px; @@ -87,6 +89,12 @@ button:hover { font-size: 10pt; line-height: 12pt; padding-bottom: 2rem; + background-color: #360f0f; + + padding: .1rem; + border: 2.5pt solid black; + border-radius: 16px; + } #control-title { @@ -95,16 +103,31 @@ button:hover { background-color: #b94b4f ; border-radius: 4px; width: 40%; + margin-top: 1rem; margin-left: 30%; } +#control-subject-label { + text-align: left; + margin-left: 10%; + margin-top: .2rem; + margin-bottom: .3rem; +} + #create-subject-label { float: left; } #create-subject { - float: right; + text-align: right; + margin-bottom: 1rem; + +} +#subject-submit { + margin-bottom: .5rem; + text-align: right; + } #subject-list-label { @@ -129,20 +152,24 @@ button:hover { } #subject-subcategories { - padding-top: 3rem; + padding-top: 1rem; + margin-left: 1rem; + margin-right: 1rem; } #subject-subcategories button { - float: right; + text-align: right; + + /* float: right; */ } -/* Que */ +/* Queue */ -.que-category { +.queue-category { font-size: 8pt; margin: .2rem; padding: .1rem; @@ -153,7 +180,7 @@ button:hover { line-height: 1; } -.que-category-head { +.queue-category-head { background-color: #b94b4f; padding-left: .5rem; padding-bottom: .6rem; @@ -164,48 +191,48 @@ button:hover { width: 40%; } -.que-head, .que-title { +.queue-head, .que-title { font-size: 10pt; } -.que-line { +.queue-line { display: inline-block; } -.que-todo , .que-todo-title { +.queue-todo , .que-todo-title { width: 35%; } -.que-subject, .que-subject-title { +.queue-subject, .que-subject-title { width: 32%; } -.que-contents { +.queue-contents { font-weight: 300; line-height: .9; font-size: 8pt; } -.que-button-right { +.queue-button-right { /* float: right; margin-right: 5px; */ font-size: 10pt; width: 30%; } -.que-details { +.queue-details { width: 77%; } -.que-points { +.queue-points { width: 10% } -.que-multiplier { +.queue-multiplier { width: 10% } -.que-bar { +.queue-bar { margin: .2rem; padding-bottom: 0.5rem; padding-left: .5rem; @@ -215,12 +242,12 @@ button:hover { background-color: #31465a; } -.que-title { +.queue-title { border-radius: 4px; background-color: #31465a ; } -.que-area { +.queue-area { padding-top: 5px; } diff --git a/src/public/javascript/mvc/controller/controller.js b/src/public/javascript/mvc/controller/controller.js index 137b88c..b967f18 100644 --- a/src/public/javascript/mvc/controller/controller.js +++ b/src/public/javascript/mvc/controller/controller.js @@ -9,19 +9,162 @@ * sends data interactions to the model object */ class Controller { - constructor(model, view) { + constructor(model, view) { + this.model = model; + this.view = view; // Get state from local storage - if (localStorage.key(1)==null) { - this.state = 0; - localStorage.setItem('planner_state', 0) + if (localStorage.getItem('planner_state')==null) { + this.state = 1; } else { - this.state = localStorage.getItem('planner_state') + this.state = localStorage.getItem('planner_state'); }; + this.restoreState(); + + + return this; + }; + + restoreState() { + this.view.bindData(this.model); + this.view.update(this.state); + this.updateListeners(); + + return this; + }; + + storeLocally() { + localStorage.setItem('planner_state', this.state); + }; + + subjectListener(button, fieldElement) { + if (this.subjectButtonListener) { + delete this.subjectButtonListener + }; + + + this.subjectButtonListener = button.addEventListener('click', (event)=>{ + let field = fieldElement.value; + if( + field != '' + && !this.model.subjects.some((x) => x == field) + ) { + console.log('success: subject was created') + this.model.subjectFactory(field) + if(this.state < 2) { + this.state = 2 + this.view.virtualControlPanel(2) + .updateControlPanel(); + this.updateListeners(); + this.toDoListener(this.view.createTodoButton, this.view.createTodo); + + + } else { + this.view.virtualControlPanel() + .updateControlPanel(); + this.updateListeners(); + }; + } else { + + console.log('failure: input was not accepted'); + } + }); + + return this; + }; + + toDoListener(button, fields) { + if(this.toDoButtonListener) { + delete this.toDoButtonListener; + }; + + this.toDoButtonListener = button.addEventListener('click', (event) => { + console.log('hello from todoListener') + if(this.view.checkToDoInput()) { + + var parsedDate = Date.parse(this.view.createTodo.due.value); + var date = new Date(parsedDate+21600000); + var item = { + subject: this.view.createTodo.subject.value, + todo: this.view.createTodo.todo.value, + details: this.view.createTodo.detail.value, + due: date, + points: this.view.createTodo.point.value + }; + + this.model.data[this.view.createTodo.subject.value][this.view.createTodo.category.value].push(item); + this.model.Q.pushTo(this.view.createTodo.category.value, item) + .sort(); + + if(this.state < 3) { + this.state = 3; + this.view.update(3); + this.updateListeners(); + } else { + this.view.virtualQueue() + .updateQueue(); + }; + } else { + console.log("input fields needed to create todo item"); + }; + + }) + return this; }; + updateListeners() { + var state = this.state; + if(state == 1) { + if(this.subjectButtonListener) { + delete this.subjectButtonListener; + }; + this.subjectListener(this.view.createSubjectButton, this.view.newSubjectField); + } else if (state == 2) { + if(this.subjectButtonListener) { + delete this.subjectButtonListener; + }; + + if(this.toDoButtonListener) { + delete this.toDoButtonListener; + }; + + this.subjectListener(this.view.createSubjectButton, this.view.newSubjectField); + this.toDoListener(this.view.createTodoButton, this.view.createTodo); + } else if (state == 3) { + if(this.subjectButtonListener) { + delete this.subjectButtonListener; + }; + + if(this.toDoButtonListener) { + delete this.toDoButtonListener; + }; + + this.subjectListener(this.view.createSubjectButton, this.view.newSubjectField); + this.toDoListener(this.view.createTodoButton, this.view.createTodo); + } else if (state == 4) { + if(this.subjectButtonListener) { + delete this.subjectButtonListener; + }; + + if(this.toDoButtonListener) { + delete this.toDoButtonListener; + }; + + this.subjectListener(this.view.createSubjectButton, this.view.newSubjectField); + this.toDoListener(this.view.createTodoButton, this.view.createTodo); + }; + + return this; + } + + + }; +export {Controller} + + + diff --git a/src/public/javascript/mvc/models/model.js b/src/public/javascript/mvc/models/model.js index f00bd61..3efd4a0 100644 --- a/src/public/javascript/mvc/models/model.js +++ b/src/public/javascript/mvc/models/model.js @@ -13,37 +13,39 @@ import {Queue} from "./queue.js"; */ class Model{ constructor() { - if (localStorage.key(1)==null) { + if (localStorage.getItem('subjects') == null) { this.sb = new Scoreboard; this.Q = new Queue; this.deletedQ = new Queue; this.completedQ = new Queue; this.subjects = []; - this.data ={}; - - this.storeLocally(); + this.data = {}; } else { - this.sb = new Scoreboard(localStorage.getItem('score')); - this.Q = new Queue(localStorage.getItem('queue')); - this.deletedQ = new Queue(localStorage.getItem('deleted_queue')); - this.completedQ = new Queue(localStorage.getItem('completed_queue')); - this.subjects = (localStorage.getItem('subjects')) - this.data =(localStorage.getItem('data')) + this.sb = new Scoreboard(JSON.parse(localStorage.getItem('score'))) + this.Q = new Queue(JSON.parse(localStorage.getItem('queue'))) + this.deletedQ = new Queue(JSON.parse(localStorage.getItem('deleted_queue'))) + this.completedQ = new Queue(JSON.parse(localStorage.getItem('completed_queue'))) + this.subjects = JSON.parse(localStorage.getItem('subjects')) + this.data = JSON.parse(localStorage.getItem('data')) } this.categories = ['Homework', 'Projects', 'Reading', 'Tests', 'Videos']; + this.storeLocally() + return this; }; storeLocally() { - localStorage.setItem('score', this.sb.score) - localStorage.setItem('queue', this.Q.queue) - localStorage.setItem('deleted_queue', this.deletedQ.queue) - localStorage.setItem('completed_queue', this.completedQ.queue) - localStorage.setItem('subjects', this.subjects) - localStorage.setItem('data', this.data) + localStorage.setItem('score', JSON.stringify(this.sb.score)) + localStorage.setItem('queue', JSON.stringify(this.Q.queue)) + localStorage.setItem('deleted_queue', JSON.stringify(this.deletedQ.queue)) + localStorage.setItem('completed_queue', JSON.stringify(this.completedQ.queue)) + localStorage.setItem('subjects', JSON.stringify(this.subjects)) + localStorage.setItem('data', JSON.stringify(this.data)) return this; - } + }; + + /** @@ -51,13 +53,16 @@ class Model{ * data object to represent a new subject */ subjectFactory(subject) { - return this.data[subject] = { + this.subjects.push(subject) + this.data[subject] = { Homework: [], Projects: [], Reading: [], Tests: [], Videos: [] }; + + return this; }; @@ -83,3 +88,6 @@ class Model{ }; + + +export {Model} \ No newline at end of file diff --git a/src/public/javascript/mvc/models/queue.js b/src/public/javascript/mvc/models/queue.js index 0a8299f..862b730 100644 --- a/src/public/javascript/mvc/models/queue.js +++ b/src/public/javascript/mvc/models/queue.js @@ -2,7 +2,7 @@ export {Queue}; - + class Queue { constructor(queue) { this.queue = queue || {Homework: [], Projects: [], Reading: [], Tests: [], Videos: []}; @@ -17,16 +17,23 @@ class Queue { return this; }; + activeCategories() { + return this.categories.filter((x)=> this.queue[x][0] !== undefined); + + } + currentItems() { - var upNext = this.categories.map((x)=>{ - return this.queue[x][0]; - }); + console.log('state of the queue', this.queue) + var upNext = this.categories.filter((x)=> this.queue[x][0] !== undefined) + .map((y) => this.queue[y][0]); + console.log('state of the queue after filter', upNext) return upNext; }; pushTo(category, item) { + console.log('from queue:: pushTo(category, item):', category, item) if (this.categories.some((x) => x === category)) { this.queue[category].push(item); }; diff --git a/src/public/javascript/mvc/views/test.html b/src/public/javascript/mvc/views/test.html new file mode 100644 index 0000000..fb8afd8 --- /dev/null +++ b/src/public/javascript/mvc/views/test.html @@ -0,0 +1,68 @@ + +
+
+

Subject Control Panel

+

Add New Subject

+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + + +
+
+ +
+
+
\ No newline at end of file diff --git a/src/public/javascript/mvc/views/view.js b/src/public/javascript/mvc/views/view.js index a2ca9ce..c3a8f16 100644 --- a/src/public/javascript/mvc/views/view.js +++ b/src/public/javascript/mvc/views/view.js @@ -1,4 +1,146 @@ +const Comps = { + categories: ['Homework', 'Projects', 'Reading', 'Tests', 'Videos'], + queueIds: {'Homework': 'homework-queue', 'Projects': 'project-queue', 'Reading' : 'reading-queue', 'Tests' : 'test-queue', 'Videos' : 'video-queue'}, + + + Ctr: (...elements) => React.createElement( + 'div', + {'id': 'control', 'key': 'ctr'}, + React.createElement('p', {'id': 'control-title','key': 'ControlTitle'}, "Control Panel"), + React.createElement('p', {'id': 'control-subject-label','key': 'NewSubjectLabel'}, "Add New Subject"), + Comps.CtrSubjectSubmit(), + ...elements, + ), + + CtrSubjectSubmit: () => React.createElement( + 'div', + {'id': 'create-subject','key': 'CreateSubject'}, + React.createElement('input', {type: 'text', name: 'subject', placeholder: 'new subject...', id: 'createSubject', key: 'CreateSubjectField'}), + React.createElement('button', {id: 'create-subject-button', key: 'CreateSubjectButton'}, 'Submit') + ), + + CtrFillSubject: (subjects) => React.createElement( + 'div', + {'id': 'subject-subcategories','key': 'SubjectSubcategories'}, + React.createElement('label', {'htmlFor': 'subjects', id: 'subject-list-label', key: 'SubjectListLabel'}, 'Subject:'), + React.createElement( + 'select', + {name: 'subjects', id: 'subject-list', key: 'SubjectDropDown'}, + subjects.map((x, i) => React.createElement('option', {value: x, className: x, key: 'SubjectOptions'+i}, x)) + ), + Comps.CtrToDoFields(), + React.createElement( + 'div', + {id: 'subject-submit', key: 'EnterToDo'}, + React.createElement('button', {'id': 'add-items','key': 'CreateTodo'}, "Submit") + ) + ), + + CtrToDoFields: () => React.createElement( + 'div', + {className: 'subcategories', id: 'addToDo', key: 'SubcategoriesArea'}, + React.createElement( + 'section', + {key: 'Section1'}, + React.createElement('label', {htmlFor: 'category', id: 'category-list-label', key: 'CategoryListLabel'}, "Category: "), + React.createElement( + 'select', + {name: 'category', id: 'category-list', key: 'CategoryDropDown'}, + Comps.categories.map((x, i) => React.createElement('option', {value: x, key: x + i}, x)) + ) + ), + React.createElement( + 'section', + {key: 'Section2'}, + React.createElement('label', {htmlFor: 'category-input', id: 'category-input-label', key: 'CategoryInputLabel'}, 'To-Do: '), + React.createElement('input', {type: 'text', id: 'category-input', name: 'category-input', placeholder: 'Add item to ToDo list', key: 'InputToDoField'}) + ), + React.createElement( + 'section', + {key: 'Section3'}, + React.createElement('label', {htmlFor: 'category-details', id: 'details-label', key: 'CategoryDetailsLabel'}, 'Details: '), + React.createElement('input', {type: 'text', id: 'category-details', name: 'category-details', placeholder: 'details...', key: 'CategoryDetailsField'}) + ), + React.createElement( + 'section', + {key: 'Section4'}, + React.createElement('label', {htmlFor: 'category-due', id: 'due-label', key: 'CategoryDueLabel'}, 'Due Date: '), + React.createElement('input', {type: 'date', id: 'category-due', name: 'category-due', key: 'CategoryDueField'}) + ), + React.createElement( + 'section', + {key: 'Section5'}, + React.createElement('label', {htmlFor: 'points', id: 'points-label', key: 'CategoryPointsLabel'}, 'Points: '), + React.createElement( + 'select', + {id: 'points-dropdown', name: 'points', key: 'CategoryPointsDropDown'}, + ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'].map((x) => React.createElement('option', {value: x, key: `${x}Point`}, x)) + ) + ) + ), + + QueueArea: (queue, checkMultiplier) => { + var items = queue.activeCategories(); + if (items.length == 0) { + console.log('item length is 0:', items) + return; + }; + return React.createElement( + 'div', + {'key': "queue-container", 'id': 'queue', key: 100*Math.random}, + items.map((x) => { + console.log("from items.map",x, queue.peekAt(x), checkMultiplier(new Date)) + return Comps.QueueSingle(x, queue.peekAt(x), checkMultiplier) + }) + ); + }, + + QueueSingle: (category, queueItem, checkMultiplier) => { + console.log('queueSingle1', category, queueItem) + var dueDate = new Date((queueItem['due'].getDate)? queueItem['due']: Date.parse(queueItem['due'])) + console.log('queueSingle2', category, queueItem, dueDate) + + return React.createElement( + 'div', + {className: 'queue-category', id: Comps.queueIds[category], key: `${category}Queue`}, + React.createElement( + 'section', + {className: 'queue-head', key: `${category}QueueSection1`}, + React.createElement('div', {className: 'queue-line queue-category-head', key: `${category}QueueCategoryLabel`}, category), + React.createElement('div', {className: 'queue-line queue-due', key: `${category}QueueDueDisplay`}, `Due: ${dueDate.getMonth() + 1}/${dueDate.getDate()}`) + ), + React.createElement( + 'div', + {className: 'queue-bar', key: `${category}QueueBar1`}, + React.createElement( + 'section', + {className: 'queue-title', key: `${category}QueueSection2`}, + React.createElement('div', {className: 'queue-line queue-todo-title' , key: `${category}QueueToDoLabel`}, 'To-Do: '), + React.createElement('div', {className: 'queue-line queue-subject-title' , key: `${category}QueueSubjectLabel`}, 'Subject: '), + React.createElement('button', {className: 'queue-line queue-button-right complete' , key: `${category}QueueCompleteButton`}, 'Complete') + ), + React.createElement( + 'section', + {className: 'queue-area queue-contents', key: `${category}QueueSection3`}, + React.createElement('div', {className: "queue-line queue-todo queue-contents" ,key: `${category}QueueToDoItem`}, queueItem['todo']), + React.createElement('div', {className: "queue-line queue-subject queue-contents" ,key: `${category}QueueSubject`}, queueItem['subject']), + React.createElement('button', {className: "queue-line queue-button-right delete" ,key: `${category}QueueDeleteButton`}, 'Delete') + ) + ), + React.createElement( + 'section', + {className: 'queue-bar queue-contents', key: `${category}QueueBar2`}, + React.createElement('div', {className: 'queue-line queue-details queue-contents', key: `${category}QueueDetailsDisplay`}, queueItem['details']), + React.createElement('div', {className: 'queue-line queue-points queue-multiplier queue-contents', key: `${category}QueueMultDisplay`}, `x${checkMultiplier(dueDate)}`), + React.createElement('div', {className: 'queue-line queue-points points queue-contents', key: `${category}QueuePointDisplay`}, queueItem['points']) + ) + ) + }, +}; + + + /** * Class controls all user interface manipulations @@ -7,353 +149,193 @@ */ class View { constructor() { - this.que = {}; - this.needed = {}; - this.scoreboard = {}; - this.createSubject = document.querySelector('#create-subject'); - this.subjectControl = document.querySelector('#control'); - this.subjectCategories = document.querySelector('#add-items') || ''; - this.scoreboard.id = document.getElementById('score'); - this.que.id = document.getElementById('que-list'); - this.needed.due = 0; - this.needed.que = 0; + this.state = 0 + + + this.left = document.getElementById('Left_Panel') + this.middle = document.getElementById('Middle_Panel') + this.right = document.getElementById('Right_Panel') + + return this; }; - /** - * Function constructs the subject list drop down and appends an option for - * each subject created by the user - */ - subjectList(subjects) { - var displayArea = document.getElementById('subject-subcategories') - if (subjects.length == 0) { - while (displayArea.firstChild) { - displayArea.removeChild(displayArea.firstChild) - }; - return this; - } else if (!(document.getElementById('subject-list'))) { - if (!document.getElementById('subject-list-label')) { - var label = document.createElement('label'); - label.innerText = "Subject: "; - label.htmlFor = 'subjects'; - label.id = 'subject-list-label'; - displayArea.append(label); - }; + bindData(model) { + this.model = model; - var list = document.createElement('select'); - list.name = "subjects"; - list.id = 'subject-list'; - displayArea.append(list); - } else { - var list = document.getElementById('subject-list'); + return this; + } + + setPosition() { + console.log('state', this.state) + switch(this.state) { + case 1: + this.controlPosition = this.middle; + this.sbPosition = ''; + this.queuePosition = ''; + break; + case 2: + this.controlPosition = this.middle; + this.sbPosition = ''; + this.queuePosition = ''; + break; + case 3: + console.log('from setPosition, state=', this.state) + this.controlPosition = this.right; + this.sbPosition = this.middle; + this.queuePosition = this.left; + break; + case 4: + this.controlPosition = this.left; + this.sbPosition = this.right; + this.queuePosition = this.middle; + break; }; - while (list.firstChild) { - list.removeChild(list.firstChild); + return this; + }; + + update(state) { + if(this.state !== state) { + this.state = state; + this.renderDOM() }; + }; - subjects.forEach((x)=>{ - var option = document.createElement("option"); - option.textContent = x; - option.value = x; - option.className = x; - list.append(option); - }); - - this.createSubjectItems() - this.subjectCategories = document.querySelector('#add-items') + cleanDOM() { + // this.controlPosition = ''; + // this.queuePosition = ''; + // this.sbPosition = ''; + console.log('Componenet unmounted at left: ', ReactDOM.unmountComponentAtNode(this.left)) + console.log('Componenet unmounted at middle: ', ReactDOM.unmountComponentAtNode(this.middle)) + console.log('Componenet unmounted at right: ', ReactDOM.unmountComponentAtNode(this.right)) return this; }; + renderDOM() { + this.cleanDOM().setPosition(); + this.cleanDOM().setPosition(); + this.virtualControlPanel() + this.virtualQueue() + this.virtualScoreboard() + + if(this.controlPosition !== '') { + console.log('from renderDOM:', this.controlPanel, this.controlPosition) + ReactDOM.render(this.controlPanel, this.controlPosition, ()=>console.log('rendered control panel at: ', this.controlPosition.id)) + this.controlSelectors(); + } else; + + if(this.queuePosition !== '') { + ReactDOM.render(this.queueView, this.queuePosition, ()=>console.log("rendered Que at:", this.queuePosition.id)); + this.queueSelectors(); + }; - /** - * function creates input fields to add items to - * the que under their subjects and categories - */ - createSubjectItems() { - if (document.getElementById('subject-list') && !document.getElementById('add-items')) { - var displayArea = document.getElementById('subject-subcategories'); - - var newDiv = document.createElement('div'); - newDiv.className = "subcategories"; - newDiv.innerHTML = template('subject-panel'); - newDiv.id = 'addToDo'; - displayArea.append(newDiv); - this.subjectToDo = document.getElementById('addToDo') - - var button = document.createElement('button'); - button.id = "add-items"; - button.textContent = 'Submit'; - displayArea.append(button); + if(this.sbPosition !== '') { + ReactDOM.render(this.scoreboardView, this.controlPosition); }; - this.categorySelectors(); + return this; }; - - /** - * function checks to make sure the input fields on the subject panel - * have been properly entered. If not appends a message to guide the - * user to the bottom of the panel - */ - checkToDoInput() { - var parsedDate = Date.parse(this.dueSelector.value); - if (isNaN(parsedDate) || this.todoSelector.value == '') { - if (this.needed.due == 0) { - var needDue = document.createElement("p"); - needDue.innerText = 'Item and Due Date are required to create new Todo'; - this.subjectToDo.append(needDue); - this.needed.due = 1; - }; - return false; - } else if (this.needed.due == 1) { - this.needed.due = 0; - this.subjectToDo.removeChild(this.subjectToDo.lastChild); + virtualControlPanel(state) { + this.state = state || this.state; + console.log("state from virtualControlPanel: ", this.state) + if(this.state < 2){ + this.controlPanel = Comps.Ctr() + } else { + console.log('control panel: ', this.controlPanel) + this.controlPanel = Comps.Ctr(Comps.CtrFillSubject(this.model.subjects)) + console.log('control panel: ', this.controlPanel) + }; - return true; + + return this; }; + virtualQueue() { + if(this.state > 2) { + this.queueView = Comps.QueueArea(this.model.Q, this.model.checkMultiplier) + }; - /** - * function constructs each categories cell in the que interface - * using the queTemplate from ./templates.js - */ - constructQue(category) { - var newQue = document.createElement('div'); - newQue.id = 'que'; - newQue.innerHTML = queTemplate(category); - this.que.id.append(newQue); - this.queSelectors(); return this; }; + virtualScoreboard() { + this.scoreboardView = ''; - /** - * Function creates the scoreboard interface using - * the scoreboard template from ./template.js - */ - constructScoreboard() { - var sb = document.createElement('div'); - sb.id = "scoreboard"; - sb.innerHTML = template('scoreboard'); - this.scoreboard.id.append(sb); - this.sbSelectors(); return this; }; - - populateQue(data){ - var categories = data.categories; - var tableData = data.que; - - - for (var x of categories) { - var quePanel = this.que[x] - if (tableData[x][0]) { - var queData = tableData[x][0]; - quePanel.due.innerText = "Due Date: " + ` ${queData.due.getMonth() +1}/${queData.due.getDate()}`; - quePanel.subject.innerText = `${queData.subject}`; - quePanel.todo.innerText = `${queData.todo}`; - quePanel.details.innerText = `${queData.details}`; - quePanel.points.innerText = `${queData.points}`; - quePanel.multiplier.innerText = `x${data.checkMultiplier(queData.due)}`; - }; + updateControlPanel() { + if(this.controlPosition !== '') { + ReactDOM.render(this.controlPanel, this.controlPosition) + this.controlSelectors(); }; - }; - - /** - * Function populates the scoreboard with the - * score stored in the model.sb.score object - * passed in from the controller object - * - * NEEDS REFACTORED TO USE LOOPS - */ - populateSB(score) { - this.scoreboard.monday.points.innerText = score.Monday.Points; - this.scoreboard.tuesday.points.innerText = score.Tuesday.Points; - this.scoreboard.wednesday.points.innerText = score.Wednesday.Points; - this.scoreboard.thursday.points.innerText = score.Thursday.Points; - this.scoreboard.friday.points.innerText = score.Friday.Points; - this.scoreboard.saturday.points.innerText = score.Saturday.Points; - this.scoreboard.sunday.points.innerText = score.Sunday.Points; - this.scoreboard.total.points.innerText = score.Total.Points; - this.scoreboard.historic.points.innerText = score['Historic Total'].Points; - - this.scoreboard.monday.lastWeek.innerText = score.Monday['Last Week']; - this.scoreboard.tuesday.lastWeek.innerText = score.Tuesday['Last Week']; - this.scoreboard.wednesday.lastWeek.innerText = score.Wednesday['Last Week']; - this.scoreboard.thursday.lastWeek.innerText = score.Thursday['Last Week']; - this.scoreboard.friday.lastWeek.innerText = score.Friday['Last Week']; - this.scoreboard.saturday.lastWeek.innerText = score.Saturday['Last Week']; - this.scoreboard.sunday.lastWeek.innerText = score.Sunday['Last Week']; - this.scoreboard.total.lastWeek.innerText = score.Total['Last Week']; - this.scoreboard.historic.lastWeek.innerText = score['Historic Total']['Last Week']; - - this.scoreboard.monday.historic.innerText = score.Monday['Historic High']; - this.scoreboard.tuesday.historic.innerText = score.Tuesday['Historic High']; - this.scoreboard.wednesday.historic.innerText = score.Wednesday['Historic High']; - this.scoreboard.thursday.historic.innerText = score.Thursday['Historic High']; - this.scoreboard.friday.historic.innerText = score.Friday['Historic High']; - this.scoreboard.saturday.historic.innerText = score.Saturday['Historic High']; - this.scoreboard.sunday.historic.innerText = score.Sunday['Historic High']; - this.scoreboard.total.historic.innerText = score.Total['Historic High']; - this.scoreboard.historic.historic.innerText = score['Historic Total']['Historic High']; return this; }; - cleanQue(category) { - var que = this.que[category]; + updateQueue() { + if(this.queuePosition !== '') { + ReactDOM.render(this.queueView, this.queuePosition) + this.queueSelectors(); + }; - que.due.innerText = "Due Date: "; - que.subject.innerText = ``; - que.todo.innerText = `Nothing`; - que.details.innerText = `None`; - que.points.innerText = `0`; - que.multiplier.innerText = `x1`; + return this; + } + + controlSelectors() { + this.newSubjectField = document.getElementById('createSubject') + this.createSubjectButton = document.getElementById('create-subject-button') + if(this.state > 1) { + this.createTodoButton = document.getElementById('add-items'), + this.createTodo = {}, + + this.createTodo.subject = document.getElementById('subject-list'), + this.createTodo.category = document.getElementById('category-list'), + this.createTodo.todo = document.getElementById("category-input"), + this.createTodo.detail = document.getElementById('category-details'), + this.createTodo.due = document.getElementById('category-due'), + this.createTodo.point = document.getElementById('points-dropdown') + }; + + return this; }; - - - /** - * Function instantiates selectors for the que - * and stores their reference in the view.que object - * - * NEEDS REFACTORED TO USE LOOPS - */ - queSelectors() { - this.que.Homework = {}; - this.que.Homework.id = document.getElementById('homework-que'); - this.que.Homework.due = document.querySelector('#homework-que .que-due'); - this.que.Homework.todo = document.querySelector('#homework-que .que-todo'); - this.que.Homework.subject = document.querySelector('#homework-que .que-subject'); - this.que.Homework.delete = document.querySelector('#homework-que .delete'); - this.que.Homework.complete = document.querySelector('#homework-que .complete'); - this.que.Homework.details = document.querySelector('#homework-que .que-details'); - this.que.Homework.points = document.querySelector('#homework-que .points'); - this.que.Homework.multiplier = document.querySelector('#homework-que .que-multiplier'); - - this.que.Projects = {}; - this.que.Projects.id = document.getElementById('project-que'); - this.que.Projects.due = document.querySelector('#project-que .que-due'); - this.que.Projects.todo = document.querySelector('#project-que .que-todo'); - this.que.Projects.subject = document.querySelector('#project-que .que-subject'); - this.que.Projects.delete = document.querySelector('#project-que .delete'); - this.que.Projects.complete = document.querySelector('#project-que .complete'); - this.que.Projects.details = document.querySelector('#project-que .que-details'); - this.que.Projects.points = document.querySelector('#project-que .points'); - this.que.Projects.multiplier = document.querySelector('#project-que .que-multiplier'); - - this.que.Reading = {}; - this.que.Reading.id = document.getElementById('reading-que'); - this.que.Reading.due = document.querySelector('#reading-que .que-due'); - this.que.Reading.todo = document.querySelector('#reading-que .que-todo'); - this.que.Reading.subject = document.querySelector('#reading-que .que-subject'); - this.que.Reading.delete = document.querySelector('#reading-que .delete'); - this.que.Reading.complete = document.querySelector('#reading-que .complete'); - this.que.Reading.details = document.querySelector('#reading-que .que-details'); - this.que.Reading.points = document.querySelector('#reading-que .points'); - this.que.Reading.multiplier = document.querySelector('#reading-que .que-multiplier'); - - this.que.Tests = {}; - this.que.Tests.id = document.getElementById('test-que'); - this.que.Tests.due = document.querySelector('#test-que .que-due'); - this.que.Tests.todo = document.querySelector('#test-que .que-todo'); - this.que.Tests.subject = document.querySelector('#test-que .que-subject'); - this.que.Tests.delete = document.querySelector('#test-que .delete'); - this.que.Tests.complete = document.querySelector('#test-que .complete'); - this.que.Tests.details = document.querySelector('#test-que .que-details'); - this.que.Tests.points = document.querySelector('#test-que .points'); - this.que.Tests.multiplier = document.querySelector('#test-que .que-multiplier'); - - this.que.Videos = {}; - this.que.Videos.id = document.getElementById('video-que'); - this.que.Videos.due = document.querySelector('#video-que .que-due'); - this.que.Videos.todo = document.querySelector('#video-que .que-todo'); - this.que.Videos.subject = document.querySelector('#video-que .que-subject'); - this.que.Videos.delete = document.querySelector('#video-que .delete'); - this.que.Videos.complete = document.querySelector('#video-que .complete'); - this.que.Videos.details = document.querySelector('#video-que .que-details'); - this.que.Videos.points = document.querySelector('#video-que .points'); - this.que.Videos.multiplier = document.querySelector('#video-que .que-multiplier'); + queueSelectors() { return this; }; + /** - * Function instantiates selectors for the scoreboard - * and stores their reference in the view.scoreboard object - * - * NEEDS REFACTORED TO USE LOOPS + * function checks to make sure the input fields on the subject panel + * have been properly entered. If not appends a message to guide the + * user to the bottom of the panel */ - sbSelectors() { - this.scoreboard.monday = {}; - this.scoreboard.tuesday = {}; - this.scoreboard.wednesday = {}; - this.scoreboard.thursday = {}; - this.scoreboard.friday = {}; - this.scoreboard.saturday = {}; - this.scoreboard.sunday = {}; - this.scoreboard.total = {}; - this.scoreboard.historic = {}; - - this.scoreboard.monday.id = document.querySelector('#monday'); - this.scoreboard.tuesday.id = document.querySelector('#tuesday'); - this.scoreboard.wednesday.id = document.querySelector('#wednesday'); - this.scoreboard.thursday.id = document.querySelector('#thursday'); - this.scoreboard.friday.id = document.querySelector('#friday'); - this.scoreboard.saturday.id = document.querySelector('#saturday'); - this.scoreboard.sunday.id = document.querySelector('#sunday'); - this.scoreboard.total.id = document.querySelector('#totals_row'); - this.scoreboard.historic.id = document.querySelector('#totals_historic_row'); - - this.scoreboard.monday.points = document.querySelector('#monday .points'); - this.scoreboard.tuesday.points = document.querySelector('#tuesday .points'); - this.scoreboard.wednesday.points = document.querySelector('#wednesday .points'); - this.scoreboard.thursday.points = document.querySelector('#thursday .points'); - this.scoreboard.friday.points = document.querySelector('#friday .points'); - this.scoreboard.saturday.points = document.querySelector('#saturday .points'); - this.scoreboard.sunday.points = document.querySelector('#sunday .points'); - this.scoreboard.total.points = document.querySelector('#totals_row .points'); - this.scoreboard.historic.points = document.querySelector('#totals_historic_row .points'); - - this.scoreboard.monday.lastWeek = document.querySelector('#monday .totals_prev'); - this.scoreboard.tuesday.lastWeek = document.querySelector('#tuesday .totals_prev'); - this.scoreboard.wednesday.lastWeek = document.querySelector('#wednesday .totals_prev'); - this.scoreboard.thursday.lastWeek = document.querySelector('#thursday .totals_prev'); - this.scoreboard.friday.lastWeek = document.querySelector('#friday .totals_prev'); - this.scoreboard.saturday.lastWeek = document.querySelector('#saturday .totals_prev'); - this.scoreboard.sunday.lastWeek = document.querySelector('#sunday .totals_prev'); - this.scoreboard.total.lastWeek = document.querySelector('#totals_row .totals_prev'); - this.scoreboard.historic.lastWeek = document.querySelector('#totals_historic_row .totals_prev'); - - this.scoreboard.monday.historic = document.querySelector('#monday .totals_historic_column'); - this.scoreboard.tuesday.historic = document.querySelector('#tuesday .totals_historic_column'); - this.scoreboard.wednesday.historic = document.querySelector('#wednesday .totals_historic_column'); - this.scoreboard.thursday.historic = document.querySelector('#thursday .totals_historic_column'); - this.scoreboard.friday.historic = document.querySelector('#friday .totals_historic_column'); - this.scoreboard.saturday.historic = document.querySelector('#saturday .totals_historic_column'); - this.scoreboard.sunday.historic = document.querySelector('#sunday .totals_historic_column'); - this.scoreboard.total.historic = document.querySelector('#totals_row .totals_historic_column'); - this.scoreboard.historic.historic = document.querySelector('#totals_historic_row .totals_historic_column'); + checkToDoInput() { + var parsedDate = Date.parse(this.createTodo.due.value); + console.log('date: ',parsedDate) + console.log('todays date: ',Date.parse(new Date) < parsedDate) + this.subjectToDo = document.getElementById('addToDo'); + if (isNaN(parsedDate) || this.createTodo.todo.value == '') { + console.log("childeren", this.subjectToDo.children.length); + if(this.subjectToDo.children.length == 5) { + var needDue = document.createElement("p"); + needDue.innerText = 'valid To-Do and Due Date are required to create a new To-Do item'; + this.subjectToDo.append(needDue); + }; - return this; + return false; + } else if(this.subjectToDo.children.length > 5) { + this.subjectToDo.removeChild(this.subjectToDo.lastChild); + }; + return true; }; + - /** - * function instantiates selectors for newly created - * dom elements for the controller to access - */ - categorySelectors() { - this.subjectSelector = document.getElementById('subject-list'); - this.categorySelector = document.getElementById('category-list'); - this.todoSelector = document.getElementById("category-input"); - this.detailSelector = document.getElementById('category-details'); - this.dueSelector = document.getElementById('category-due'); - this.pointSelector = document.getElementById('points-dropdown'); - return this; - }; }; +export {View} \ No newline at end of file diff --git a/src/public/javascript/package-lock.json b/src/public/javascript/package-lock.json index 6d28064..9cd2d36 100644 --- a/src/public/javascript/package-lock.json +++ b/src/public/javascript/package-lock.json @@ -3495,8 +3495,7 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { "version": "3.13.1", @@ -3676,7 +3675,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, "requires": { "js-tokens": "^3.0.0 || ^4.0.0" } @@ -3922,6 +3920,11 @@ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, "object-copy": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", @@ -4274,6 +4277,16 @@ "sisteransi": "^1.0.4" } }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, "psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -4302,11 +4315,31 @@ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, + "react": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz", + "integrity": "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + } + }, + "react-dom": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.13.1.tgz", + "integrity": "sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.19.1" + } + }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "read-pkg": { "version": "5.2.0", @@ -4747,6 +4780,15 @@ "xmlchars": "^2.1.1" } }, + "scheduler": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", + "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", diff --git a/src/public/javascript/package.json b/src/public/javascript/package.json index 0012a0b..63d2642 100644 --- a/src/public/javascript/package.json +++ b/src/public/javascript/package.json @@ -5,8 +5,8 @@ "main": "mvc.js", "type": "module", "scripts": { - "test": "jest", - "test2": "node test.js test" + "start": "jest", + "test": "node /test/tester.js test" }, "author": "James E. Halladay", "license": "MIT", @@ -14,5 +14,9 @@ "@babel/preset-env": "^7.9.5", "babel-jest": "^25.4.0", "jest": "^25.4.0" + }, + "dependencies": { + "react": "^16.13.1", + "react-dom": "^16.13.1" } } diff --git a/src/public/javascript/planner.js b/src/public/javascript/planner.js index 33d39a2..0872a36 100644 --- a/src/public/javascript/planner.js +++ b/src/public/javascript/planner.js @@ -2,4 +2,4 @@ import {Model} from './mvc/models/model.js'; import {View} from './mvc/views/view.js'; import {Controller} from './mvc/controller/controller.js'; -const Planner = new Controller(new Model, new View); \ No newline at end of file +const Planner = new Controller(new Model, new View); diff --git a/src/public/javascript/tests/SBTester.js b/src/public/javascript/tests/tester.js similarity index 100% rename from src/public/javascript/tests/SBTester.js rename to src/public/javascript/tests/tester.js diff --git a/src/views/planner.ejs b/src/views/planner.ejs index 57033e7..be921ce 100644 --- a/src/views/planner.ejs +++ b/src/views/planner.ejs @@ -1,55 +1,19 @@ - -
- - - -
- -
-
- -
-
- -
- -
- - -
- -
-
- - - +
+
+
+ \ No newline at end of file From 177811a0e0fe7133171426a9cb296da7167a9adc Mon Sep 17 00:00:00 2001 From: James Halladay Date: Thu, 30 Apr 2020 22:52:08 -0600 Subject: [PATCH 05/17] got planner working on client side through server template --- backup/plannerbackup.ejs | 83 --- backup/public/admin.html | 53 -- backup/public/mvc/models/data_handler.js | 10 - backup/public/mvc/models/journal.js | 25 - backup/public/mvc/models/schedule.js | 0 backup/public/mvcWorking.js | 681 ------------------ backup/public/planner.html | 97 --- backup/public/states/state2.html | 142 ---- backup/public/states/state3.html | 337 --------- backup/public/test.html | 0 src/public/css/main.css | 87 +-- {backup => src}/public/index.html | 22 - .../public/javascript/mvc.js | 4 + .../javascript/mvc/controller/controller.js | 170 ----- src/public/javascript/mvc/models/model.js | 93 --- src/public/javascript/mvc/models/queue.js | 80 -- .../javascript/mvc/models/scoreboard.js | 229 ------ src/public/javascript/mvc/views/index.js | 361 ---------- src/public/javascript/mvc/views/templates.js | 183 ----- src/public/javascript/mvc/views/test.html | 68 -- src/public/javascript/mvc/views/view.js | 341 --------- src/public/javascript/mvc/views/view_queue.js | 109 --- .../javascript/mvc/views/view_schedule.js | 0 .../javascript/mvc/views/view_scoreboard.js | 114 --- src/public/javascript/planner.js | 5 - .../public/javascript}/scoreboard.js | 1 + .../public/javascript}/templates.js | 1 + src/public/javascript/test.js | 212 ++++++ src/views/layout.ejs | 2 +- src/views/planner.ejs | 47 +- 30 files changed, 274 insertions(+), 3283 deletions(-) delete mode 100644 backup/plannerbackup.ejs delete mode 100644 backup/public/admin.html delete mode 100644 backup/public/mvc/models/data_handler.js delete mode 100644 backup/public/mvc/models/journal.js delete mode 100644 backup/public/mvc/models/schedule.js delete mode 100644 backup/public/mvcWorking.js delete mode 100644 backup/public/planner.html delete mode 100644 backup/public/states/state2.html delete mode 100644 backup/public/states/state3.html delete mode 100644 backup/public/test.html rename {backup => src}/public/index.html (82%) rename backup/public/mvcbackup.js => src/public/javascript/mvc.js (99%) delete mode 100644 src/public/javascript/mvc/controller/controller.js delete mode 100644 src/public/javascript/mvc/models/model.js delete mode 100644 src/public/javascript/mvc/models/queue.js delete mode 100644 src/public/javascript/mvc/models/scoreboard.js delete mode 100644 src/public/javascript/mvc/views/index.js delete mode 100644 src/public/javascript/mvc/views/templates.js delete mode 100644 src/public/javascript/mvc/views/test.html delete mode 100644 src/public/javascript/mvc/views/view.js delete mode 100644 src/public/javascript/mvc/views/view_queue.js delete mode 100644 src/public/javascript/mvc/views/view_schedule.js delete mode 100644 src/public/javascript/mvc/views/view_scoreboard.js delete mode 100644 src/public/javascript/planner.js rename {backup/public => src/public/javascript}/scoreboard.js (99%) rename {backup/public => src/public/javascript}/templates.js (99%) create mode 100644 src/public/javascript/test.js diff --git a/backup/plannerbackup.ejs b/backup/plannerbackup.ejs deleted file mode 100644 index 3607d66..0000000 --- a/backup/plannerbackup.ejs +++ /dev/null @@ -1,83 +0,0 @@ - - -
- - - -
- -
- -

-
- -
-
-
-
- -
-
-

Subject Control Panel

-

Add New Subject

-
- - -
-
-
-
-
- -
- -
- - -
- -
-
- -
-
-
- -
-
-
-
- -
-
-
-
- -
-
- -
- - - -
-
-
- -
-

- -
- - - diff --git a/backup/public/admin.html b/backup/public/admin.html deleted file mode 100644 index 7be2468..0000000 --- a/backup/public/admin.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - Web Template - - - - -
-
- Template -
-

- This is the Header -

-
- - -
-

- This is Main -

-

Lorem, ipsum dolor sit amet consectetur adipisicing elit. Illo temporibus beatae libero, sed in fugiat laudantium dolore vitae, ipsa quia ratione ipsam error consectetur eos, quos aliquam non! Voluptate, libero!

-

Lorem, ipsum dolor sit amet consectetur adipisicing elit. Illo temporibus beatae libero, sed in fugiat laudantium dolore vitae, ipsa quia ratione ipsam error consectetur eos, quos aliquam non! Voluptate, libero!

-

Lorem, ipsum dolor sit amet consectetur adipisicing elit. Illo temporibus beatae libero, sed in fugiat laudantium dolore vitae, ipsa quia ratione ipsam error consectetur eos, quos aliquam non! Voluptate, libero!

-

Lorem, ipsum dolor sit amet consectetur adipisicing elit. Illo temporibus beatae libero, sed in fugiat laudantium dolore vitae, ipsa quia ratione ipsam error consectetur eos, quos aliquam non! Voluptate, libero!

-

Lorem, ipsum dolor sit amet consectetur adipisicing elit. Illo temporibus beatae libero, sed in fugiat laudantium dolore vitae, ipsa quia ratione ipsam error consectetur eos, quos aliquam non! Voluptate, libero!

-

Lorem, ipsum dolor sit amet consectetur adipisicing elit. Illo temporibus beatae libero, sed in fugiat laudantium dolore vitae, ipsa quia ratione ipsam error consectetur eos, quos aliquam non! Voluptate, libero!

-
- -
-

- This is the Footer -

-
- -
-
- - - - - \ No newline at end of file diff --git a/backup/public/mvc/models/data_handler.js b/backup/public/mvc/models/data_handler.js deleted file mode 100644 index ac1db5e..0000000 --- a/backup/public/mvc/models/data_handler.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; - -export {DataHandler}; - -class DataHandler { - constructor() { - - return this; - }; -}; \ No newline at end of file diff --git a/backup/public/mvc/models/journal.js b/backup/public/mvc/models/journal.js deleted file mode 100644 index 87ac983..0000000 --- a/backup/public/mvc/models/journal.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict'; - -export {Journal}; -import { Queue } from './queue.js'; - -class Journal extends Queue { - constructor(queue) { - super(queue); - return this; - }; - - - - -}; - -// console.log('hello world') -// const journal = new Journal({ Homework: [], Projects: [], Reading: ["rtyu"], Tests: ["gfhj"], Videos: ["asdf"] }); -// journal.printQueue() -// var p = console.log; - - -// p(journal.categories) - -// journal.categories.forEach((a) => journal.printCategory(a)) \ No newline at end of file diff --git a/backup/public/mvc/models/schedule.js b/backup/public/mvc/models/schedule.js deleted file mode 100644 index e69de29..0000000 diff --git a/backup/public/mvcWorking.js b/backup/public/mvcWorking.js deleted file mode 100644 index 0b738dc..0000000 --- a/backup/public/mvcWorking.js +++ /dev/null @@ -1,681 +0,0 @@ -/* -************************************************************************** -Assignment: Project 2 - Planner App -Author: James Halladay -Advanced Programming with JavaScript -Date: 3/30/2020 - - -************************************************************************** - -I wanted to build a model view controller to get a better understanding of - the design pattern. I had once tried to use Django for python, which uses - the model-template-view pattern, and was completely lost and overwhelmed. - Since the MTV pattern is descended from the MVC, and the MVC seems to be - a pervasive pattern in the industry so I went about building one instead - of a MTV. - -The project itself is a planner that adds todo items organized first by custom - subjects and then by individual todo categories. The user allocates points - to give weight to larger todo items. When a Todo item is completed, the - points are added to a score that is maintained by the Model Class. The - scoreboard displays totals for points earned both daily and weekly, going - back 1 week. It also shows the users historic high scores. - -The point system allows users to quantitatively measure their productivity in a - meaningful way, and provides the user with motivation in a game-like fashion. - A user may strive to cram in as many items as possible to exceed previous - scores. - -There are 3 classes in this file as well as one IIFE that serves to initialize - the classes. - -The Model Class is composed of the Scoreboard class created in the scoreboard.js - file and controls the data for the planner app. - -The View Class imports templates from function stored in the templates.js file - and controls all changes to the appearance of Planner App through HTML - modifications. - -The Controller Class is composed of the Model and View Classes and facilitates - all interactions between the user and the program - - -I Think I accomplished most of my goals, but Initially I had planned for the app - to use server side storage so I could use this for school. The mvc.js itself - needs refactored to use more loops because of the huge blocks of code that - creates HTML selectors are both not aesthetic and just bad code. - -I had some problems getting local storage built in after building the app. It seems - that I need to refactor the Controller Class methods in order to have the app - restart with all the Panels active. - -I also need to create a set of methods for the Model Class to fetch old data from - the server and send data to the server. I would like to do this because it - would allow me to rely on the data being present in the case of a browser - update that clears the cache or some other incident that results in the - browser data being unrecoverable. - -************************************************************************** -*/ - -import {Scoreboard} from "./models/scoreboard.js"; -import {template, queTemplate} from "./views/templates.js"; - -'use strict' - - -/** - * Class stores all of the data for the planner app - * contains methods for manipulating the data - * using the scoreboard object in its composition - * located in ./scoreboard.js - */ -class Model{ - constructor() { - this.sb = new Scoreboard; - this.subjects = []; - this.categories = ['Homework', 'Projects', 'Reading', 'Tests', 'Videos']; - this.data ={}; - this.que = {Homework: [], Projects: [], Reading: [], Tests: [], Videos: []}; - this.completedQue = {Homework: [], Projects: [], Reading: [], Tests: [], Videos: []}; - this.deletedQue = {Homework: [], Projects: [], Reading: [], Tests: [], Videos: []}; - }; - - - /** - * function creates a new set of arrays inside the - * data object to represent a new subject - */ - subjectFactory(subject) { - return this.data[subject] = { - Homework: [], - Projects: [], - Reading: [], - Tests: [], - Videos: [] - }; - }; - - - /** - * Function adds new todo item to the Ques and - * sorts them by due date - */ - queBuilder(subject, category) { - var incoming = this.data[subject][category]; - var newItem = incoming[incoming.length - 1]; - var section = this.que[category]; - section.push(newItem); - section.sort((a, b) => { - if (a['due'] < b['due']) { - return -1; - } else if (a['due'] > b['due']) { - return 1; - } else { - return 0; - }; - }); - console.log(section); - console.log("Queue: ",this.que) - return this; - }; - - - /** - * function gives a point multiplier that - * depends on how soon the todo item is due - */ - checkMultiplier(dueDate) { - var output = dueDate === ''? 0: 1; - if (output = 0) { - return output - }; - var today = Date.parse(new Date); - var item = Date.parse(dueDate); - var difference = (item - today)/3600000; - if (difference < 6) { - var output = 2; - } else if (difference < 12) { - var output = 1.5; - }; - return output; - }; - - - queHandler(category, action) { - var data = this.que[category].shift(); - if (action == 'delete') { - console.log("deleted") - this.deletedQue[category].push(data); - - } else if (action == 'complete') { - this.completedQue[category].push(data); - var points = parseInt(data.points) * this.checkMultiplier(data.due); - this.sb.setPoints(points); - console.table(this.sb.score); - }; - } - - -}; - - - - - -/** - * Class controls all user interface manipulations - * instantiates selectors for the controller to access - * and passes data from the UI to the controller - */ -class View { - constructor() { - this.que = {}; - this.needed = {}; - this.scoreboard = {}; - this.createSubject = document.querySelector('#create-subject'); - this.subjectControl = document.querySelector('#control'); - this.subjectCategories = document.querySelector('#add-items') || ''; - this.scoreboard.id = document.getElementById('score'); - this.que.id = document.getElementById('que-list'); - this.needed.due = 0; - this.needed.que = 0; - }; - - - /** - * Function constructs the subject list drop down and appends an option for - * each subject created by the user - */ - subjectList(subjects) { - var displayArea = document.getElementById('subject-subcategories') - if (subjects.length == 0) { - while (displayArea.firstChild) { - displayArea.removeChild(displayArea.firstChild) - }; - return this; - } else if (!(document.getElementById('subject-list'))) { - if (!document.getElementById('subject-list-label')) { - var label = document.createElement('label'); - label.innerText = "Subject: "; - label.htmlFor = 'subjects'; - label.id = 'subject-list-label'; - displayArea.append(label); - }; - - var list = document.createElement('select'); - list.name = "subjects"; - list.id = 'subject-list'; - displayArea.append(list); - } else { - var list = document.getElementById('subject-list'); - }; - - while (list.firstChild) { - list.removeChild(list.firstChild); - }; - - subjects.forEach((x)=>{ - var option = document.createElement("option"); - option.textContent = x; - option.value = x; - option.className = x; - list.append(option); - }); - - this.createSubjectItems() - this.subjectCategories = document.querySelector('#add-items') - return this; - }; - - - /** - * function creates input fields to add items to - * the que under their subjects and categories - */ - createSubjectItems() { - if (document.getElementById('subject-list') && !document.getElementById('add-items')) { - var displayArea = document.getElementById('subject-subcategories'); - - var newDiv = document.createElement('div'); - newDiv.className = "subcategories"; - newDiv.innerHTML = template('subject-panel'); - newDiv.id = 'addToDo'; - displayArea.append(newDiv); - this.subjectToDo = document.getElementById('addToDo') - - var button = document.createElement('button'); - button.id = "add-items"; - button.textContent = 'Submit'; - displayArea.append(button); - }; - this.categorySelectors(); - return this; - }; - - - /** - * function checks to make sure the input fields on the subject panel - * have been properly entered. If not appends a message to guide the - * user to the bottom of the panel - */ - checkToDoInput() { - var parsedDate = Date.parse(this.dueSelector.value); - if (isNaN(parsedDate) || this.todoSelector.value == '') { - if (this.needed.due == 0) { - var needDue = document.createElement("p"); - needDue.innerText = 'Item and Due Date are required to create new Todo'; - this.subjectToDo.append(needDue); - this.needed.due = 1; - }; - return false; - } else if (this.needed.due == 1) { - this.needed.due = 0; - this.subjectToDo.removeChild(this.subjectToDo.lastChild); - }; - return true; - }; - - - /** - * function constructs each categories cell in the que interface - * using the queTemplate from ./templates.js - */ - constructQue(category) { - var newQue = document.createElement('div'); - newQue.id = 'que'; - newQue.innerHTML = queTemplate(category); - this.que.id.append(newQue); - this.queSelectors(); - return this; - }; - - - /** - * Function creates the scoreboard interface using - * the scoreboard template from ./template.js - */ - constructScoreboard() { - var sb = document.createElement('div'); - sb.id = "scoreboard"; - sb.innerHTML = template('scoreboard'); - this.scoreboard.id.append(sb); - this.sbSelectors(); - return this; - }; - - - populateQue(data){ - var categories = data.categories; - var tableData = data.que; - - - for (var x of categories) { - var quePanel = this.que[x] - if (tableData[x][0]) { - var queData = tableData[x][0]; - quePanel.due.innerText = "Due Date: " + ` ${queData.due.getMonth() +1}/${queData.due.getDate()}`; - quePanel.subject.innerText = `${queData.subject}`; - quePanel.todo.innerText = `${queData.todo}`; - quePanel.details.innerText = `${queData.details}`; - quePanel.points.innerText = `${queData.points}`; - quePanel.multiplier.innerText = `x${data.checkMultiplier(queData.due)}`; - }; - }; - }; - - /** - * Function populates the scoreboard with the - * score stored in the model.sb.score object - * passed in from the controller object - * - * NEEDS REFACTORED TO USE LOOPS - */ - populateSB(score) { - this.scoreboard.monday.points.innerText = score.Monday.Points; - this.scoreboard.tuesday.points.innerText = score.Tuesday.Points; - this.scoreboard.wednesday.points.innerText = score.Wednesday.Points; - this.scoreboard.thursday.points.innerText = score.Thursday.Points; - this.scoreboard.friday.points.innerText = score.Friday.Points; - this.scoreboard.saturday.points.innerText = score.Saturday.Points; - this.scoreboard.sunday.points.innerText = score.Sunday.Points; - this.scoreboard.total.points.innerText = score.Total.Points; - this.scoreboard.historic.points.innerText = score['Historic Total'].Points; - - this.scoreboard.monday.lastWeek.innerText = score.Monday['Last Week']; - this.scoreboard.tuesday.lastWeek.innerText = score.Tuesday['Last Week']; - this.scoreboard.wednesday.lastWeek.innerText = score.Wednesday['Last Week']; - this.scoreboard.thursday.lastWeek.innerText = score.Thursday['Last Week']; - this.scoreboard.friday.lastWeek.innerText = score.Friday['Last Week']; - this.scoreboard.saturday.lastWeek.innerText = score.Saturday['Last Week']; - this.scoreboard.sunday.lastWeek.innerText = score.Sunday['Last Week']; - this.scoreboard.total.lastWeek.innerText = score.Total['Last Week']; - this.scoreboard.historic.lastWeek.innerText = score['Historic Total']['Last Week']; - - this.scoreboard.monday.historic.innerText = score.Monday['Historic High']; - this.scoreboard.tuesday.historic.innerText = score.Tuesday['Historic High']; - this.scoreboard.wednesday.historic.innerText = score.Wednesday['Historic High']; - this.scoreboard.thursday.historic.innerText = score.Thursday['Historic High']; - this.scoreboard.friday.historic.innerText = score.Friday['Historic High']; - this.scoreboard.saturday.historic.innerText = score.Saturday['Historic High']; - this.scoreboard.sunday.historic.innerText = score.Sunday['Historic High']; - this.scoreboard.total.historic.innerText = score.Total['Historic High']; - this.scoreboard.historic.historic.innerText = score['Historic Total']['Historic High']; - - return this; - }; - - cleanQue(category) { - var que = this.que[category]; - - que.due.innerText = "Due Date: "; - que.subject.innerText = ``; - que.todo.innerText = `Nothing`; - que.details.innerText = `None`; - que.points.innerText = `0`; - que.multiplier.innerText = `x1`; - }; - - - - /** - * Function instantiates selectors for the que - * and stores their reference in the view.que object - * - * NEEDS REFACTORED TO USE LOOPS - */ - queSelectors() { - this.que.Homework = {}; - this.que.Homework.id = document.getElementById('homework-que'); - this.que.Homework.due = document.querySelector('#homework-que .que-due'); - this.que.Homework.todo = document.querySelector('#homework-que .que-todo'); - this.que.Homework.subject = document.querySelector('#homework-que .que-subject'); - this.que.Homework.delete = document.querySelector('#homework-que .delete'); - this.que.Homework.complete = document.querySelector('#homework-que .complete'); - this.que.Homework.details = document.querySelector('#homework-que .que-details'); - this.que.Homework.points = document.querySelector('#homework-que .points'); - this.que.Homework.multiplier = document.querySelector('#homework-que .que-multiplier'); - - this.que.Projects = {}; - this.que.Projects.id = document.getElementById('project-que'); - this.que.Projects.due = document.querySelector('#project-que .que-due'); - this.que.Projects.todo = document.querySelector('#project-que .que-todo'); - this.que.Projects.subject = document.querySelector('#project-que .que-subject'); - this.que.Projects.delete = document.querySelector('#project-que .delete'); - this.que.Projects.complete = document.querySelector('#project-que .complete'); - this.que.Projects.details = document.querySelector('#project-que .que-details'); - this.que.Projects.points = document.querySelector('#project-que .points'); - this.que.Projects.multiplier = document.querySelector('#project-que .que-multiplier'); - - this.que.Reading = {}; - this.que.Reading.id = document.getElementById('reading-que'); - this.que.Reading.due = document.querySelector('#reading-que .que-due'); - this.que.Reading.todo = document.querySelector('#reading-que .que-todo'); - this.que.Reading.subject = document.querySelector('#reading-que .que-subject'); - this.que.Reading.delete = document.querySelector('#reading-que .delete'); - this.que.Reading.complete = document.querySelector('#reading-que .complete'); - this.que.Reading.details = document.querySelector('#reading-que .que-details'); - this.que.Reading.points = document.querySelector('#reading-que .points'); - this.que.Reading.multiplier = document.querySelector('#reading-que .que-multiplier'); - - this.que.Tests = {}; - this.que.Tests.id = document.getElementById('test-que'); - this.que.Tests.due = document.querySelector('#test-que .que-due'); - this.que.Tests.todo = document.querySelector('#test-que .que-todo'); - this.que.Tests.subject = document.querySelector('#test-que .que-subject'); - this.que.Tests.delete = document.querySelector('#test-que .delete'); - this.que.Tests.complete = document.querySelector('#test-que .complete'); - this.que.Tests.details = document.querySelector('#test-que .que-details'); - this.que.Tests.points = document.querySelector('#test-que .points'); - this.que.Tests.multiplier = document.querySelector('#test-que .que-multiplier'); - - this.que.Videos = {}; - this.que.Videos.id = document.getElementById('video-que'); - this.que.Videos.due = document.querySelector('#video-que .que-due'); - this.que.Videos.todo = document.querySelector('#video-que .que-todo'); - this.que.Videos.subject = document.querySelector('#video-que .que-subject'); - this.que.Videos.delete = document.querySelector('#video-que .delete'); - this.que.Videos.complete = document.querySelector('#video-que .complete'); - this.que.Videos.details = document.querySelector('#video-que .que-details'); - this.que.Videos.points = document.querySelector('#video-que .points'); - this.que.Videos.multiplier = document.querySelector('#video-que .que-multiplier'); - - return this; - }; - - - /** - * Function instantiates selectors for the scoreboard - * and stores their reference in the view.scoreboard object - * - * NEEDS REFACTORED TO USE LOOPS - */ - sbSelectors() { - this.scoreboard.monday = {}; - this.scoreboard.tuesday = {}; - this.scoreboard.wednesday = {}; - this.scoreboard.thursday = {}; - this.scoreboard.friday = {}; - this.scoreboard.saturday = {}; - this.scoreboard.sunday = {}; - this.scoreboard.total = {}; - this.scoreboard.historic = {}; - - this.scoreboard.monday.id = document.querySelector('#monday'); - this.scoreboard.tuesday.id = document.querySelector('#tuesday'); - this.scoreboard.wednesday.id = document.querySelector('#wednesday'); - this.scoreboard.thursday.id = document.querySelector('#thursday'); - this.scoreboard.friday.id = document.querySelector('#friday'); - this.scoreboard.saturday.id = document.querySelector('#saturday'); - this.scoreboard.sunday.id = document.querySelector('#sunday'); - this.scoreboard.total.id = document.querySelector('#totals_row'); - this.scoreboard.historic.id = document.querySelector('#totals_historic_row'); - - this.scoreboard.monday.points = document.querySelector('#monday .points'); - this.scoreboard.tuesday.points = document.querySelector('#tuesday .points'); - this.scoreboard.wednesday.points = document.querySelector('#wednesday .points'); - this.scoreboard.thursday.points = document.querySelector('#thursday .points'); - this.scoreboard.friday.points = document.querySelector('#friday .points'); - this.scoreboard.saturday.points = document.querySelector('#saturday .points'); - this.scoreboard.sunday.points = document.querySelector('#sunday .points'); - this.scoreboard.total.points = document.querySelector('#totals_row .points'); - this.scoreboard.historic.points = document.querySelector('#totals_historic_row .points'); - - this.scoreboard.monday.lastWeek = document.querySelector('#monday .totals_prev'); - this.scoreboard.tuesday.lastWeek = document.querySelector('#tuesday .totals_prev'); - this.scoreboard.wednesday.lastWeek = document.querySelector('#wednesday .totals_prev'); - this.scoreboard.thursday.lastWeek = document.querySelector('#thursday .totals_prev'); - this.scoreboard.friday.lastWeek = document.querySelector('#friday .totals_prev'); - this.scoreboard.saturday.lastWeek = document.querySelector('#saturday .totals_prev'); - this.scoreboard.sunday.lastWeek = document.querySelector('#sunday .totals_prev'); - this.scoreboard.total.lastWeek = document.querySelector('#totals_row .totals_prev'); - this.scoreboard.historic.lastWeek = document.querySelector('#totals_historic_row .totals_prev'); - - this.scoreboard.monday.historic = document.querySelector('#monday .totals_historic_column'); - this.scoreboard.tuesday.historic = document.querySelector('#tuesday .totals_historic_column'); - this.scoreboard.wednesday.historic = document.querySelector('#wednesday .totals_historic_column'); - this.scoreboard.thursday.historic = document.querySelector('#thursday .totals_historic_column'); - this.scoreboard.friday.historic = document.querySelector('#friday .totals_historic_column'); - this.scoreboard.saturday.historic = document.querySelector('#saturday .totals_historic_column'); - this.scoreboard.sunday.historic = document.querySelector('#sunday .totals_historic_column'); - this.scoreboard.total.historic = document.querySelector('#totals_row .totals_historic_column'); - this.scoreboard.historic.historic = document.querySelector('#totals_historic_row .totals_historic_column'); - - return this; - }; - - - /** - * function instantiates selectors for newly created - * dom elements for the controller to access - */ - categorySelectors() { - this.subjectSelector = document.getElementById('subject-list'); - this.categorySelector = document.getElementById('category-list'); - this.todoSelector = document.getElementById("category-input"); - this.detailSelector = document.getElementById('category-details'); - this.dueSelector = document.getElementById('category-due'); - this.pointSelector = document.getElementById('points-dropdown'); - return this; - }; -}; - - - - - -/** - * Class controls all user interactions and - * is composed of a model and view object - * sends user interface manipulations to - * the view object - * sends data interactions to the model object - */ -class Controller { - constructor(model, view) { - this.model = model; - this.view = view; - this.needed = {}; - this.needed.ran = 0; - if (localStorage.key(1)==null) { - this.watcher(); - } else { - this.restoreState(); - }; - }; - - - /** - * Function initializes event listeners - */ - watcher() { - this.controlListener(); - return this; - }; - - saveState() { - return this; - }; - - - restoreState() { - return this; - }; - - clearState() { - localStorage.clear() - return this; - }; - - - /** - * function controls the event listener attached to the submit button - * for the Add New Subject area of the Subject Control Panel - */ - controlListener() { - this.view.createSubject.children[1].addEventListener('click', (event) => { - var subjects = this.model.subjects; - var value = this.view.createSubject.children[0].value; - if (!(subjects.some((x) => x == value)) && value != '') { - subjects.push(value); - this.model.subjectFactory(subjects[subjects.length - 1]) - } else { - this.view.createSubject.children[0].value = ''; - }; - console.log("The subjects array:",subjects); - this.view.subjectList(subjects); - this.subjectListener(); - }); - return this; - }; - - - /** - * Function adds an event listener to the Subject Control Panel - * after its body has been instantiated - */ - subjectListener() { - if (this.needed.ran > 0) { - return this; - }; - if (this.view.subjectCategories && this.needed.ran === 0) { - this.needed.ran = 1; - this.view.subjectCategories.addEventListener('click', (event) => { - if (this.needed.ran < 2) { - this.view.categorySelectors(); - this.needed.ran = 2; - }; - if(!this.view.checkToDoInput()) { - return this; - } - - var parsedDate = Date.parse(this.view.dueSelector.value); - var date = new Date(parsedDate+21600000); - - this.model.data[this.view.subjectSelector.value][this.view.categorySelector.value].push({ - subject: this.view.subjectSelector.value, - todo: this.view.todoSelector.value, - details: this.view.detailSelector.value, - due: date, - points: this.view.pointSelector.value - }); - console.log(this.model.data[this.view.subjectSelector.value][this.view.categorySelector.value]) - this.model.queBuilder(this.view.subjectSelector.value, this.view.categorySelector.value); - - if (this.view.needed.que == 0) { - this.view.needed.que = 1; - this.model.categories.forEach((x) => { - this.view.constructQue(x); - }); - this.view.constructScoreboard(); - this.view.populateSB(this.model.sb.score); - this.view.populateQue(this.model) - this.queListener(); - - } else if (this.view.needed.que == 1) { - this.view.populateSB(this.model.sb.score); - this.view.populateQue(this.model) - }; - }); - }; - return this; - }; - - - - queListener() { - var categories = this.model.categories; - - categories.forEach((x) => { - var deleteButton = this.view.que[x].delete - var completeButton = this.view.que[x].complete - deleteButton.addEventListener('click', (event) => { - this.model.queHandler(x, 'delete'); - this.view.cleanQue(x); - this.view.populateQue(this.model); - }); - completeButton.addEventListener('click', (event) => { - this.model.queHandler(x, 'complete'); - this.view.cleanQue(x); - this.view.populateSB(this.model.sb.score); - this.view.populateQue(this.model); - }); - }); - - return this; - }; - -}; - - - - - -/** - * IIFE Function initializes a controller composed with - * a model and a view object - */ -;(function() { - const app = new Controller(new Model, new View); -}()); \ No newline at end of file diff --git a/backup/public/planner.html b/backup/public/planner.html deleted file mode 100644 index 2f36df3..0000000 --- a/backup/public/planner.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - Planner - - - - - - - - - - - - - - - - - -
- -

-
- -
-
-
-
- -
-
-

Subject Control Panel

-

Add New Subject

-
- - -
-
-
-
-
- -
- -
- - -
- -
-
- -
-
-
- -
-
-
-
- -
-
-
-
- -
-
- -
- - - -
-
-
- -
-

- -
- - - diff --git a/backup/public/states/state2.html b/backup/public/states/state2.html deleted file mode 100644 index 43a53f0..0000000 --- a/backup/public/states/state2.html +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - - - - - - - - - - - - - -
- -

-
- -
-
-
-
- -
-
-

Subject Control Panel

-

Add New Subject

-
- - -
-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - - -
-
-
- -
- -
- - -
- -
-
- -
-
-
- -
-
-
-
- -
-
-
-
- -
-
- -
- - - -
-
-
- -
-

- -
- - - - \ No newline at end of file diff --git a/backup/public/states/state3.html b/backup/public/states/state3.html deleted file mode 100644 index 2ecd151..0000000 --- a/backup/public/states/state3.html +++ /dev/null @@ -1,337 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -
- -

-
- -
-
-
-
- -
-
-

Subject Control Panel

-

Add New Subject

-
- - -
-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - - -
-
-
- -
- -
-
-
-
Homework
-
Due Date: 4/30
-
-
- -
-
To-Do:
-
Subject:
- -
-
-
asdf
-
asdf
- -
-
-
-
-
x1
-
1
-
-
-
-
-
Projects
-
Due Date:
-
-
- -
-
To-Do:
-
Subject:
- -
-
-
todo
-
subject
- -
-
-
-
details
-
x1
-
pts
-
-
-
-
-
Reading
-
Due Date:
-
-
- -
-
To-Do:
-
Subject:
- -
-
-
todo
-
subject
- -
-
-
-
details
-
x1
-
pts
-
-
-
-
-
Tests
-
Due Date:
-
-
- -
-
To-Do:
-
Subject:
- -
-
-
todo
-
subject
- -
-
-
-
details
-
x1
-
pts
-
-
-
-
-
Videos
-
Due Date:
-
-
- -
-
To-Do:
-
Subject:
- -
-
-
todo
-
subject
- -
-
-
-
details
-
x1
-
pts
-
-
- - -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DayPointsLast WeekHistoric High
Mon:000
Tues:000
Weds:000
Thurs:000
Fri:000
Sat:000
Sun:000
Total:000
Historic:000
-
- -
-
-
- -
-
-
-
- -
-
-
-
- -
-
- -
- - - -
-
-
- -
-

- -
- - - - \ No newline at end of file diff --git a/backup/public/test.html b/backup/public/test.html deleted file mode 100644 index e69de29..0000000 diff --git a/src/public/css/main.css b/src/public/css/main.css index b3b2560..79f0a24 100644 --- a/src/public/css/main.css +++ b/src/public/css/main.css @@ -20,9 +20,7 @@ rgb(156, 95, 61) subdued orange .navIn { padding:.5rem; - /* background-color: #31465a; */ - background-color: #323232; - + background-color: #31465a; } .navIn p { @@ -46,18 +44,12 @@ header { #background { padding-top: 1rem; - /* background-color: #360f0f; */ - /* background-color:lightseagreen; */ - background-color: #31465a; - + background-color: #360f0f; color: #dddddd; } body { - /* background-color: #323232; */ - - background-color: #31465a; - + background-color: #323232; } button { @@ -65,18 +57,6 @@ button { background-color: rgb(255, 130, 62); color: #323232; border-radius: 8px; - margin-left: .2rem; - margin-right: .2rem; -} - -button:hover { - border: solid 1pt seagreen; - background-color:lightseagreen; - /* border: solid 1pt green; - background-color:lightgreen; */ - color: #323232; - border-radius: 8px; - } @@ -89,12 +69,6 @@ button:hover { font-size: 10pt; line-height: 12pt; padding-bottom: 2rem; - background-color: #360f0f; - - padding: .1rem; - border: 2.5pt solid black; - border-radius: 16px; - } #control-title { @@ -103,31 +77,16 @@ button:hover { background-color: #b94b4f ; border-radius: 4px; width: 40%; - margin-top: 1rem; margin-left: 30%; } -#control-subject-label { - text-align: left; - margin-left: 10%; - margin-top: .2rem; - margin-bottom: .3rem; -} - #create-subject-label { float: left; } #create-subject { - text-align: right; - margin-bottom: 1rem; - -} + float: right; -#subject-submit { - margin-bottom: .5rem; - text-align: right; - } #subject-list-label { @@ -152,24 +111,20 @@ button:hover { } #subject-subcategories { - padding-top: 1rem; - margin-left: 1rem; - margin-right: 1rem; + padding-top: 3rem; } #subject-subcategories button { - text-align: right; - - /* float: right; */ + float: right; } -/* Queue */ +/* Que */ -.queue-category { +.que-category { font-size: 8pt; margin: .2rem; padding: .1rem; @@ -180,7 +135,7 @@ button:hover { line-height: 1; } -.queue-category-head { +.que-category-head { background-color: #b94b4f; padding-left: .5rem; padding-bottom: .6rem; @@ -191,48 +146,48 @@ button:hover { width: 40%; } -.queue-head, .que-title { +.que-head, .que-title { font-size: 10pt; } -.queue-line { +.que-line { display: inline-block; } -.queue-todo , .que-todo-title { +.que-todo , .que-todo-title { width: 35%; } -.queue-subject, .que-subject-title { +.que-subject, .que-subject-title { width: 32%; } -.queue-contents { +.que-contents { font-weight: 300; line-height: .9; font-size: 8pt; } -.queue-button-right { +.que-button-right { /* float: right; margin-right: 5px; */ font-size: 10pt; width: 30%; } -.queue-details { +.que-details { width: 77%; } -.queue-points { +.que-points { width: 10% } -.queue-multiplier { +.que-multiplier { width: 10% } -.queue-bar { +.que-bar { margin: .2rem; padding-bottom: 0.5rem; padding-left: .5rem; @@ -242,12 +197,12 @@ button:hover { background-color: #31465a; } -.queue-title { +.que-title { border-radius: 4px; background-color: #31465a ; } -.queue-area { +.que-area { padding-top: 5px; } diff --git a/backup/public/index.html b/src/public/index.html similarity index 82% rename from backup/public/index.html rename to src/public/index.html index 3a93227..d8c8f66 100644 --- a/backup/public/index.html +++ b/src/public/index.html @@ -55,28 +55,6 @@
- -
-
-
- -
-
-
-
- -
-
-
-
- -
-
- -
- - -
diff --git a/backup/public/mvcbackup.js b/src/public/javascript/mvc.js similarity index 99% rename from backup/public/mvcbackup.js rename to src/public/javascript/mvc.js index 36c2d50..4538c14 100644 --- a/backup/public/mvcbackup.js +++ b/src/public/javascript/mvc.js @@ -539,6 +539,8 @@ class Controller { } else { this.restoreState(); }; + + }; @@ -570,8 +572,10 @@ class Controller { * for the Add New Subject area of the Subject Control Panel */ controlListener() { + console.log('outside listener 1') this.view.createSubject.children[1].addEventListener('click', (event) => { var subjects = this.model.subjects; + console.log('inside listener 1') var value = this.view.createSubject.children[0].value; if (!(subjects.some((x) => x == value)) && value != '') { subjects.push(value); diff --git a/src/public/javascript/mvc/controller/controller.js b/src/public/javascript/mvc/controller/controller.js deleted file mode 100644 index b967f18..0000000 --- a/src/public/javascript/mvc/controller/controller.js +++ /dev/null @@ -1,170 +0,0 @@ - - - -/** - * Class controls all user interactions and - * is composed of a model and view object - * sends user interface manipulations to - * the view object - * sends data interactions to the model object - */ -class Controller { - constructor(model, view) { - this.model = model; - this.view = view; - - // Get state from local storage - if (localStorage.getItem('planner_state')==null) { - this.state = 1; - } else { - this.state = localStorage.getItem('planner_state'); - }; - this.restoreState(); - - - return this; - }; - - restoreState() { - this.view.bindData(this.model); - this.view.update(this.state); - this.updateListeners(); - - return this; - }; - - storeLocally() { - localStorage.setItem('planner_state', this.state); - }; - - subjectListener(button, fieldElement) { - if (this.subjectButtonListener) { - delete this.subjectButtonListener - }; - - - this.subjectButtonListener = button.addEventListener('click', (event)=>{ - let field = fieldElement.value; - if( - field != '' - && !this.model.subjects.some((x) => x == field) - ) { - console.log('success: subject was created') - this.model.subjectFactory(field) - if(this.state < 2) { - this.state = 2 - this.view.virtualControlPanel(2) - .updateControlPanel(); - this.updateListeners(); - this.toDoListener(this.view.createTodoButton, this.view.createTodo); - - - } else { - this.view.virtualControlPanel() - .updateControlPanel(); - this.updateListeners(); - }; - } else { - - console.log('failure: input was not accepted'); - } - }); - - return this; - }; - - toDoListener(button, fields) { - if(this.toDoButtonListener) { - delete this.toDoButtonListener; - }; - - this.toDoButtonListener = button.addEventListener('click', (event) => { - console.log('hello from todoListener') - if(this.view.checkToDoInput()) { - - var parsedDate = Date.parse(this.view.createTodo.due.value); - var date = new Date(parsedDate+21600000); - var item = { - subject: this.view.createTodo.subject.value, - todo: this.view.createTodo.todo.value, - details: this.view.createTodo.detail.value, - due: date, - points: this.view.createTodo.point.value - }; - - this.model.data[this.view.createTodo.subject.value][this.view.createTodo.category.value].push(item); - this.model.Q.pushTo(this.view.createTodo.category.value, item) - .sort(); - - if(this.state < 3) { - this.state = 3; - this.view.update(3); - this.updateListeners(); - } else { - this.view.virtualQueue() - .updateQueue(); - }; - } else { - console.log("input fields needed to create todo item"); - }; - - }) - - return this; - }; - - - updateListeners() { - var state = this.state; - if(state == 1) { - if(this.subjectButtonListener) { - delete this.subjectButtonListener; - }; - this.subjectListener(this.view.createSubjectButton, this.view.newSubjectField); - } else if (state == 2) { - if(this.subjectButtonListener) { - delete this.subjectButtonListener; - }; - - if(this.toDoButtonListener) { - delete this.toDoButtonListener; - }; - - this.subjectListener(this.view.createSubjectButton, this.view.newSubjectField); - this.toDoListener(this.view.createTodoButton, this.view.createTodo); - } else if (state == 3) { - if(this.subjectButtonListener) { - delete this.subjectButtonListener; - }; - - if(this.toDoButtonListener) { - delete this.toDoButtonListener; - }; - - this.subjectListener(this.view.createSubjectButton, this.view.newSubjectField); - this.toDoListener(this.view.createTodoButton, this.view.createTodo); - } else if (state == 4) { - if(this.subjectButtonListener) { - delete this.subjectButtonListener; - }; - - if(this.toDoButtonListener) { - delete this.toDoButtonListener; - }; - - this.subjectListener(this.view.createSubjectButton, this.view.newSubjectField); - this.toDoListener(this.view.createTodoButton, this.view.createTodo); - }; - - return this; - } - - - -}; - - -export {Controller} - - - diff --git a/src/public/javascript/mvc/models/model.js b/src/public/javascript/mvc/models/model.js deleted file mode 100644 index 3efd4a0..0000000 --- a/src/public/javascript/mvc/models/model.js +++ /dev/null @@ -1,93 +0,0 @@ - -import {Scoreboard} from "./scoreboard.js"; -import {Queue} from "./queue.js"; - -'use strict' - - -/** - * Class stores all of the data for the planner app - * contains methods for manipulating the data - * using the scoreboard object in its composition - * located in ./scoreboard.js - */ -class Model{ - constructor() { - if (localStorage.getItem('subjects') == null) { - this.sb = new Scoreboard; - this.Q = new Queue; - this.deletedQ = new Queue; - this.completedQ = new Queue; - this.subjects = []; - this.data = {}; - } else { - this.sb = new Scoreboard(JSON.parse(localStorage.getItem('score'))) - this.Q = new Queue(JSON.parse(localStorage.getItem('queue'))) - this.deletedQ = new Queue(JSON.parse(localStorage.getItem('deleted_queue'))) - this.completedQ = new Queue(JSON.parse(localStorage.getItem('completed_queue'))) - this.subjects = JSON.parse(localStorage.getItem('subjects')) - this.data = JSON.parse(localStorage.getItem('data')) - } - this.categories = ['Homework', 'Projects', 'Reading', 'Tests', 'Videos']; - this.storeLocally() - - return this; - }; - - storeLocally() { - localStorage.setItem('score', JSON.stringify(this.sb.score)) - localStorage.setItem('queue', JSON.stringify(this.Q.queue)) - localStorage.setItem('deleted_queue', JSON.stringify(this.deletedQ.queue)) - localStorage.setItem('completed_queue', JSON.stringify(this.completedQ.queue)) - localStorage.setItem('subjects', JSON.stringify(this.subjects)) - localStorage.setItem('data', JSON.stringify(this.data)) - - return this; - }; - - - - - /** - * function creates a new set of arrays inside the - * data object to represent a new subject - */ - subjectFactory(subject) { - this.subjects.push(subject) - this.data[subject] = { - Homework: [], - Projects: [], - Reading: [], - Tests: [], - Videos: [] - }; - - return this; - }; - - - /** - * function gives a point multiplier that - * depends on how soon the todo item is due - */ - checkMultiplier(dueDate) { - var output = dueDate === ''? 0: 1; - if (output = 0) { - return output - }; - var today = Date.parse(new Date); - var item = Date.parse(dueDate); - var difference = (item - today)/3600000; - if (difference < 6) { - var output = 2; - } else if (difference < 12) { - var output = 1.5; - }; - return output; - }; -}; - - - - -export {Model} \ No newline at end of file diff --git a/src/public/javascript/mvc/models/queue.js b/src/public/javascript/mvc/models/queue.js deleted file mode 100644 index 862b730..0000000 --- a/src/public/javascript/mvc/models/queue.js +++ /dev/null @@ -1,80 +0,0 @@ -'use strict'; - -export {Queue}; - - -class Queue { - constructor(queue) { - this.queue = queue || {Homework: [], Projects: [], Reading: [], Tests: [], Videos: []}; - this.categories = Object.keys(this.queue); - }; - - - shiftOut(category) { - if (this.categories.some((x) => x === category)) { - this.queue[category].shift(); - }; - return this; - }; - - activeCategories() { - return this.categories.filter((x)=> this.queue[x][0] !== undefined); - - } - - - currentItems() { - console.log('state of the queue', this.queue) - var upNext = this.categories.filter((x)=> this.queue[x][0] !== undefined) - .map((y) => this.queue[y][0]); - console.log('state of the queue after filter', upNext) - return upNext; - }; - - - pushTo(category, item) { - console.log('from queue:: pushTo(category, item):', category, item) - if (this.categories.some((x) => x === category)) { - this.queue[category].push(item); - }; - return this; - }; - - - peekAt(category) { - if (this.categories.some((x) => x === category)) { - return this.queue[category][0]; - }; - }; - - sort() { - this.categories.forEach((x) => { - this.queue[x].sort((a, b) => { - if (a['due'] < b['due']) { - return -1; - } else if (a['due'] > b['due']) { - return 1; - } else { - return 0; - }; - }); - }); - - return this; - }; - - - printCategory(category) { - if (this.categories.some((x) => x === category)) { - console.table(this.queue[category]); - }; - return this; - }; - - - printQueue() { - console.log(this.queue); - return this; - }; - -}; \ No newline at end of file diff --git a/src/public/javascript/mvc/models/scoreboard.js b/src/public/javascript/mvc/models/scoreboard.js deleted file mode 100644 index c6abb83..0000000 --- a/src/public/javascript/mvc/models/scoreboard.js +++ /dev/null @@ -1,229 +0,0 @@ -/* -************************************************************************** -Assignment -James Halladay -Advanced Programming with JavaScript -Date: 3/30/2020 - -*/ - -'use strict' - -export {Scoreboard} - -/** - * Object Scoreboard - * - * Object is used to control the Data of the Scoreboard - * for the Planner - * - * Methods: - * constructor :: object -> Scoreboard - * instantiates Scoreboard object - * - * setTotals :: void -> Scoreboard - * checks and sets Totals/Historic Total Row - * and Historic High Column - * - * checkDay :: str -> Scoreboard - * checks currentDay property against today's date - * reassignes currentDay value if different - * starts setNextWeek method if different and Monday - * - * setNewWeek :: void -> Scoreboard - * reassignes the values held in the Last Week Column - * to the value held in the Points Column - * reassignes the Points Column to 0 - * leaves the Historic Total Points Column untouched - * - * setPoints :: number -> Scoreboard - * accepts a parameter which is then used to increment - * the value of the Points Column for the day - * that matches the currentDay property - * - * printScore :: void -> Scoreboard - * prints out the score property using a table method from - * the console namespace - * - * Methods all return Scoreboard object to allow for Method Chaining - * - * - * Properties: - * score ::= The current score held in all rows and columns - * weekday ::= Array containing the Days of the week for lookup - * row ::= Array containing the list of rows in order for lookup - * currentDay ::= Creates new date object and looks up day from weekday - */ -class Scoreboard { - - /** - * constructor :: object -> Scoreboard - * - * function instantiates the properties of the Scoreboard object: - * score ::= The current score held in all rows and columns - * weekday ::= Array containing the Days of the week for lookup - * row ::= Array containing the list of rows in order for lookup - * currentDay ::= Creates new date object and looks up day from weekday - * - * returns Scoreboard to allow for Method Chaining - */ - constructor(currentScore) { - this.score = currentScore || { - "Monday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Tuesday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Wednesday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Thursday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Friday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Saturday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Sunday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Total" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Historic Total": {"Points": 0, "Last Week": 0, "Historic High": 0} - }; - - this.weekday = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; - - this.rows = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", "Total", "Historic Total"] - - this.currentDay = this.weekday[new Date().getDay()]; - - return this; - }; - - - /** - * setTotals :: void -> Scoreboard - * - * Function calculates the values held in the Total Row, The Historic Total Row - * and The Historic High Column - * - * returns Scoreboard object to allow method chaining - */ - setTotals() { - var score = this.score; - - function highScore(day) { - day["Historic High"] = [ - day.Points , - day["Last Week"] , - day["Historic High"] - ].sort((a, b)=> b - a)[0] - } - - - score.Total.Points = 0 - for (var day of this.weekday) { - score.Total.Points += score[day].Points; - }; - - score["Historic Total"].Points = ( - score.Total.Points + - score["Historic Total"]["Last Week"] - ); - - for (var row of this.rows) { - highScore(score[row]); - }; - - return this; - }; - - - /** - * checkDay :: str -> Scoreboard - * - * Function checks the currentDay property of Scoreboard - * and reassigns the correct day. - * - * Takes a test parameter to allow for manually setting - * the day for test purposes - * - * returns Scoreboard to allow method chaining - */ - checkDay(test) { - var day = test || this.weekday[new Date().getDay()]; - - if (day == this.currentDay) { - return this; - } else if (day == "Monday") { - this.currentDay = "Monday"; - this.setTotals().setNewWeek(); - } else { - this.currentDay = day; - }; - return this; - }; - - - /** - * setNewWeek :: void -> Scoreboard - * - * Function reassigns the values in the Last Week Column to the - * Value held in the Points Column - * - * It then reassigns the values in the Points Column to 0 - * - * The Historic Total Row maintains its current Points Value - * - * returns Scoreboard to allow for Method Chaining - */ - setNewWeek() { - var score = this.score; - - function moveScore(day) { - day["Last Week"] = day.Points; - if (day != score["Historic Total"]) { - day.Points = 0; - }; - }; - - - for (var row of this.rows) { - moveScore(score[row]); - }; - - return this; - }; - - - /** - * setPoints :: number -> Scoreboard - * - * function takes an input value and uses it to increment - * the Points column of the row matching currentDay - * - * returns Scoreboard to allow for method chaining - */ - setPoints(value) { - var newPoints = value || 0; - var day = this.checkDay().currentDay; - this.score[day].Points += newPoints; - - return this; - } - - - /** - * printScore :: void -> Scoreboard - * - * Function prints out score property of Scoreboard in a - * table format to either the node terminal or browser - * console - * - * returns Scoreboard to allow for Method Chaining - */ - printScore() { - console.table(this.score); - return this; - }; - -}; - - - -// (function() { -// if (typeof window === 'undefined'){ -// if (require.main != module) { -// exports.Scoreboard = Scoreboard; -// }; -// }; -// }()); \ No newline at end of file diff --git a/src/public/javascript/mvc/views/index.js b/src/public/javascript/mvc/views/index.js deleted file mode 100644 index d0f119b..0000000 --- a/src/public/javascript/mvc/views/index.js +++ /dev/null @@ -1,361 +0,0 @@ -function compose(...funcs) { - return (x) => funcs.reduceRight(((value, func)=>func(value)), x); -} - - -function scoreboard(score) { - - var score = score || { - "Monday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Tuesday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Wednesday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Thursday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Friday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Saturday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Sunday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Total" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Historic Total": {"Points": 0, "Last Week": 0, "Historic High": 0} - }; - - - - var values = [ - ['Day' , 'Points' , 'Last Week' , 'Historic High'], - ["Mon:" , score['Monday']['Points'] , score['Monday']['Last Week'] , score['Monday']['Historic High']], - ["Tues:" , score['Tuesday']['Points'] , score['Tuesday']['Last Week'] , score['Tuesday']['Historic High']], - ["Weds:" , score['Wednesday']['Points'] , score['Wednesday']['Last Week'] , score['Wednesday']['Historic High']], - ["Thurs:" , score['Thursday']['Points'] , score['Thursday']['Last Week'] , score['Thursday']['Historic High']], - ["Fri:" , score['Friday']['Points'] , score['Friday']['Last Week'] , score['Friday']['Historic High']], - ["Sat:" , score['Saturday']['Points'] , score['Saturday']['Last Week'] , score['Saturday']['Historic High']], - ["Sun:" , score['Sunday']['Points'] , score['Sunday']['Last Week'] , score['Sunday']['Historic High']], - ["Total:" , score['Total']['Points'] , score['Total']['Last Week'] , score['Total']['Historic High']], - ["Historic:", score['Historic Total']['Points'], score['Historic Total']['Last Week'], score['Historic Total']['Historic High']] - ] - - var columnIDs = [ - ['rows' , 'th'], - ['points' , 'td'], - ['totals_prev' , 'td'], - ['totals_historic_column', 'td'] - ] - - var rowIDs = [ - 'columns' , 'monday', - 'tuesday' , 'wednesday', - 'thursday' , 'friday', - 'saturday' , 'sunday', - 'totals_row', 'totals_historic_row', - ] - - var table = React.createElement( - 'table', - {'class': 'table table-dark table-hover', 'key':'Scoreboard_View'}, - React.createElement( - 'tbody', - {key: `Sb_tbody`}, - rowIDs.map((x, i) => { - // make rows - return React.createElement( - 'tr', - {'id': x, key: `${x}_${i}`}, - columnIDs.map((y, j) => { - // Make columns; first Column uses 'th' tag - if (j > 0) { - return React.createElement( - i>0? 'td': 'th', - {'class': y[0], key: `${y}_${j}`}, - values[i][j] - ) - } else { - return React.createElement( - y[1], - {'class': y[0], key: `${y}_${j}`}, - values[i][j] - ); - }; - }) - ) - }) - ) - ); - return table; -}; - - -function queueBuilder(checkMultiplier, categories, queue) { - var idCreator = { - 'Homework': 'homework-que', - 'Projects': 'project-que', - 'Reading' : 'reading-que', - 'Tests' : 'test-que', - 'Videos' : 'video-que' - }; - - function layer1(category, queue) { - if (queue[category][0]) { - if (queue[category][0]['due'].split !== undefined) { - var Qdate = Date.parse(queue[category][0]['due']) - } else { - var Qdate = queue[category][0]['due'] - } - Qdate = new Date(Qdate); - var data = [ - `Due Date: ${Qdate.getMonth() + 1}/${Qdate.getDate()}`, - queue[category][0]['todo'], - queue[category][0]['subject'], - queue[category][0]['details'], - checkMultiplier(queue[category][0].due), - queue[category][0]['points'] - ] - } else { - var data = [ - 'Due Date: ', 'Nothing', - '' , 'None', - '0' , '0x' - ] - }; - - return [ - ['section', 'que-head' , [ - ['div', 'que-line que-category-head', category], - ['div', 'que-line que-due', data[0]], - ]], - ['div' , 'que-bar' , [ - ['section', 'que-title', [ - ['div' , 'que-line que-todo-title' , 'To-Do:'], - ['div' , 'que-line que-subject-title' , 'Subject:'], - ['button', 'que-line que-button-right complete', 'Complete'] - ] - ], - ['section', 'que-title', [ - ['div' , 'que-line que-todo-title' , data[1]], - ['div' , 'que-line que-subject-title' , data[2]], - ['button', 'que-line que-button-right delete', 'Delete'] - ] - ] - ]], - ['section', 'que-bar que-contents', [ - ['div', 'que-line que-details que-contents', data[3]], - ['div', 'que-line que-points que-multiplier que-contents', data[4]], - ['div', 'que-line que-points points que-contents', data[5]] - ]] - ]; - }; - - var queues = React.createElement( - 'div', - {'key': "queue-container"}, - categories.map((x, i) => { - var inner = layer1(x, queue); - - return React.createElement( - 'div', - {'class': 'que-category', 'id': idCreator[x], 'key': `queue-${x}`}, - inner.map((y, j) => { - - return React.createElement( - y[0], - {'class': y[1], 'key': `${y}${j}`}, - y[2].map((z, k) => { - console.log('z[2]: ', z[2]) - if (z[2].join === undefined) { - var fill = z[2] - } else { - var fill = z[2].map((a, l) => { - return React.createElement( - a[0], - {'class': a[1], 'key': `${a}${l}`}, - a[2] - ); - }) - }; - return React.createElement( - z[0], - {'class': z[1], 'key': `${z}${k}`}, - fill - ) - }) - ); - - }) - ); - }) - ); - - - return queues; -}; - -function queueBuilder2(checkMultiplier, categories, queue) { - - var emptyQueue = { - 'subject': '', - 'todo':'Nothing', - 'details':'None', - 'points':'0' - }; - - var dueDate = categories.map((a) => - queue[a][0]? - '': - new Date( - (queue[a][0]['due'].getDate)? - queue[a][0]['due']: - Date.parse(queue[a][0]['due']))) - - var multiplier = dueDate.map((a) => checkMultiplier(a)) - - var counter = 0; - - var level1 = [ - ['div', {'key':counter++, 'className': 'que-category', 'id': 'homework-que'}], - ['div', {'key':counter++, 'className': 'que-category', 'id': 'project-que'}], - ['div', {'key':counter++, 'className': 'que-category', 'id': 'reading-que'}], - ['div', {'key':counter++, 'className': 'que-category', 'id': 'test-que'}], - ['div', {'key':counter++, 'className': 'que-category', 'id': 'video-que'}] - ]; - - var level2 = [ - ['section', {'key':counter++, 'className': 'que-head'}], - ['div', {'key':counter++, 'className': 'que-bar'}], - ['section', {'key':counter++, 'className': 'que-bar que-contents'}], - ] - - var level3 = [ - ['div', {'key':counter++, 'className': 'que-line que-category-head'}], - ['div', {'key':counter++, 'className': 'que-line que-date'}], - ['section', {'key':counter++, 'className': 'que-title'}], - ['section', {'key':counter++, 'className': 'que-area que-contents'}], - ['div', {'key':counter++, 'className': 'que-line que-details que-contents'}], - ['div', {'key':counter++, 'className': 'que-line que-points que-multiplier que-contents'}], - ['div', {'key':counter++, 'className': 'que-line que-points points que-contents'}] - ]; - - var level4 = [ - ['div', {'key':counter++, 'className': 'que-line que-todo-title'}], - ['div', {'key':counter++, 'className': 'que-line que-subject-title'}], - ['button', {'key':counter++, 'className': 'que-line que-button-right complete'}], - ['div', {'key':counter++, 'className': 'que-line que-todo que-contents'}], - ['div', {'key':counter++, 'className': 'que-line que-subject que-contents'}], - ['button', {'key':counter++, 'className': 'que-line que-button-right delete'}], - ]; - - var level4Headers = ['To-Do:', 'Subject:', 'Complete', 'todo', 'subject', 'Delete'] - - var level4Contents = categories.map( - (a) => level4Headers.map( - (x, i) => (i != 3 && i != 4)? x: - queue[a][0]? queue[a][0][x]: emptyQueue[x])); - - var allLevel4 = categories.map( - (a, b) => level4.map( - (x, i) => React.createElement(x[0], x[1], level4Contents[b][i]))); - - var level3Content = categories.map((a, b) => - level3.map((x, i) => { - switch(i) { - case 0: return a; - case 1: return dueDate[b]; - case 2: return allLevel4[b].filter((y, j) => j < 3); - case 3: return allLevel4[b].filter((y, j) => j > 2); - case 4: return queue[a][0]? queue[a][0]['details']: emptyQueue['details']; - case 5: return `x${multiplier[b]}`; - case 6: return queue[a][0]? queue[a][0]['points']: emptyQueue['points']; - };}) - ) - - var allLevel3 = categories.map( - (a, b) => level3.map( - (x, i) => React.createElement(x[0], x[1], level3Content[b][i]))) - - var allLevel2 = categories.map( - (a, b) => level2.map( - (x, i) => { - switch(i) { - case 0: var content = allLevel3[b].filter((y, j)=> j < 2); break; - case 1: var content = allLevel3[b].filter((y, j)=> j > 1 && j < 4); break; - case 2: var content = allLevel3[b].filter((y, j)=> j > 3); - }; - - return React.createElement(x[0], x[1], content); - })) - - var allLevel1 =level1.map( - (x, i)=> React.createElement(x[0], x[1], allLevel2[i])); - - - return React.createElement('div', {'key': "queue-container", 'id': 'queue'}, allLevel1); -}; - - - - -function checkMultiplier(x) {return '1'} - -var categories = ["Homework", "Projects", "Reading", "Tests", "Videos"] - -var Testqueue = { - "Homework": [ - { - "subject": "mechanics", - "todo": "hw1", - "details": "", - "due": "2020-04-27T06:00:00.000Z", - "points": "1" - }, - { - "subject": "mechanics", - "todo": "hw2", - "details": "", - "due": "2020-05-06T06:00:00.000Z", - "points": "2" - } - ], - "Projects": [ - { - "subject": "mechanics", - "todo": "proj1", - "details": "https://www.youtube.com/watch?v=CnailTcJV_U", - "due": "2020-04-28T06:00:00.000Z", - "points": "10" - } - ], - "Reading": [ - { - "subject": "mechanics", - "todo": "ch1", - "details": "", - "due": "2020-05-24T06:00:00.000Z", - "points": "2" - } - ], - "Tests": [ - { - "subject": "mechanics", - "todo": "exam4", - "details": "", - "due": "2020-04-29T06:00:00.000Z", - "points": "10" - } - ], - "Videos": [ - { - "subject": "mechanics", - "todo": "lewin2", - "details": "https://www.youtube.com/watch?v=CnailTcJV_U", - "due": "2020-04-28T06:00:00.000Z", - "points": "1" - } - ] - } - - - -function reLaunch(score) { - ReactDOM.render(scoreboard(score), document.getElementById('root')) - -} - -function launch() { - ReactDOM.render(queueBuilder2(checkMultiplier,categories,Testqueue), document.getElementById('root')) -} \ No newline at end of file diff --git a/src/public/javascript/mvc/views/templates.js b/src/public/javascript/mvc/views/templates.js deleted file mode 100644 index fcd7b45..0000000 --- a/src/public/javascript/mvc/views/templates.js +++ /dev/null @@ -1,183 +0,0 @@ -/* -Templates.js holds large formatted strings that describes - the layout of various pieces of the apps HTML content - - Needs to be reformatted to use loops - */ - -export {template, queTemplate} - - -function template(stringName) { - if (stringName == 'subject-panel') { - var temp = ` -
- - -
-
- - -
-
- - -
-
- - -
-
- - - -
`; - } else if (stringName == 'scoreboard') { - var temp = ` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DayPointsLast WeekHistoric High
Mon:
Tues:
Weds:
Thurs:
Fri:
Sat:
Sun:
Total:
Historic:
`; - - }; - return temp; -}; - -function queTemplate(category) { - var idCreator = { - 'Homework': 'homework-que', - 'Projects': 'project-que', - 'Reading' : 'reading-que', - 'Tests' : 'test-que', - 'Videos' : 'video-que' - }; - - var currentID = idCreator[category]; - - var temp = ` -
-
-
${category}
-
Due Date:
-
-
- -
-
To-Do:
-
Subject:
- -
-
-
todo
-
subject
- -
-
-
-
details
-
x1
-
pts
-
-
`; - - return temp; -}; \ No newline at end of file diff --git a/src/public/javascript/mvc/views/test.html b/src/public/javascript/mvc/views/test.html deleted file mode 100644 index fb8afd8..0000000 --- a/src/public/javascript/mvc/views/test.html +++ /dev/null @@ -1,68 +0,0 @@ - -
-
-

Subject Control Panel

-

Add New Subject

-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - - -
-
- -
-
-
\ No newline at end of file diff --git a/src/public/javascript/mvc/views/view.js b/src/public/javascript/mvc/views/view.js deleted file mode 100644 index c3a8f16..0000000 --- a/src/public/javascript/mvc/views/view.js +++ /dev/null @@ -1,341 +0,0 @@ - -const Comps = { - categories: ['Homework', 'Projects', 'Reading', 'Tests', 'Videos'], - queueIds: {'Homework': 'homework-queue', 'Projects': 'project-queue', 'Reading' : 'reading-queue', 'Tests' : 'test-queue', 'Videos' : 'video-queue'}, - - - Ctr: (...elements) => React.createElement( - 'div', - {'id': 'control', 'key': 'ctr'}, - React.createElement('p', {'id': 'control-title','key': 'ControlTitle'}, "Control Panel"), - React.createElement('p', {'id': 'control-subject-label','key': 'NewSubjectLabel'}, "Add New Subject"), - Comps.CtrSubjectSubmit(), - ...elements, - ), - - CtrSubjectSubmit: () => React.createElement( - 'div', - {'id': 'create-subject','key': 'CreateSubject'}, - React.createElement('input', {type: 'text', name: 'subject', placeholder: 'new subject...', id: 'createSubject', key: 'CreateSubjectField'}), - React.createElement('button', {id: 'create-subject-button', key: 'CreateSubjectButton'}, 'Submit') - ), - - CtrFillSubject: (subjects) => React.createElement( - 'div', - {'id': 'subject-subcategories','key': 'SubjectSubcategories'}, - React.createElement('label', {'htmlFor': 'subjects', id: 'subject-list-label', key: 'SubjectListLabel'}, 'Subject:'), - React.createElement( - 'select', - {name: 'subjects', id: 'subject-list', key: 'SubjectDropDown'}, - subjects.map((x, i) => React.createElement('option', {value: x, className: x, key: 'SubjectOptions'+i}, x)) - ), - Comps.CtrToDoFields(), - React.createElement( - 'div', - {id: 'subject-submit', key: 'EnterToDo'}, - React.createElement('button', {'id': 'add-items','key': 'CreateTodo'}, "Submit") - ) - ), - - CtrToDoFields: () => React.createElement( - 'div', - {className: 'subcategories', id: 'addToDo', key: 'SubcategoriesArea'}, - React.createElement( - 'section', - {key: 'Section1'}, - React.createElement('label', {htmlFor: 'category', id: 'category-list-label', key: 'CategoryListLabel'}, "Category: "), - React.createElement( - 'select', - {name: 'category', id: 'category-list', key: 'CategoryDropDown'}, - Comps.categories.map((x, i) => React.createElement('option', {value: x, key: x + i}, x)) - ) - ), - React.createElement( - 'section', - {key: 'Section2'}, - React.createElement('label', {htmlFor: 'category-input', id: 'category-input-label', key: 'CategoryInputLabel'}, 'To-Do: '), - React.createElement('input', {type: 'text', id: 'category-input', name: 'category-input', placeholder: 'Add item to ToDo list', key: 'InputToDoField'}) - ), - React.createElement( - 'section', - {key: 'Section3'}, - React.createElement('label', {htmlFor: 'category-details', id: 'details-label', key: 'CategoryDetailsLabel'}, 'Details: '), - React.createElement('input', {type: 'text', id: 'category-details', name: 'category-details', placeholder: 'details...', key: 'CategoryDetailsField'}) - ), - React.createElement( - 'section', - {key: 'Section4'}, - React.createElement('label', {htmlFor: 'category-due', id: 'due-label', key: 'CategoryDueLabel'}, 'Due Date: '), - React.createElement('input', {type: 'date', id: 'category-due', name: 'category-due', key: 'CategoryDueField'}) - ), - React.createElement( - 'section', - {key: 'Section5'}, - React.createElement('label', {htmlFor: 'points', id: 'points-label', key: 'CategoryPointsLabel'}, 'Points: '), - React.createElement( - 'select', - {id: 'points-dropdown', name: 'points', key: 'CategoryPointsDropDown'}, - ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'].map((x) => React.createElement('option', {value: x, key: `${x}Point`}, x)) - ) - ) - ), - - QueueArea: (queue, checkMultiplier) => { - var items = queue.activeCategories(); - if (items.length == 0) { - console.log('item length is 0:', items) - return; - }; - return React.createElement( - 'div', - {'key': "queue-container", 'id': 'queue', key: 100*Math.random}, - items.map((x) => { - console.log("from items.map",x, queue.peekAt(x), checkMultiplier(new Date)) - return Comps.QueueSingle(x, queue.peekAt(x), checkMultiplier) - }) - ); - }, - - QueueSingle: (category, queueItem, checkMultiplier) => { - console.log('queueSingle1', category, queueItem) - var dueDate = new Date((queueItem['due'].getDate)? queueItem['due']: Date.parse(queueItem['due'])) - console.log('queueSingle2', category, queueItem, dueDate) - - return React.createElement( - 'div', - {className: 'queue-category', id: Comps.queueIds[category], key: `${category}Queue`}, - React.createElement( - 'section', - {className: 'queue-head', key: `${category}QueueSection1`}, - React.createElement('div', {className: 'queue-line queue-category-head', key: `${category}QueueCategoryLabel`}, category), - React.createElement('div', {className: 'queue-line queue-due', key: `${category}QueueDueDisplay`}, `Due: ${dueDate.getMonth() + 1}/${dueDate.getDate()}`) - ), - React.createElement( - 'div', - {className: 'queue-bar', key: `${category}QueueBar1`}, - React.createElement( - 'section', - {className: 'queue-title', key: `${category}QueueSection2`}, - React.createElement('div', {className: 'queue-line queue-todo-title' , key: `${category}QueueToDoLabel`}, 'To-Do: '), - React.createElement('div', {className: 'queue-line queue-subject-title' , key: `${category}QueueSubjectLabel`}, 'Subject: '), - React.createElement('button', {className: 'queue-line queue-button-right complete' , key: `${category}QueueCompleteButton`}, 'Complete') - ), - React.createElement( - 'section', - {className: 'queue-area queue-contents', key: `${category}QueueSection3`}, - React.createElement('div', {className: "queue-line queue-todo queue-contents" ,key: `${category}QueueToDoItem`}, queueItem['todo']), - React.createElement('div', {className: "queue-line queue-subject queue-contents" ,key: `${category}QueueSubject`}, queueItem['subject']), - React.createElement('button', {className: "queue-line queue-button-right delete" ,key: `${category}QueueDeleteButton`}, 'Delete') - ) - ), - React.createElement( - 'section', - {className: 'queue-bar queue-contents', key: `${category}QueueBar2`}, - React.createElement('div', {className: 'queue-line queue-details queue-contents', key: `${category}QueueDetailsDisplay`}, queueItem['details']), - React.createElement('div', {className: 'queue-line queue-points queue-multiplier queue-contents', key: `${category}QueueMultDisplay`}, `x${checkMultiplier(dueDate)}`), - React.createElement('div', {className: 'queue-line queue-points points queue-contents', key: `${category}QueuePointDisplay`}, queueItem['points']) - ) - ) - }, -}; - - - - -/** - * Class controls all user interface manipulations - * instantiates selectors for the controller to access - * and passes data from the UI to the controller - */ -class View { - constructor() { - this.state = 0 - - - this.left = document.getElementById('Left_Panel') - this.middle = document.getElementById('Middle_Panel') - this.right = document.getElementById('Right_Panel') - - return this; - }; - - - bindData(model) { - this.model = model; - - return this; - } - - setPosition() { - console.log('state', this.state) - switch(this.state) { - case 1: - this.controlPosition = this.middle; - this.sbPosition = ''; - this.queuePosition = ''; - break; - case 2: - this.controlPosition = this.middle; - this.sbPosition = ''; - this.queuePosition = ''; - break; - case 3: - console.log('from setPosition, state=', this.state) - this.controlPosition = this.right; - this.sbPosition = this.middle; - this.queuePosition = this.left; - break; - case 4: - this.controlPosition = this.left; - this.sbPosition = this.right; - this.queuePosition = this.middle; - break; - }; - - return this; - }; - - update(state) { - if(this.state !== state) { - this.state = state; - this.renderDOM() - }; - }; - - cleanDOM() { - // this.controlPosition = ''; - // this.queuePosition = ''; - // this.sbPosition = ''; - console.log('Componenet unmounted at left: ', ReactDOM.unmountComponentAtNode(this.left)) - console.log('Componenet unmounted at middle: ', ReactDOM.unmountComponentAtNode(this.middle)) - console.log('Componenet unmounted at right: ', ReactDOM.unmountComponentAtNode(this.right)) - return this; - }; - - renderDOM() { - this.cleanDOM().setPosition(); - this.cleanDOM().setPosition(); - this.virtualControlPanel() - this.virtualQueue() - this.virtualScoreboard() - - if(this.controlPosition !== '') { - console.log('from renderDOM:', this.controlPanel, this.controlPosition) - ReactDOM.render(this.controlPanel, this.controlPosition, ()=>console.log('rendered control panel at: ', this.controlPosition.id)) - this.controlSelectors(); - } else; - - if(this.queuePosition !== '') { - ReactDOM.render(this.queueView, this.queuePosition, ()=>console.log("rendered Que at:", this.queuePosition.id)); - this.queueSelectors(); - }; - - if(this.sbPosition !== '') { - ReactDOM.render(this.scoreboardView, this.controlPosition); - }; - - return this; - }; - - virtualControlPanel(state) { - this.state = state || this.state; - console.log("state from virtualControlPanel: ", this.state) - if(this.state < 2){ - this.controlPanel = Comps.Ctr() - } else { - console.log('control panel: ', this.controlPanel) - this.controlPanel = Comps.Ctr(Comps.CtrFillSubject(this.model.subjects)) - console.log('control panel: ', this.controlPanel) - - }; - - return this; - }; - - virtualQueue() { - if(this.state > 2) { - this.queueView = Comps.QueueArea(this.model.Q, this.model.checkMultiplier) - }; - - return this; - }; - - virtualScoreboard() { - this.scoreboardView = ''; - - return this; - }; - - updateControlPanel() { - if(this.controlPosition !== '') { - ReactDOM.render(this.controlPanel, this.controlPosition) - this.controlSelectors(); - }; - - return this; - }; - - updateQueue() { - if(this.queuePosition !== '') { - ReactDOM.render(this.queueView, this.queuePosition) - this.queueSelectors(); - }; - - return this; - } - - controlSelectors() { - this.newSubjectField = document.getElementById('createSubject') - this.createSubjectButton = document.getElementById('create-subject-button') - if(this.state > 1) { - this.createTodoButton = document.getElementById('add-items'), - this.createTodo = {}, - - this.createTodo.subject = document.getElementById('subject-list'), - this.createTodo.category = document.getElementById('category-list'), - this.createTodo.todo = document.getElementById("category-input"), - this.createTodo.detail = document.getElementById('category-details'), - this.createTodo.due = document.getElementById('category-due'), - this.createTodo.point = document.getElementById('points-dropdown') - }; - - return this; - }; - - queueSelectors() { - - return this; - }; - - - - /** - * function checks to make sure the input fields on the subject panel - * have been properly entered. If not appends a message to guide the - * user to the bottom of the panel - */ - checkToDoInput() { - var parsedDate = Date.parse(this.createTodo.due.value); - console.log('date: ',parsedDate) - console.log('todays date: ',Date.parse(new Date) < parsedDate) - this.subjectToDo = document.getElementById('addToDo'); - if (isNaN(parsedDate) || this.createTodo.todo.value == '') { - console.log("childeren", this.subjectToDo.children.length); - if(this.subjectToDo.children.length == 5) { - var needDue = document.createElement("p"); - needDue.innerText = 'valid To-Do and Due Date are required to create a new To-Do item'; - this.subjectToDo.append(needDue); - }; - - return false; - } else if(this.subjectToDo.children.length > 5) { - this.subjectToDo.removeChild(this.subjectToDo.lastChild); - }; - return true; - }; - - - -}; - -export {View} \ No newline at end of file diff --git a/src/public/javascript/mvc/views/view_queue.js b/src/public/javascript/mvc/views/view_queue.js deleted file mode 100644 index 4df4a2a..0000000 --- a/src/public/javascript/mvc/views/view_queue.js +++ /dev/null @@ -1,109 +0,0 @@ -'use strict'; - -export {ViewQueue}; -import {queTemplate} from './templates.js'; - -class ViewQueue { - constructor(){ - this.categories = ['Homework', 'Projects', 'Reading', 'Tests', 'Videos']; - this.fields = ['id', 'due', 'todo', 'subject', 'delete', 'complete', 'details', 'points', 'multiplier']; - this.id = document.getElementById('que-list') - return this; - }; - - - build() { - this.categories.forEach((x) => { - var newQue = document.createElement('div'); - newQue.id = 'que'; - newQue.innerHTML = queTemplate(x); - this.id.append(newQue); - }); - - return this; - }; - - - selectors() { - let ids = ['#homework-que', '#project-que', '#reading-que', '#test-que', '#video-que']; - let classes = ['.que-category', '.que-due', '.que-todo', '.que-subject', '.delete', '.complete', '.que-details', '.points', '.que-multiplier']; - - this.categories.forEach((x, i) => { - this[x] = {}; - this.fields.forEach((y, j) => { - this[x][y] = document.querySelector(`${ids[i]} ${classes[j]}`) - }); - }); - - return this; - }; - - - populate(queue, checkMultiplier) { - var queue = queue || {Homework: [], Projects: [], Reading: [], Tests: [], Videos: []}; - - this.categories.forEach((x) => { - if (queue[x][0]) { - this.fields.forEach((y, j) => { - if (j == 2 || j == 3 || j == 6 || j == 7 ) { - this[x][y].innerText = `${queue[x][0][y]}`; - } else if (j == 1) { - this[x][y].innerText = `Due Date: ${queue[x][0][y].getMonth() + 1}/${queue[x][0][y].getDate()}`; - } else if (j == 8) { - this[x][y].innerText = `x${checkMultiplier(queue[x][0].due)}`; - }; - }); - }; - }); - return this; - }; - - - clean(category) { - this[category].due.innerText = 'Due Date: '; - this[category].subject.innerText = ''; - this[category].todo.innerText = 'Nothing'; - this[category].details.innerText = 'None'; - this[category].points.innerText = '0'; - this[category].multiplier.innerText = 'x0'; - - return this; - }; - - - listener(queue, queueHandler, checkMultiplier, score, populateSB) { - this.categories.forEach((x) => { - var deleteButton = this[x].delete; - var completeButton = this[x].complete; - deleteButton.addEventListener('click', (event) => { - queueHandler(x, 'delete'); - this.clean(x); - this.populate(queue, checkMultiplier) - }); - completeButton.addEventListener('click', (event) => { - queueHandler(x, 'complete'); - this.clean(x); - this.populate(queue, checkMultiplier); - populateSB(score); - }); - }); - return this; - }; - - // completeButton() { - - // return this; - // }; - - // deleteButton() { - - // return this; - // }; - - delete() { - this.id.innerHTML = ''; - - return this; - }; - -}; \ No newline at end of file diff --git a/src/public/javascript/mvc/views/view_schedule.js b/src/public/javascript/mvc/views/view_schedule.js deleted file mode 100644 index e69de29..0000000 diff --git a/src/public/javascript/mvc/views/view_scoreboard.js b/src/public/javascript/mvc/views/view_scoreboard.js deleted file mode 100644 index 6891248..0000000 --- a/src/public/javascript/mvc/views/view_scoreboard.js +++ /dev/null @@ -1,114 +0,0 @@ -'use strict' - -export {ViewScore}; - -function scoreboard(score) { - - var score = score || { - "Monday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Tuesday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Wednesday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Thursday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Friday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Saturday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Sunday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Total" : {"Points": 0, "Last Week": 0, "Historic High": 0}, - "Historic Total": {"Points": 0, "Last Week": 0, "Historic High": 0} - }; - - - var values = [ - ['Day' , 'Points' , 'Last Week' , 'Historic High'], - ["Mon:" , score['Monday']['Points'] , score['Monday']['Last Week'] , score['Monday']['Historic High']], - ["Tues:" , score['Tuesday']['Points'] , score['Tuesday']['Last Week'] , score['Tuesday']['Historic High']], - ["Weds:" , score['Wednesday']['Points'] , score['Wednesday']['Last Week'] , score['Wednesday']['Historic High']], - ["Thurs:" , score['Thursday']['Points'] , score['Thursday']['Last Week'] , score['Thursday']['Historic High']], - ["Fri:" , score['Friday']['Points'] , score['Friday']['Last Week'] , score['Friday']['Historic High']], - ["Sat:" , score['Saturday']['Points'] , score['Saturday']['Last Week'] , score['Saturday']['Historic High']], - ["Sun:" , score['Sunday']['Points'] , score['Sunday']['Last Week'] , score['Sunday']['Historic High']], - ["Total:" , score['Total']['Points'] , score['Total']['Last Week'] , score['Total']['Historic High']], - ["Historic:", score['Historic Total']['Points'], score['Historic Total']['Last Week'], score['Historic Total']['Historic High']] - ] - - var columnIDs = [ - ['rows' , 'th'], - ['points' , 'td'], - ['totals_prev' , 'td'], - ['totals_historic_column', 'td'] - ] - - var rowIDs = [ - 'columns', - 'monday', - 'tuesday', - 'wednesday', - 'thursday', - 'friday', - 'saturday', - 'sunday', - 'totals_row', - 'totals_historic_row', - ] - - var table = React.createElement( - 'table', - {'class': 'table table-dark table-hover', 'key':'Scoreboard_View'}, - rowIDs.map((x, i) => { - // make rows - return React.createElement( - 'tbody', - {key: `tbody_${x}_${i}`}, - React.createElement( - 'tr', - {'id': x, key: `${x}_${i}`}, - columnIDs.map((y, j) => { - // Make columns; first Column uses 'th' tag - if (j > 0) { - return React.createElement( - i>0? 'td': 'th', - {'class': y[0], key: `${y}_${j}`}, - values[i][j] - ) - } else { - return React.createElement( - y[1], - {'class': y[0], key: `${y}_${j}`}, - values[i][j] - ); - }; - }) - ) - ) - }) - ); - return table; -} - - -class ViewScore { - constructor() { - - return this; - }; - - build() { - - return this; - }; - - selectors() { - - return this; - }; - - populate(score) { - - return this; - }; - - delete() { - - return this; - }; - -}; \ No newline at end of file diff --git a/src/public/javascript/planner.js b/src/public/javascript/planner.js deleted file mode 100644 index 0872a36..0000000 --- a/src/public/javascript/planner.js +++ /dev/null @@ -1,5 +0,0 @@ -import {Model} from './mvc/models/model.js'; -import {View} from './mvc/views/view.js'; -import {Controller} from './mvc/controller/controller.js'; - -const Planner = new Controller(new Model, new View); diff --git a/backup/public/scoreboard.js b/src/public/javascript/scoreboard.js similarity index 99% rename from backup/public/scoreboard.js rename to src/public/javascript/scoreboard.js index 54401f7..c15ef21 100644 --- a/backup/public/scoreboard.js +++ b/src/public/javascript/scoreboard.js @@ -67,6 +67,7 @@ class Scoreboard { * returns Scoreboard to allow for Method Chaining */ constructor(currentScore) { + console.log('hello from scoreboard') this.score = currentScore || { "Monday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, "Tuesday" : {"Points": 0, "Last Week": 0, "Historic High": 0}, diff --git a/backup/public/templates.js b/src/public/javascript/templates.js similarity index 99% rename from backup/public/templates.js rename to src/public/javascript/templates.js index fcd7b45..a110bd0 100644 --- a/backup/public/templates.js +++ b/src/public/javascript/templates.js @@ -9,6 +9,7 @@ export {template, queTemplate} function template(stringName) { + console.log("hello from template") if (stringName == 'subject-panel') { var temp = `
diff --git a/src/public/javascript/test.js b/src/public/javascript/test.js new file mode 100644 index 0000000..7735cb0 --- /dev/null +++ b/src/public/javascript/test.js @@ -0,0 +1,212 @@ +/* +************************************************************************** +Assignment +James Halladay +Advanced Programming with JavaScript +Date: + + +************************************************************************** +Steps: + +************************************************************************** +*/ + +import {deepEqual} from 'assert'; // If using node v13.2 or above comment out, else uncomment +import {Scoreboard} from "./scoreboard.js" // If using node v13.2 or above comment out, else uncomment + +'use strict' + +// const assert = require("assert").strict; + + +/** + * deepTester :: (object, object, string, number) -> bool + * + * function compares one object to another while using + * the passed in string and number to inform the tester + * of the results of the test + * + * returns true if test passes, otherwise returns false + */ +function deepTester(comp, compTo, name, set) { + try { + // assert.deepEqual(comp, compTo) // If using node v13.2 or above comment out, else uncomment + deepEqual(comp, compTo) // If not using node v13 or above comment out, else uncomment + console.log(`\t${name}, Deep Assert ${set}: Passed`); + return true; + } catch { + console.log(`\t\t${name}, Deep Assert ${set}: Failed`); + return false; + }; +}; + + +/** + * testScoreboard :: void -> bool + * + * function tests the methods of the class Scoreboard + * + * returns true if all tests pass, otherwise returns false + */ +function testScoreboard() { + // const sb = require("./scoreboard.js"); // If using node v13.2 or above comment out, else uncomment + // var testBoard = new sb.Scoreboard; // If using node v13.2 or above comment out, else uncomment + var testBoard = new Scoreboard; // If not using node v13 or above comment out, else uncomment + var tScore = testBoard.score; + var fPass = true; + + // Comparison values to test against + var scoreBefore1 = {"Monday":{"Points":30,"Last Week":0,"Historic High":30},"Tuesday":{"Points":30,"Last Week":0,"Historic High":30},"Wednesday":{"Points":30,"Last Week":0,"Historic High":30},"Thursday":{"Points":30,"Last Week":0,"Historic High":30},"Friday":{"Points":30,"Last Week":0,"Historic High":30},"Saturday":{"Points":30,"Last Week":0,"Historic High":30},"Sunday":{"Points":30,"Last Week":0,"Historic High":30},"Total":{"Points":210,"Last Week":0,"Historic High":210},"Historic Total":{"Points":210,"Last Week":0,"Historic High":210}}; + var scoreBefore2 = {"Monday":{"Points":60,"Last Week":0,"Historic High":60},"Tuesday":{"Points":60,"Last Week":0,"Historic High":60},"Wednesday":{"Points":60,"Last Week":0,"Historic High":60},"Thursday":{"Points":60,"Last Week":0,"Historic High":60},"Friday":{"Points":60,"Last Week":0,"Historic High":60},"Saturday":{"Points":60,"Last Week":0,"Historic High":60},"Sunday":{"Points":60,"Last Week":0,"Historic High":60},"Total":{"Points":420,"Last Week":0,"Historic High":420},"Historic Total":{"Points":420,"Last Week":0,"Historic High":420}}; + var scoreAfter1 = {"Monday":{"Points":0,"Last Week":30,"Historic High":30},"Tuesday":{"Points":0,"Last Week":30,"Historic High":30},"Wednesday":{"Points":0,"Last Week":30,"Historic High":30},"Thursday":{"Points":0,"Last Week":30,"Historic High":30},"Friday":{"Points":0,"Last Week":30,"Historic High":30},"Saturday":{"Points":0,"Last Week":30,"Historic High":30},"Sunday":{"Points":0,"Last Week":30,"Historic High":30},"Total":{"Points":0,"Last Week":210,"Historic High":210},"Historic Total":{"Points":210,"Last Week":210,"Historic High":210}}; + var scoreAfter2 = {"Monday":{"Points":0,"Last Week":30,"Historic High":30},"Tuesday":{"Points":0,"Last Week":30,"Historic High":30},"Wednesday":{"Points":0,"Last Week":30,"Historic High":30},"Thursday":{"Points":0,"Last Week":30,"Historic High":30},"Friday":{"Points":0,"Last Week":30,"Historic High":30},"Saturday":{"Points":0,"Last Week":30,"Historic High":30},"Sunday":{"Points":0,"Last Week":30,"Historic High":30},"Total":{"Points":0,"Last Week":210,"Historic High":210},"Historic Total":{"Points":420,"Last Week":420,"Historic High":420}}; + + // Helper function to increment the value of the testBoard object + function incrementScore(x) { + var inc = x || 30; + + tScore.Monday.Points += inc; + tScore.Tuesday.Points += inc; + tScore.Wednesday.Points += inc; + tScore.Thursday.Points += inc; + tScore.Friday.Points += inc; + tScore.Saturday.Points += inc; + tScore.Sunday.Points += inc; + }; + + + console.log("Testing Scoreboard Class:"); + console.log("\nTesting Scoreboard.setTotals Method:\n"); + + if (fPass) { + incrementScore(); + testBoard.setTotals(); + fPass = deepTester(tScore, scoreBefore1, "Scoreboard.setTotals", 1); + }; + + if (fPass) { + incrementScore(); + testBoard.setTotals(); + fPass = deepTester(tScore, scoreBefore2, "Scoreboard.setTotals", 2); + }; + + if (!fPass) { + return false; + }; + + // var testBoard = new sb.Scoreboard; // If using node v13.2 or above comment out, else uncomment + var testBoard = new Scoreboard; // If not using node v13 or above comment out, else uncomment + var tScore = testBoard.score; + + console.log("\nTesting Scoreboard.setNextWeek Method:\n"); + + if (fPass) { + incrementScore(); + testBoard.setTotals().setNewWeek(); + fPass = deepTester(tScore, scoreAfter1, "Scoreboard.setNextWeek", 1); + }; + + if (fPass) { + incrementScore(); + testBoard.setTotals().setNewWeek(); + fPass = deepTester(tScore, scoreAfter2, "Scoreboard.setNextWeek", 2); + }; + + if (!fPass) { + return false; + }; + + console.log("\nTesting Scoreboard.checkDay Method:\n"); + + // var testBoard = new sb.Scoreboard; // If using node v13.2 or above comment out, else uncomment + var testBoard = new Scoreboard; // If not using node v13 or above comment out, else uncomment + var tScore = testBoard.score; + var date = testBoard.weekday[new Date().getDay()] + + if (fPass) { + fPass = deepTester(testBoard.currentDay, date, "Scoreboard.checkDay", 1) + }; + + if (fPass) { + date = "Thursday"; + testBoard.checkDay("Thursday"); + fPass = deepTester(testBoard.currentDay, date, "Scoreboard.checkDay", 2) + }; + + if (fPass) { + testBoard.checkDay("Wednesday"); + fPass = deepTester(testBoard.currentDay, "Wednesday", "Scoreboard.checkDay", 3) + }; + + if (fPass) { + incrementScore(); + testBoard.checkDay("Monday"); + fPass = deepTester(tScore, scoreAfter1, "Scoreboard.checkDay", 4); + }; + + if (fPass) { + incrementScore(); + testBoard.checkDay("Sunday"); + testBoard.checkDay("Monday"); + fPass = deepTester(tScore, scoreAfter2, "Scoreboard.checkDay", 5); + }; + + + return fPass; +}; + + +/** + * testRunner :: (Function, string) -> Bool + * + * Function runs the passed in function and informs the + * tester of the results test. + * + * returns true if the Function passed in returns true + * otherwise returns false + */ +function testRunner(testFunc, name) { + if (testFunc()) { + console.log(`\nTests on ${name}: Passed\n`); + return true; + } else { + console.log(`\n\tTests on ${name}: Failed\n`); + return false; + }; +}; + + +/** + * unitTest :: void -> void + * + * Function executes unit tests on classes, methods, and functions + */ +function unitTest() { + var pass = true; + + if (pass) { + pass = testRunner(testScoreboard, "Scoreboard"); + } + + if (pass) { + console.log("All test cases passed"); + } else { + console.log("TEST FAILED!!"); + }; +}; + + +/** + * launch :: void -> void + * + * Function checks if it is being run natively with the test argument + * if test argument is given it runs the tests + */ +;(function launch() { + // if (require.main == module) { // If using node v13 comment out, else uncomment + if (process.argv.length > 2 && process.argv[2] == 'test') { + unitTest(); + }; + // }; // If using node v13 comment out, else uncomment +}()); \ No newline at end of file diff --git a/src/views/layout.ejs b/src/views/layout.ejs index d3568a2..954331b 100644 --- a/src/views/layout.ejs +++ b/src/views/layout.ejs @@ -26,7 +26,7 @@ -