联系方式

  • QQ:99515681
  • 邮箱:99515681@qq.com
  • 工作时间:8:00-23:00
  • 微信:codinghelp2

您当前位置:首页 >> CS作业CS作业

日期:2019-12-06 10:56

COMP3322A Modern Technologies on World Wide Web

Assignment (20%)

[Learning Outcomes 1, 2]

Due by: 23:55, Friday

Dec 14 2019

Overview

In this assignment, we are going to develop a simple single-page social photo sharing

application iAlbum using the MERN stack (MongoDB, Express.JS, ReactJS and Node.js). The

main work flow of iAlbum is as follows.

? Upon loading, the sketch of the page is shown in Fig. 1

Fig. 1

? After a user has logged in, the sketch of the page is in Fig. 2. A list of friend albums is

shown in the left division.

Fig. 2

? After clicking “My Album”, the sketch of the page is in Fig. 3. The photos in the user’s

own album is displayed in the right division, together with messages of who liked a

photo, deletion buttons, and new photo selection/upload buttons.

Fig. 3

? Each photo is clickable. After clicking a photo, the photo will be enlarged as in Fig. 4,

together with the “liked” message and the deletion button. When the cross is clicked,

the page returns to the view shown in Fig. 3.

Fig. 4

? When a friend’s album is selected in the left-hand list, the page view becomes one in

Fig. 5. Photos of the friend are shown in the right division, together with messages of

who liked a photo and the like buttons.

Fig. 5

? Similarly, when a photo is clicked, the photo will be enlarged as in Fig. 6, together with

the “liked” message and the like button. When the cross is clicked, the page returns

to the view shown in Fig. 5.

Fig. 6

We are going to achieve this application by implementing code in a backend Express app and

a frontend React app.

? Express app:

app.js

./routes/ albums.js

? React app:

./src/App.js

./src/index.js

./src/App.css

Task 1. Backend Web Service

We implement the backend web service logic using Express.js. The web service is accessed at

http://localhost:3002/xx.

Preparations

1. Following steps in Lab 6, install the Node.js environment and the Express framework, create

an Express project named AlbumService, and install dependencies for MongoDB/monk.

2. Following steps in Lab 6, install MongoDB, run MongoDB server, and create a database

“assignment2” in the database server.

Insert a number of records to a userList collection in the database in the format as follows.

We will assume that user names are all different in this application.

Create a folder “uploads” under the public folder in your project directory. Copy a few photos

to the uploads folder (due to our simplified implementation to be outlined later, we will only

use .jpg photo files in this assignment). Insert a few records to a photoList collection in the

database in the format as follows, each corresponding to one photo you have copied to the

uploads folder. Here userid should be the value of _id generated by MongoDB for the photo

owner’s record in the userList collection, which you can find out using db.userList.find().

Note that copying photos to uploads folder and inserting photo records into the photoList

collection, as we do above, are only for testing purpose. We will implement the functionality

of uploading photos and inserting their records to the database using iAlbum.

For implementation simplicity, in this assignment, we do not store uploaded photos in

MongoDB. Instead, we store them in the harddisk under the ./public/uploads/ folder, and

store the path of a photo in the photoList collection only, using which we can identify the

photo in the uploads folder.

Task 1. Implement backend web service logic (AlbumService/app.js,

AlbumService/routes/albums.js)

app.js (10 marks)

In app.js, load the router module implemented in ./routes/albums.js. Then add the

middleware to specify that all requests for http://localhost:3002/ will be handled by this

router.

Add necessary code for loading the MongoDB database you have created, creating an instance

of the database, and passing the database instance for usage of all middlewares.

Also load any other modules and add other middlewares which you may need to implement

this application.

Add the middleware to serve requests for static files in the public folder.

We will let the server run on the default port 3002 and launch the Express app using

command “node app.js”.

./routes/albums.js (32 marks)

db.userList.insert({'username': 'Eddie', 'password': '123456', 'friends':['Ken', 'Alice', 'Bill']})

db.photoList.insert({'url': 'http://localhost:3002/uploads/1.jpg', 'userid': 'xxxxxxx', 'likedby':['Ken',

'Alice']})

In albums.js, implement the router module with middlewares to handle the following

endpoints:

1. HTTP GET requests for http://localhost:3002/init. The middleware checks if the “userID”

cookie has been set for the client. If not, send an empty string back to the client. Otherwise,

retrieve username of the current user (according to the value of the “userID” cookie), and

username and _id of friends of the current user from the userList collection in the database;

send all retrieved information as a JSON string to the client if the database operation is

successful, and the error message if failure. You should decide the format of the JSON string

and retrieve data accordingly in the client-side code to be implemented in Task2.

2. HTTP POST requests for http://localhost:3002/login. The middleware should parse the

body of the HTTP POST request and extract the username and password carried in request

body. Then it checks whether the username and password match any record in the userList

collection in the database. If no, send “Login failure” in the body of the response message. If

yes, set a cookie with the key of “userID”, the value of this user record’s _id, and a maxAge of

1 hour; send the username and _id of all friends of the logged-in user as a JSON string in the

body of the response message if database operation is successful and the error message if

failure. Again, you should design the format of the JSONstring.

3. HTTP GET requests for http://localhost:3002/logout. The middleware should unset the

“userID” cookie, and send an empty string back to the user.

4. HTTP GET requests for http://localhost:3002/getalbum/:userid. If the userid in the URL is

“0”, the middleware should retrieve _id, url and likedby array of all photos of the current user

from the photoList collection in the database, based on the userid stored in the “userID”

cookie. Otherwise, retrieve _id, url and likedby array of all photos of the friend from the

photoList collection based on the userid in the URL. Send all retrieved information as a JSON

string in the body of the response message if database operation is successful, and the error

message if failure. You should decide the format of the JSON string to be included in the

response body.

5. HTTP POST request for http://localhost:3002/uploadphoto. Store the photo carried in the

request body in ./public/uploads/ folder and insert a record of the photo in the photoList

collection in the database.

To read and write files in the Express/Node.js framework, you will need the fs module

(https://nodejs.org/api/fs.html). Load the module in albums.js. To store the received photo

in a path (e.g., ./public/uploads/1.jpg), a simple approach is to use

req.pipe(fs.createWriteStream(path)); .

Refer to https://nodejs.org/api/fs.html#fs_fs_createwritestream_path_options for

fs.createWriteStream() and

https://nodejs.org/api/stream.html#stream_readable_pipe_destination_options for pipe().

Since in our simplified client-side implementation (detailed in Task 2), the client does not send

the file name of the uploaded photo but only the image file, you can create a name of your

choice for the newly uploaded photo. For example, you can generate a random number x and

name the file x.jpg (recall that we assume only .jpg files are uploaded). Then the photo record

to be inserted to the photoList collection should be {'url': 'http://localhost:3002/uploads/x.jpg',

'userid': 'xxxxxxx', 'likedby':[]}, where userid is the value of the “userID” cookie.

The middleware should send a JSON string containing the _id and url of the photo in the

photoList collection to the user if success, and the error message if failure.

6. HTTP DELETE requests for http://localhost:3002/deletephoto/:photoid. The middleware

should delete the photo record from the photoList collection, corresponding to the _id value

in the URL, and remove the photo file from ./public/uploads/ folder (Hint: you may find

fs.unlink() useful https://nodejs.org/api/fs.html#fs_fs_unlink_path_callback). Return an

empty string to the client if success and the error message iffailure.

7. HTTP PUT requests for http://localhost:3002/updatelike/:photoid. The middleware should

update the likedby array of the photo record in the photoList collection, corresponding to the

_id value in the URL. Especially, use _id of the current user in the “userID” cookie to find out

the username of the current user from the userList collection, and then use the

db.collection.update method to update the photo record in the photoList collection. Return

the updated likedby array to the client if success and the error message if failure.

8. Add the code for enabling CORS in albums.js, similar to what you did in Lab 8.

Task 2 Front-end React App

Implement the front-end as a React app. The app is accessed at http://localhost:3000/.

Preparations

Following steps in Lab 8, create a React app named MyApp and install the jQuery module in

the React app.

Implement the React app (MyApp/src/index.js,

MyApp/src/App.js, MyApp/src/App.css)

index.js (3 marks)

Modify the generated Index.js in the ./src folder of your react app directory, such that it

renders the component you create in App.js in the “root” division in the default index.html.

App.js (40 marks)

App.js should import the jQuery module and link to the style sheet App.css.

Design and implement the component structure in App.js, such that the front-end page views

and functionalities as illustrated in Figures 1-6 can be achieved. You can decide the

components to create, in order to implement the React app.

Hints:

1. You can use conditional rendering to decide what component to be displayed on the

page view. For example, in the root component you are creating in App.js, you may

use a state variable to indicate if a cookie has been set for the current user (i.e., the

user has logged in) or not, and then render the component presenting the respective

page view accordingly. Initialize the state variable to indicate that no cookie has been

set, and update it when the user has successfully logged in and logged out,

respectively.

2. Page load. When the browser loads the page from the React App, send an AJAX HTTP

GET request for http://localhost:3002/init: (1) if an empty string is received from the

server, a page as shown in Fig. 1 should be displayed; (2) if a JSON string carrying

username of the logged-in user and _id and username of the friends is received, a

page as shown in Fig. 2 should be displayed. Especially, the username of the loggedin

user is to be shown in the message “Hello username!” in the header area.

3. Log in. When handling the click event on the “log in” button, check if both the

username and password input textboxes are non-empty: if so, send an AJAX HTTP

POST request for http://localhost:3002/login, carrying the input username and

password in the request body; otherwise, show an alert popup box stating “You must

enter username and password”. If a “Login failure” response is received, the page view

remains the one in Fig. 1, except for displaying “Login failure” in the header area in

addition. If a JSON string containing the username and _id of friends is received,

display the page as shown in Fig. 2.

4. Log out. When handling a click event on the “log out” button, send an AJAX HTTP GET

request for http://localhost:3002/logout. Display the page view as in Fig. 1 when an

empty string is received from the server.

5. When handling a click event on “My Album” in the album list, send an AJAX HTTP GET

request for http://localhost:3002/getalbum/0. When the JSON string containing

_id, url and likedby array of the current user’s photos is received, display the photos

following the sketch in Fig. 3. Especially, each photo is an <img> element with a “src”

attribute pointing to the url of the respective photo, and an “id” attribute recording

_id of the photo. If the likedby array of a photo is not empty, display a message “xx

liked the photo!” underneath the photo; otherwise, do not display the message.

Display a “Delete” button under each photo. You can decide the display size of the

photos and the number of photos to display in each row on the page. Add a file upload

input element (http://www.w3schools.com/jsref/dom_obj_fileupload.asp) and an

“Upload Photo” button at the bottom of the right division. Note that the texts to

display on and behind the file upload input button may differ depending on the

browser you use to render the file upload input element.

6. When handling a click event on a friend’s “xx’s Album” entry in the album list, send an

AJAX HTTP GET request for http://localhost:3002/getalbum/userid, where the userid

is the _id of the friend in the userList collection in the database. When the JSON string

containing _id, url and likedby array of the friend’s photos is received, display the page

view as shown in Fig. 5. Note that the album entry in the list in the left division, whose

photos are being displayed in the right division, should be highlighted.

7. When handling a click event on the “Upload Photo” button, check if a file has been

selected with the file upload input element (Hint: you may find “files” property of the

input FileUpload object useful

http://www.w3schools.com/jsref/dom_obj_fileupload.asp). If no, do nothing. If yes,

send an AJAX HTTP POST request for http://localhost:3002/uploadphoto, enclosing

the file object as a whole in the body of the request message. If a JSON string

containing the _id and url of the uploaded photo is received, display the new photo

as the last photo on the page, together with a “Delete” button. If an error message is

received, show the error message in an alert box.

8. When handling a click event on a “Delete” button on the page view in Fig. 3, a

confirmation box will be popped up, showing the message “Are you sure you want to

delete this photo?”. If “Cancel” is clicked, the box disappears and the previous page

view remains; if “OK” is clicked, send an AJAX HTTP DELETE request for

http://localhost:3002/deletephoto/photoid, where the photoid should be _id of the

photo in the photoList collection in the database. Upon receiving an empty string in

the response, the photo together with the “liked” message and the “Delete” button

should be removed from the page, and the following photo entries should be moved

forward to occupy its space, if it is not the last photo. If an error message is received,

show the error message in an alert box.

9. When handling a click event on a “Delete” button on the page view in Fig. 4, similar

event handling as the above should be implemented, except for the following: upon

receiving an empty string in the response, the page view in Fig. 3 should be displayed,

where the photo entry corresponding to the deleted photo is removed and the

following photo entries are moved forward to occupy its space (if it is not the last

photo).

10. When handling a click event on a “Like” button (either on the page view in Fig. 5 or on

the page view in Fig. 6), send an AJAX HTTP PUT request for

http://localhost:3002/updatelike/photoid, where photoid should be _id of the photo

in the photoList collection in the database. Upon receiving the updated likedby array

in the response, display the updated “liked” message underneath the photo on the

page. If an error message is received, show the error message in an alertbox.

11. When handling a click event on a photo on the page view in Fig. 3 or Fig. 5, display the

photo together with the “liked” message, the “Delete” or the “Like” button, and the

“x” in the right division (Fig. 4 or Fig. 6). When “x” is clicked, the page view returns to

Fig. 3 or Fig. 5. An AJAX HTTP GET request should be sent for

http://localhost:3002/getalbum/0 or http://localhost:3002/getalbum/userid

(depending on whose album entry is highlighted in the left division), and response

should be handled similarly as in points 5 and 6 above, to retrieve the photo

information for display.

App.css (10 marks)

Style your page views nicely using CSS rules in App.css.

Other marking criteria:

(5 marks) Good programming style (avoid redundant code, easy to understand and maintain).

You are encouraged to provide a readme.txt file to let us know more about your programs.

Submission:

You should zip the following files (in the indicated directory structure) into a

yourstudentID-a2.zip file

AlbumService/app.js

AlbumService/routes/albums.js

MyApp/src/App.js

MyApp/src/index.js

MyApp/src/App.css

and submit the zip file on Moodle:

(1) Login Moodle.

(2) Find “Assignments” in the left column and click “Assignment 2”.

(3) Click “Add submission”, browse your .zip file and save it. Done.

(4) You will receive an automatic confirmation email, if the submission wassuccessful.

(5) You can “Edit submission” to your already submitted file, but ONLY before the deadline.


版权所有:编程辅导网 2018 All Rights Reserved 联系方式:QQ:99515681 电子信箱:99515681@qq.com
免责声明:本站部分内容从网络整理而来,只供参考!如有版权问题可联系本站删除。