Web322 Assignment3
Web322 Assignment3
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.)
o GET /items/add
This route simply sends the file "/views/addItem.html"
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
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:
o "multer"
o "cloudinary"
o "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
});
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);
});
};
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
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)
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)
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
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".
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 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".
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.)
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