0% found this document useful (0 votes)
18 views

Web322 Assignment3

WEB322 Ass3

Uploaded by

martinwong.work
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
18 views

Web322 Assignment3

WEB322 Ass3

Uploaded by

martinwong.work
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 7

WEB322 Assignment 3

Submission Deadline and Details:


View due date on BlackBoard. All submissions *MUST* be submitted via Blackboard in order to be graded. If you are late
submitting the assignment, you will be graded with a ZERO. There are no exceptions or extensions.

Assessment Weight:
9% of your final course Grade

Objective:
Build upon the foundation established in Assignment 2 by providing new routes / views to support adding items and
querying the data.

NOTE: If you are unable to start this assignment because Assignment 2 was incomplete - email your professor for a clean
version of the Assignment 2 files to start from (effectively removing any custom CSS or text added to your solution).

Specification:
For this assignment, we will be enhancing the functionality of Assignment 2 to include new routes & logic to handle the
code to add items. We will also add new routes & functionality to execute more focused queries for data (i.e. fetch an
item by id, all items by a category, etc.)

Part 1: Adding / Updating Static .html & Directories


Step 1: Modifying about.html
 Open the about.html file from within the "views" folder

 Add a HREF to your navigation bar that links to “/items/add” Ex:


o <a href="/items/add">Add Item</a>

Step 2: Adding a route in server.js to support the new view


 Inside your server.js file add the following route (HINT: do not forget __dirname & path.join):

o GET /items/add
 This route simply sends the file "/views/addItem.html"

o Use the template FORM at https://github.com/hscanlansen/Web322_Assignment_Files under AS3 to


insert into your addItem.html. This form will allow us to submit a new item.

Step 3: Adding new file: addItem.html


 Create a new file in your "views" directory called "addItem.html" and open it for editing
 Copy the contents of "about.html" and paste it in as a starting point.
 If you are using the template provided for “About,” add the “active” class to the link you created in Step 1. This
shows the user what page they are currently on by highlighting the link in the navbar. Ex:

Part 2: Adding Routes / Middleware to Support Adding Items


Before we begin adding logic to our server, we must first register an account with an image hosting service. This is
required since the file hosting on our hosting service is "ephemeral", meaning that any files that we upload (such as
featured images for our Items), will not be permanently stored on the file system. Therefore, instead of relying on the
hosting service to store our images, we will instead use Cloudinary.

 Sign up for a free account here: https://cloudinary.com/users/register/free (Choose "Programmable Media for
image and video API" as your "product")

 Validate your email address once Cloudinary sends you a "Welcome" email

 Log in to Cloudinary and navigate to the "Dashboard"

 Record your "Cloud Name", "API Key" and "API Secret" values (we will need them later).

Once you have successfully created your Cloudinary account and obtained the required information, we can proceed to
update our code:

Step 1: Adding multer, cloudinary and streamifier


 Use npm to install the following modules:

o "multer"

o "cloudinary"

o "streamifier"

 Inside your server.js file "require" the libraries:

o const multer = require("multer");

o const cloudinary = require('cloudinary').v2

o const streamifier = require('streamifier')

 Set the cloudinary config to use your "Cloud Name", "API Key" and "API Secret" values, i.e.

cloudinary.config({
cloud_name: 'Cloud Name',
api_key: 'API Key',
api_secret: 'API Secret',
secure: true
});

 Finally, create an "upload" variable without any disk storage, i.e.


o const upload = multer(); // no { storage: storage } since we are not using disk storage

Step 2: Adding the "Item" route


 Add the following route: POST /items/add
o This route uses the middleware: upload.single("featureImage")

o Inside the route, add the following code (from: the Cloudinary Documentation)

if(req.file){
let streamUpload = (req) => {
return new Promise((resolve, reject) => {
let stream = cloudinary.uploader.upload_stream(
(error, result) => {
if (result) {
resolve(result);
} else {
reject(error);
}
}
);

streamifier.createReadStream(req.file.buffer).pipe(stream);
});
};

async function upload(req) {


let result = await streamUpload(req);
console.log(result);
return result;
}

upload(req).then((uploaded)=>{
processItem(uploaded.url);
});
}else{
processItem("");
}

function processItem(imageUrl){
req.body.featureImage = imageUrl;

// TODO: Process the req.body and add it as a new Item before redirecting to /items
}
Step 3: Adding an "addItem" function within store-service.js
 Create the function "addItem(itemData)" within store-service.js according to the following specification: (HINT:
do not forget to add it to module.exports)
o Like all functions within store-service.js, this function must return a Promise
o If itemData.published is undefined, explicitly set it to false, otherwise set it to true (this gets around the
issue of the checkbox not sending "false" if it is unchecked)
o Explicitly set the id property of itemData to be the length of the "items" array plus one (1). This will
have the effect of setting the first new item’s id to +1 of the old one, and so on.
o Push the updated ItemData object onto the "items" array and resolve the promise with the updated
itemData value (i.e. the newly added store item).
 Once this is complete, make use of the new "addItem(itemData)" function within POST /items/add route to
correctly add the new store item before redirecting the user to the /items route

Step 4: Verify your Solution


At this point, you should now be able to add new store item using the "/items/add" route and see the full store
listing on the "/items" route.

IMPORTANT NOTE:

At the moment, we are not persisting our newly created Store Items(they simply exist in memory), however any
images that we add are being stored within Cloudinary. This means that once our server restarts, the new store
items will be gone, but the featureImage link will still be valid. To cut down on your storage usage on Cloudinary,
please remember to delete these images once you have completed your testing (see the "Media Library" tab in
Cloudinary)

Part 3: Adding New Routes to query "Items"


Step 1: Update the "/items" route
 In addition to providing all the items, this route must now also support the following optional filters (via the
query string)

NOTE: We do not have to support the possibility of having both "category" and "minDate" queries present at the
same time in the URL.
o /items?category=value

 return a JSON string consisting of all items whose category property equals value - where value
could be one of 1,2,3,4 or 5 (there are currently 5 categories in the dataset). This can be
accomplished by calling the getItemsByCategory(category) function of your store-service
(defined below)

o /items?minDate=value

 return a JSON string consisting of all items whose postDate property is equal or greater than
value - where value is a date string in the format YYYY-MM-DD. This can be accomplished by
calling the getItemsByMinDate(minDateStr) function of your store-service (defined below)
o /items

 return a JSON string consisting of all items without any filter (existing functionality)

Step 2: Add the "/item/value" route

 This route will return a JSON formatted string containing a single item whose id matches the value. This can be
accomplished by calling the getItemById(id) function of your store-service (defined below).

Sample: https://yourURL.app/item/3

Part 4: Updating "store-service.js" to support the new "Item" routes


Note: All the below functions must return a promise (continuing with the pattern from the rest of the store-service.js
module)

Step 1: Add the getItemsByCategory(category) Function

 This function will provide an array of "item" objects whose category property matches the category parameter
(i.e. if category is 5 then the array will consist of only items who have a "category" property value of 5) using the
resolve method of the returned promise.
 If for some reason, the length of the array is 0 (no results returned), this function must invoke the reject method
and pass a meaningful message, i.e. "no results returned".

Step 2: Add the getItemsByMinDate(minDateStr) Function

 This function will provide an array of "item" objects whose postDate property represents a Date value that is
greater than, or equal to the minDateStr parameter Date value. For example, if minDateString is "2020-12-01",
then all "item" objects returned will have a postDate property that represents a larger Date.

Note: Date strings in this format can be compared by creating new Date objects and comparing them directly,
i.e.

if(new Date(someItemObj.postDate) >= new Date(minDateStr)){


console.log("The postDate value is greater than minDateStr")
}

If for some reason, the length of the array is 0 (no results returned), this function must invoke the reject method
and pass a meaningful message, i.e. "no results returned".

Step 3: Add the getItemById(id) Function

 This function will provide a single "item" object whose id property matches the id parameter using the resolve
method of the returned promise.
 If for some reason, the itemcannot be found, this function must invoke the reject method and pass a meaningful
message, i.e. "no result returned".
Part 5: Pushing to GitHub and Vercel
Once you are satisfied with your application, push to GitHub, and deploy it to Vercel:
 Ensure that you have checked in your latest code using git (from within Visual Studio Code)

 Push commits to the same private web322-app GitHub repository either through the integrated terminal (git
push) or through the button interface on Visual Studio Code (publish, sync, etc.)

 If set up correctly from Assignment 2, it will automatically be deployed to Vercel.


 Your Professors GitHub account should already be added as a collaborator to your web322-app GitHub
repository from AS1. If not, please email them.

Assignment Submission:
 Next, Add the following declaration at the top of your server.js file:

/*********************************************************************************
* WEB322 – Assignment 03
* I declare that this assignment is my own work in accordance with Seneca Academic Policy. No part
* of this assignment has been copied manually or electronically from any other source
* (including 3rd party web sites) or distributed to other students.
*
* Name: ______________________ Student ID: ______________ Date: ________________
*
* Vercel Web App URL: ________________________________________________________
*
* GitHub Repository URL: ______________________________________________________
*
********************************************************************************/

 Compress (.zip) your web322-app folder and submit the .zip file to My.Seneca under
Assignments -> Assignment 3

Important Note:
 Submitted assignments must run locally, i.e. start up errors causing the assignment/app to fail on startup will
result in a grade of zero (0) for the assignment.
Possible Grade Points:

Description

Added/ Updated Static .html & Directories; items/add, addItem.html, updated links

Added Routes / Middleware to Support adding items; Signed up for Cloudinary, added multer, cloudinary,
stream middleware. Added route for "Item" and upload code works.

Added New Routes to query "Items"; Updated /items route for Category and minDate filters. Changed
/Items to return JSON

Updated "store-service.js"; getItemsByCategory, getItemsByMinDate, getItemById

Push to GITHUB and Vercelworks

Use original GITHUB from AS2

Use your own code from AS2

You might also like