diff --git a/README.md b/README.md
index 304a16f1..50ed4cd5 100755
--- a/README.md
+++ b/README.md
@@ -1,89 +1,16 @@
-Assignment 2 - Short Stack: Basic Two-tier Web Application using HTML/CSS/JS and Node.js
-===
+## Generic Leaderboard
+https://csmbrad-a2-shortstack.glitch.me/
-Due: September 9th, by 11:59 AM.
+This project is meant to be a simple time-based leaderboard. Grids are used to position the elements, and a Table is used to create ther results.
+The derived field is calculated server side. there are 2 derived fields, one with the position of the time and the other the difference from first place.
+at least, that's how the derived fields should be.
+I could not get the results to show up in the table, trying to request them at the start makes the site hang and I can't figure out why.
+The server does support adding, removing, and editing entries.
-This assignment aims to introduce you to the concepts and practice involved in creating a prototype (i.e. not deployment ready) two-tiered web application.
-
-The baseline aims of this assignment involve creating an application that demonstrates the use of several specific pieces of HTML, CSS, JavaScript, and Node.js functionality.
-Another aim of this assignment is to establish creative boundaries in which you and your partner can explore designing, implementing, and evaluating usable, useful, novel, and technically efficient web applications.
-
-Baseline Requirements
----
-
-Note that there is a very large range of application areas and possibilities that meet these baseline requirements.
-Games, internet of things, organizational tools, commerce, media - all are possibilities with a two-tiered form-focused web application.
-
-Do not limit yourselves to any of the examples given below.
-Examples like the upcoming `efficiency_ratio` idea for the `cars` dataset are meant to be illustrative and easy to understand.
-They are not intended to be sensible or useful ideas.
-
-Your application is required to implement the following functionalities:
-
-- a `Server` which not only serves files, but also maintains a tabular dataset with 3 or more fields related to your application
-- a `Results` functionality which shows the entire dataset residing in the server's memory
-- a `Form/Entry` functionality which allows a user to add, modify, or delete data items residing in the server's memory
-- a `Server Logic` which, upon receiving new or modified "incoming" data, includes and uses a function that adds at least one additional derived field to this incoming data before integrating it with the existing dataset
- - the `Derived field` for a new row of data must be computed based on fields already existing in the row. For example, a `cars` dataset with `year`, `horsepower`, and `fuel_efficiency` may create a new field `efficiency_ratio` by dividing `fuel_efficiency` by `horsepower`
-
-Your application is required to demonstrate the use of the following concepts:
-
-HTML:
-- One or more [HTML Forms](https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms), with any combination of form tags appropriate for the user input portion of the application
- - Clarification: the results page can be implemented in any way. `
`s, `table`s, and `list`s are common choices
-
-CSS:
-- CSS styling of the primary visual elements in the application
-- Various CSS Selector functionality must be demonstrated:
- - Element selectors
- - ID selectors
- - Class selectors
-- CSS positioning and sizing of the primary visual elements in the application:
- - CSS to cause at least one element to be horizontally centered on the page
- - CSS to cause at least one pair of elements to appear side-by-side
- - CSS defined in a maintainable, readable form, in external stylesheets
-
-JavaScript:
-- At minimum, a small amount of front-end JavaScript to get / fetch data from the server; a sample is provided in this repository.
-
-Node.js:
-- An HTTP Server that delivers all necessary files and data for the application. A starting point is provided in this repository.
-
-Deliverables
----
-
-Do the following to complete this assignment:
-
-1. Fork the starting project code. This repo contains some starter code that may be used or discarded as needed.
-2. Implement your project with the above requirements.
-3. Test your project to make sure that when someone goes to your main page, it displays correctly.
-4. Deploy your project to Glitch, and fill in the appropriate fields in your package.json file.
-5. Ensure that your project has the proper naming scheme `a2-yourname` so we can find it.
-6. Modify the Readme to the specifications below.
-7. Create and submit a Pull Request to the original repo. Label the pull request as follows: a2-gitusername-firstname-lastname
-
-Sample Readme (delete the above when you're ready to submit, and modify the below so with your links and descriptions)
----
-
-## Your Web Application Title
-Include a very brief summary of your project here.
-Images are encouraged, along with concise, high-level text.
-
-Here is a sample formula for summarizing your activities, talk about:
-- the domain area the project pertains to
-- the main challenges or problems the application addresses
-- the key innovations that make it possible to address the problem
-- the main results of the implementation, does it really address the problem?
-- any additional implications of the resulting application, or possibly areas for future work that have been discovered as part of the design and implementation activities
-
-(Note that when I use the above formula, I aim to have only one sentence per thought in order to remain concise.)
-
-http://a2-charlieroberts.glitch.me
+I believe my sortdata function on the server side is borked. That and my table display doesn't work. I would appreciate feedback on these issues, as I can't figure it out.
## Technical Achievements
-- **Tech Achievement 1**: Using a combination of...
-- **Tech Achievement 2**: ...
+- **Tech Achievement 1**: Created a single page app with an HTML form to input fields and buttons. The server has methods for adding, deleting, and editing entries.
### Design/Evaluation Achievements
-- **Design Achievement 1**: Shown in `style.css`, the code...
-- **Design Achievement 2**: We tested the application with n=X users, finding that...
+- **Design Achievement 1**: Not enough time.
diff --git a/public/css/style.css b/public/css/style.css
index d5f842ab..dff1c070 100755
--- a/public/css/style.css
+++ b/public/css/style.css
@@ -1 +1,168 @@
-/*Style your own assignment! This is fun! */
\ No newline at end of file
+/*Style your own assignment! This is fun! */
+body {
+ font-family: "PT Sans Caption", sans-serif;
+ background: #e1f5fe;
+}
+h1 {
+ text-shadow: -2px 2px lightgrey;
+}
+
+.mainGrid {
+ display: inline-grid;
+ grid-template-areas:
+ "header header"
+ "info results"
+ "form results"
+ "blank results";
+ grid-template-rows: auto auto auto minmax(10px, auto);
+ grid-template-columns: 25% 75%;
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ /*border: 1px dashed lightgray; /* debug */
+}
+
+.headerGrid {
+ background: #eeeeee;
+ grid-area: header;
+ display: grid;
+ justify-content: center;
+ algin-content: center;
+ margin: 0 0 0.5% 0;
+ border-radius: 10px;
+ border: 1px solid #bcbcbc; /* debug */
+}
+
+.infoGrid {
+ background: #eeeeee;
+ grid-area: info;
+ display: grid;
+ margin: 0 0 2% 0;
+ border-top-left-radius: 10px;
+ border-bottom-left-radius: 10px;
+ border: 1px solid #bcbcbc; /* debug */
+ border-right: 0;
+}
+.infoTitle {
+ margin-left: 2.5%;
+ margin-bottom: -6px;
+}
+.infoText {
+ margin-left: 2.5%;
+}
+
+.formGrid {
+ background: #eeeeee;
+ grid-area: form;
+ display: grid;
+ margin: 0%;
+ border-top-left-radius: 10px;
+ border-bottom-left-radius: 10px;
+ border: 1px solid #bcbcbc; /* debug */
+ border-right: 0;
+}
+
+.resultGrid {
+ background: #eeeeee;
+ grid-area: results;
+ display: grid;
+ margin: 0;
+ margin-right: 0;
+ border-top-right-radius: 10px;
+ border-bottom-right-radius: 10px;
+ border-bottom-left-radius: 10px;
+ border: 1px solid #bcbcbc; /* debug */
+ grid-template-areas:
+ "lbTitle"
+ "lbTable";
+ grid-template-rows: 55px auto;
+}
+.leaderboardTitle {
+ margin-left: 2.5%;
+ margin-bottom: 0px;
+}
+.lbTitle {
+ grid-area: lbTitle;
+
+}
+.lbTable {
+ grid-area: lbTable;
+}
+
+table {
+ *border-collapse: collapse; /* IE7 and lower */
+ border-spacing: 0;
+ width: 95%;
+ margin-left: 2.5%;
+ background: ghostwhite;
+ margin-top: ;
+}
+th {
+ border: 1px solid #bcbcbc;
+ background: #lightgrey;
+}
+th:first-child {
+ border-radius: 6px 0 0 0;
+ border: 1px solid #bcbcbc;
+}
+th:last-child {
+ border-radius: 0 6px 0 0;
+ border: 1px solid #bcbcbc;
+}
+th:only-child {
+ border-radius: 6px 6px 0 0;
+ border: 1px solid #bcbcbc;
+}
+tr:nth-child(even) {background-color: #f2f2f2;}
+
+.blankGrid {
+ /*this is just there so the result grid can expand and the form and info will remain the same */
+ grid-area: blank;
+ display: grid;
+ margin: 0;
+ margin-right: 0;
+ /*border: 1px dashed lightgray; /* debug */
+}
+
+input {
+ width: 90%;
+ margin: 0 5% 0 2.5%;
+ display: block;
+}
+
+label {
+ margin: 0 5% 0 2.5%;
+}
+
+button {
+ width: 90%;
+ margin: 2% 5% 0 4%;
+ border-radius: 5px;
+
+ transition-duration: 0.4s;
+}
+
+#submitButton {
+ background-color: #32cd32;
+ border: 2px solid #2db92d;
+}
+#submitButton:hover {
+ background-color: #2db92d;
+}
+
+#editButton {
+ background-color: darkOrange;
+ border: 2px solid #e67e00;
+}
+#editButton:hover {
+ background-color: #e67e00;
+}
+
+#delButton {
+ background-color: #cc0000;
+ border: 2px solid #990000;
+ margin-bottom: 2.5%;
+}
+#delButton:hover {
+ background-color: #990000;
+}
diff --git a/public/index.html b/public/index.html
index c56d620e..c14d90a8 100755
--- a/public/index.html
+++ b/public/index.html
@@ -1,41 +1,77 @@
-
+
CS4241 Assignment 2
-
+
+
+
-
-
-
-
diff --git a/public/js/scripts.js b/public/js/scripts.js
index de052eae..2ce0b5f7 100755
--- a/public/js/scripts.js
+++ b/public/js/scripts.js
@@ -1,3 +1,117 @@
// Add some Javascript code here, to run on the front end.
-console.log("Welcome to assignment 2!")
\ No newline at end of file
+console.log("Welcome to assignment 2!");
+
+
+const submit = function(e) {
+ // prevent default form action from being carried out
+ e.preventDefault();
+
+ //{ pos: 1, name: "Bill", time: 10, diff: 0, done: "Yes" },
+ const input = document.querySelector("#yourname"),
+ time = document.querySelector("#time"),
+ finished = document.querySelector("#loads"),
+ json = {
+ pos: 0,
+ name: input.value,
+ time: time.value,
+ diff: 0,
+ done: finished.value
+ },
+ body = JSON.stringify(json);
+
+ fetch("/submit", {
+ method: "POST",
+ body
+ }).then(function(response) {
+ // do something with the reponse
+ var incomingData = JSON.parse(response);
+ createTable(incomingData);
+ });
+
+ return false;
+};
+
+const edit = function(e) {
+ // prevent default form action from being carried out
+ e.preventDefault();
+
+ const input = document.querySelector("#yourname"),
+ time = document.querySelector("#time"),
+ finished = document.querySelector("#loads"),
+ json = {
+ pos: 0,
+ name: input.value,
+ time: time.value,
+ diff: 0,
+ done: finished.value
+ },
+ body = JSON.stringify(json);
+ fetch("/edit", {
+ method: "POST",
+ body
+ }).then(function(response) {
+ // do something with the reponse
+ var incomingData = JSON.parse(response);
+ createTable(incomingData);
+ });
+
+ return false;
+};
+
+const delFunc = function(e) {
+ // prevent default form action from being carried out
+ e.preventDefault();
+
+ const input = document.querySelector("#yourname"),
+ json = { name: input.value },
+ body = JSON.stringify(json);
+ fetch("/delete", {
+ method: "POST",
+ body
+ }).then(function(response) {
+ // do something with the reponse
+ var incomingData = JSON.parse(response);
+ createTable(incomingData);
+ });
+};
+
+window.onload = function() {
+ firstTime();
+ /*this was meant to try to fetch the data for the first time when the page loads. it doesn't work.*/
+ const submitButton = document.querySelector("#submitButton");
+ const editButton = document.querySelector("#editButton");
+ const delButton = document.querySelector("#delButton");
+
+ submitButton.onclick = submit;
+ editButton.onclick = edit;
+ delButton.onclick = delFunc;
+};
+
+const createTable = function(data) {
+ document.getElementById("lbBody").innerHTML = "";
+ var html = "";
+ data.forEach(function(e, i) {
+ html += "
" +
+ "
" + e.pos + "
" +
+ "
" + e.name + "
" +
+ "
" + e.time + "
" +
+ "
" + e.diff + "
" +
+ "
" + e.done + "
" +
+ "
";
+ });
+ document.getElementById("lbBody").innerHTML = html;
+};
+
+const firstTime = function() {
+ const json = {start:'start'},
+ body = JSON.stringify(json);
+ fetch("/start", {
+ method: "POST",
+ body
+ }).then(function(response) {
+ console.log(response);
+ /*var incomingData = JSON.parse(response);
+ createTable(incomingData);*/
+ });
+}
\ No newline at end of file
diff --git a/server.improved.js b/server.improved.js
index 26673fc0..f2f4bc12 100644
--- a/server.improved.js
+++ b/server.improved.js
@@ -1,72 +1,130 @@
-const http = require( 'http' ),
- fs = require( 'fs' ),
- // IMPORTANT: you must run `npm install` in the directory for this assignment
- // to install the mime library used in the following line of code
- mime = require( 'mime' ),
- dir = 'public/',
- port = 3000
+const http = require("http"),
+ fs = require("fs"),
+ mime = require("mime"),
+ dir = "public/",
+ port = 3000;
const appdata = [
- { 'model': 'toyota', 'year': 1999, 'mpg': 23 },
- { 'model': 'honda', 'year': 2004, 'mpg': 30 },
- { 'model': 'ford', 'year': 1987, 'mpg': 14}
-]
-
-const server = http.createServer( function( request,response ) {
- if( request.method === 'GET' ) {
- handleGet( request, response )
- }else if( request.method === 'POST' ){
- handlePost( request, response )
+ { pos: 1, name: "Bill", time: 10, diff: 0, done: "Yes" },
+ { pos: 2, name: "Bob", time: 14, diff: 4, done: "Yes" },
+ { pos: 3, name: "Jeb", time: 36, diff: 26, done: "Yes" }
+];
+
+const server = http.createServer(function(request, response) {
+ if (request.method === "GET") {
+ handleGet(request, response);
+ } else if (request.method === "POST") {
+ handlePost(request, response);
}
-})
+});
-const handleGet = function( request, response ) {
- const filename = dir + request.url.slice( 1 )
+const handleGet = function(request, response) {
+ const filename = dir + request.url.slice(1);
- if( request.url === '/' ) {
- sendFile( response, 'public/index.html' )
- }else{
- sendFile( response, filename )
+ if (request.url === "/") {
+ sendFile(response, "public/index.html");
+ } else if (request.url === "css/style.css") {
+ sendFile(response, "public/css/style.css");
+ } else {
+ sendFile(response, filename);
}
-}
-
-const handlePost = function( request, response ) {
- let dataString = ''
+};
- request.on( 'data', function( data ) {
- dataString += data
- })
+const handlePost = function(request, response) {
+ let dataString = "";
- request.on( 'end', function() {
- console.log( JSON.parse( dataString ) )
+ request.on("data", function(data) {
+ dataString += data;
+ console.log(dataString);
+ });
+ request.on("end", function() {
+ let incoming = JSON.parse(dataString);
+ let responseStr = "";
// ... do something with the data here!!!
-
- response.writeHead( 200, "OK", {'Content-Type': 'text/plain' })
- response.end()
- })
-}
-
-const sendFile = function( response, filename ) {
- const type = mime.getType( filename )
-
- fs.readFile( filename, function( err, content ) {
-
- // if the error = null, then we've loaded the file successfully
- if( err === null ) {
-
- // status code: https://httpstatuses.com
- response.writeHeader( 200, { 'Content-Type': type })
- response.end( content )
-
- }else{
-
- // file not found, error code 404
- response.writeHeader( 404 )
- response.end( '404 Error: File Not Found' )
-
- }
- })
-}
-
-server.listen( process.env.PORT || port )
+ if (request.url === "/submit") {
+ //new entry
+ addEntry(response, incoming);
+ } else if (request.url === "/edit") {
+ //edit existing entry
+ editEntry(response, incoming);
+ } else if (request.url === "/delete") {
+ //removing an entry
+ deleteEntry(response, incoming);
+ } else if (request.url === "/start") {
+ //send the data we have right away
+ sendAppdata(response);
+ }
+ });
+};
+
+const sendFile = function(response, filename) {
+ const type = mime.getType(filename);
+
+ fs.readFile(filename, function(err, content) {
+ // if the error = null, then we've loaded the file successfully
+ if (err === null) {
+ // status code: https://httpstatuses.com
+ response.writeHeader(200, { "Content-Type": type });
+ response.end(content);
+ } else {
+ // file not found, error code 404
+ response.writeHeader(404);
+ response.end("404 Error: File Not Found");
+ }
+ });
+};
+
+server.listen(process.env.PORT || port);
+
+const sortData = function() {
+ //sort the list in terms of which has the lowest time.
+ appdata.sort((e1, e2) => (e1.time > e2.time ? 1 : -1));
+ //assigning positon numbers and calculating time differences
+ for (let i = 0; i < appdata.length; i++) {
+ appdata[i].pos = i + 1;
+ if ((i = 0)) {
+ appdata[i].diff = 0;
+ } else {
+ appdata[i].diff = appdata[i].time - appdata[0].time;
+ }
+ }
+};
+
+const sendAppdata = function(response) {
+ //sortData(); //commenting out sortdata makes it work. no idea why sortdata is bad.
+ let data = JSON.stringify(appdata);
+ response.writeHeader(200, { "Content-Type": "text/plain" });
+ response.end(data);
+};
+
+const addEntry = function(response, input) {
+ appdata.push(input);
+ sendAppdata(response);
+};
+
+const editEntry = function(response, input) {
+ //first search for the entry to see if it exists, if it does modify it.
+ let found = false;
+ for (let i = 0; i < appdata.length; i++) {
+ if (appdata[i].name === input.name) {
+ //found it, update
+ found = true;
+ appdata[i] = input;
+ }
+ }
+ sendAppdata(response);
+};
+
+const deleteEntry = function(response, input) {
+ var index = -1;
+ for (var i = 0; i < appdata.length; i++) {
+ if (appdata[i]['name'] === input.name) {
+ index = i;
+ }
+ }
+ if (index > -1) {
+ appdata.splice(index, 1);
+ }
+ sendAppdata(response);
+};
diff --git a/shrinkwrap.yaml b/shrinkwrap.yaml
new file mode 100644
index 00000000..f6d7ea4f
--- /dev/null
+++ b/shrinkwrap.yaml
@@ -0,0 +1,15 @@
+dependencies:
+ mime: 2.4.6
+packages:
+ /mime/2.4.6:
+ dev: false
+ engines:
+ node: '>=4.0.0'
+ hasBin: true
+ resolution:
+ integrity: sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==
+registry: 'https://registry.npmjs.org/'
+shrinkwrapMinorVersion: 9
+shrinkwrapVersion: 3
+specifiers:
+ mime: ^2.4.4