From e24937ba2dc52e431f35797a19d3fb6ffc7049a2 Mon Sep 17 00:00:00 2001 From: Daniel Caffrey Date: Mon, 9 Sep 2019 11:50:37 -0400 Subject: [PATCH] Submission of Assignment 2 --- README.md | 96 ++++------------------ package.json | 8 +- pnpm-debug.log | 15 ++++ public/css/style.css | 2 +- public/index.html | 190 +++++++++++++++++++++++++++++++++++++++---- server.improved.js | 135 ++++++++++++++++++++++++++---- shrinkwrap.yaml | 15 ++++ 7 files changed, 345 insertions(+), 116 deletions(-) create mode 100644 pnpm-debug.log create mode 100644 shrinkwrap.yaml diff --git a/README.md b/README.md index 2ccf40cb..6d549691 100755 --- a/README.md +++ b/README.md @@ -1,87 +1,27 @@ -Assignment 2 - Short Stack: Basic Two-tier Web Application using HTML/CSS/JS and Node.js -=== -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. +## Power Usage Database -Baseline Requirements ---- +The website allows the user to enter voltage and current reading, and power is calculated. +The backend architecture is established for a system that can track the power usage of certain appliances +The UI allows the user to not only submit data, but also modify and delete is, as well as retrieve all of the data currenlty stored in the server +In the future, graphs could be generated to better display to the user exactly how their power is being used -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. +Notes: + 1) I could not get a seperate CSS stylesheet to work, so all of my styling is in a style tag at the top of index.html + 2) Something must be entered into the "Remove a reading" form before hitting the button, otherwise the site will break. All other forms can be submitted with no data entered and be fine -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-yourTeamName` so we can find it. -6. Modify the Readme to the specifications below. -7. Create and submit a Pull Request to the original repo. Only one member needs to submit a pull request. - -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 +http://a2-danielcaffrey.glitch.me ## Technical Achievements -- **Tech Achievement 1**: Using a combination of... -- **Tech Achievement 2**: ... +- **Tech Achievement 1**: Using basic HTML forms, created a user interface that allows a user to add, delete, or modify data +- **Tech Achievement 2**: Using an HTML table and button, created a user interface that allows a user to see the data currently stored on the server +- **Tech Achievement 3**: Using an HTML paragraph text object, created an area to display to the user the communication that the website has recieved from the server +- **Tech Achievement 4**: Using an array, maintained a server database of data submitted by the user +- **Tech Achievement 5**: Calculated the power value based on the given Voltage and Current +- **Tech Achievement 6**: Implementation of error correction for added Voltage and Current values that prevents a value of 0 from being entered. This also accounts for nothing being sent in these two fields ### 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**: Shown in the style tag of the HTML doc, Element Selectors are used to center the headings and forms +- **Design Achievement 2**: ID Selectors are used to implement a grid layout over the "Respone from Server" and "Data form Server" sections of the website. This places these sections side by side +- **Design Achievement 3**: Class Selectors are used to add a border to the "Respone from Server" and "Data form Server" sections of the website diff --git a/package.json b/package.json index 988f135f..fb2a5292 100755 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { - "name": "", - "version": "", - "description": "", - "author": "", + "name": "Daniel Caffrey", + "version": "1.0", + "description": "A client-server based power monitoring website", + "author": "Daniel Caffrey", "scripts": { "start": "node server.improved.js" }, diff --git a/pnpm-debug.log b/pnpm-debug.log new file mode 100644 index 00000000..4a76a982 --- /dev/null +++ b/pnpm-debug.log @@ -0,0 +1,15 @@ +--- + 0 debug pnpm:scope: + selected: 1 + workspacePrefix: null + 1 info pnpm: + message: "A store server is running. All store manipulations are delegated to it." + prefix: "/app" + 2 error pnpm: + message: + code: "ERR_PNPM_BAD_PACKAGE_JSON" + err: + name: "Error" + message: "/app/package.json: Invalid name: \"Daniel Caffrey\"" + code: "ERR_PNPM_BAD_PACKAGE_JSON" + stack: "Error: /app/package.json: Invalid name: \"Daniel Caffrey\"\n at Object. (/opt/nvm/versions/node/v10.15.3/lib/node_modules/pnpm/lib/node_modules/@pnpm/read-package-json/lib/index.js:23:31)\n at Generator.throw ()\n at rejected (/opt/nvm/versions/node/v10.15.3/lib/node_modules/pnpm/lib/node_modules/@pnpm/read-package-json/lib/index.js:5:65)" diff --git a/public/css/style.css b/public/css/style.css index d5f842ab..36a5f292 100755 --- a/public/css/style.css +++ b/public/css/style.css @@ -1 +1 @@ -/*Style your own assignment! This is fun! */ \ No newline at end of file +/*Style your own assignment! This is fun! */ diff --git a/public/index.html b/public/index.html index c56d620e..8681c3d1 100755 --- a/public/index.html +++ b/public/index.html @@ -1,40 +1,198 @@ + + + CS4241 Assignment 2 -
- - -
+ +

Power Usage Database

+

Add a reading

+
+
+
+
+
+ +
+ +

Remove a reading

+
+
+ +
+ +

Modfy a reading

+
+
+
+
+
+
+

+
+ +
+
+

Response from the server:

+


+
+ +
+

Retrieve Data from Server

+
+ +

+
+
+
+ diff --git a/server.improved.js b/server.improved.js index 26673fc0..09520db2 100644 --- a/server.improved.js +++ b/server.improved.js @@ -6,26 +6,28 @@ const http = require( 'http' ), 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 appData = [ + {'date': '04/03/98', 'time': '13:30', 'voltage': 2, 'current': 1 , 'power': 2,'id':1}, + {'date': '12/17/01','time': '13:35', 'voltage': 2.3, 'current': 2, 'power': 9.2,'id':2 }, + {'date': '6/19/12','time': '13:40', 'voltage': 2.5, 'current': 3, 'power': 22.5,'id':3 } ] const server = http.createServer( function( request,response ) { if( request.method === 'GET' ) { handleGet( request, response ) - }else if( request.method === 'POST' ){ + } + else if( request.method === 'POST' ){ handlePost( request, response ) } }) + const handleGet = function( request, response ) { const filename = dir + request.url.slice( 1 ) - if( request.url === '/' ) { sendFile( response, 'public/index.html' ) - }else{ + } + else{ sendFile( response, filename ) } } @@ -34,16 +36,115 @@ const handlePost = function( request, response ) { let dataString = '' request.on( 'data', function( data ) { - dataString += data + dataString += data //Sometimes data must be sent in multiple parts, this listens for all parts }) request.on( 'end', function() { - console.log( JSON.parse( dataString ) ) - - // ... do something with the data here!!! - - response.writeHead( 200, "OK", {'Content-Type': 'text/plain' }) - response.end() + if (request.url === "/addData") { + const json = JSON.parse( dataString ) //Outputs an object + const volt = Number(json.voltage), + curr = Number(json.current), + [year, month, day] = json.date.split("/"), + [hours, minutes, seconds] = json.time.split(":") + + let error = "" + if (volt <=0){ error += "Invalid Voltage value. " } + if (curr <=0){ error += "Invalid Current value. " } + + if (error !== "" ){ + error += "Data will not be recorded" + response.writeHead(400, 'OK', {'Content-Type': 'text/plain' }) //Write a reponse back to client + response.write(error) + response.end() + } + else{ + const power = json.voltage * json.current * json.current + json.power = power + let id =0 + for (let entry of appData){ + console.log + if (entry.id > id){ + id =entry.id +1 + } + } + json["id"]= id + appData.push(json) + response.writeHead( 200, "OK", {'Content-Type': 'text/plain' }) //Write a reponse back to client + response.write("Data has been recorded") + response.end() + } + } + + else if (request.url === "/delData"){ + const json = JSON.parse( dataString ) //Outputs an object + + if (json == false){ + response.writeHead( 401, "OK", {'Content-Type': 'text/plain' }) //Write a reponse back to client + response.write("Error: No ID given") + response.end() + } + else{ + console.log(json) + let index = 0 + for (let json of appData){ + console.log(json.id) + if (json.id == Number(dataString)){ + appData.splice(index, 1) + console.log("something deleted") + } + index++ + } + response.writeHead( 200, "OK", {'Content-Type': 'text/plain' }) //Write a reponse back to client + response.write("Record(s) with the given Id have been removed") + response.end() + } + } + + else if (request.url === "/getData"){ + response.writeHead( 200, "OK", {'Content-Type': 'text/plain' }) //Write a reponse back to client + response.write(JSON.stringify(appData)) + response.end() + } + + else if (request.url === "/modData"){ + const json = JSON.parse( dataString ) //Outputs an object + const volt = Number(json.voltage), + curr = Number(json.current), + date = json.date, + time = json.time + + let error = "" + if (volt <=0){error += "Invalid Voltage value. "} + + if (curr <=0){ error += "Invalid Current value. "} + + if (error !== "" ){ + error += "Data will not be modified" + response.writeHead(400, 'OK', {'Content-Type': 'text/plain' }) //Write a reponse back to client + response.write(error) + response.end() + } + else{ + const power = json.voltage * json.current * json.current + json["power"] = power + let index = 0 + for (let entry of appData){ + console.log(entry.id) + console.log(json.id) + if (entry.id == json.id){ + appData[index].date = date + appData[index].time = time + appData[index].voltage = volt + appData[index].current = curr + appData[index].power = power + index ++ + } + } + response.writeHead( 200, "OK", {'Content-Type': 'text/plain' }) //Write a reponse back to client + response.write("Data has been recorded") + response.end() + } + } }) } @@ -57,9 +158,9 @@ const sendFile = function( response, filename ) { // status code: https://httpstatuses.com response.writeHeader( 200, { 'Content-Type': type }) - response.end( content ) - - }else{ + response.end( content ) // This will be sent back, it is helpful to pass an array + } + else{ // file not found, error code 404 response.writeHeader( 404 ) diff --git a/shrinkwrap.yaml b/shrinkwrap.yaml new file mode 100644 index 00000000..86c7048d --- /dev/null +++ b/shrinkwrap.yaml @@ -0,0 +1,15 @@ +dependencies: + mime: 2.4.4 +packages: + /mime/2.4.4: + dev: false + engines: + node: '>=4.0.0' + hasBin: true + resolution: + integrity: sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== +registry: 'https://registry.npmjs.org/' +shrinkwrapMinorVersion: 9 +shrinkwrapVersion: 3 +specifiers: + mime: ^2.4.4