update,
This commit is contained in:
144
james_endl-js-commission/.gitignore
vendored
Normal file
144
james_endl-js-commission/.gitignore
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/node
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=node
|
||||
|
||||
### Node ###
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
### Node Patch ###
|
||||
# Serverless Webpack directories
|
||||
.webpack/
|
||||
|
||||
# Optional stylelint cache
|
||||
|
||||
# SvelteKit build / generate output
|
||||
.svelte-kit
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/node
|
0
james_endl-js-commission/.gitkeep
Normal file
0
james_endl-js-commission/.gitkeep
Normal file
4
james_endl-js-commission/JOURNAL.md
Normal file
4
james_endl-js-commission/JOURNAL.md
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
|
||||
using remote mongodb
|
||||
/home/logic/_workspace/COMP3322A-lab6/gen_db.js
|
45
james_endl-js-commission/app/app.js
Normal file
45
james_endl-js-commission/app/app.js
Normal file
@@ -0,0 +1,45 @@
|
||||
const createError = require("http-errors");
|
||||
const express = require("express");
|
||||
const path = require("path");
|
||||
const logger = require("morgan");
|
||||
|
||||
const MONGO_HOST = "mongo";
|
||||
// const MONGO_HOST = "127.0.0.1";
|
||||
|
||||
const monk = require("monk");
|
||||
const db = monk(`${MONGO_HOST}:27017/lab6-db`);
|
||||
|
||||
const indexRouter = require("./routes/index");
|
||||
const usersRouter = require("./routes/users");
|
||||
|
||||
const app = express();
|
||||
|
||||
app.set("views", path.join(__dirname, "views"));
|
||||
app.set("view engine", "pug");
|
||||
|
||||
app.use(logger("dev"));
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
app.use(express.static(path.join(__dirname, "public")));
|
||||
|
||||
app.use((req, res, next) => {
|
||||
req.db = db;
|
||||
next();
|
||||
});
|
||||
|
||||
app.use("/", indexRouter);
|
||||
app.use("/users", usersRouter);
|
||||
|
||||
app.use((req, res, next) => {
|
||||
next(createError(404));
|
||||
});
|
||||
|
||||
app.use((err, req, res, next) => {
|
||||
res.locals.message = err.message;
|
||||
res.locals.error = req.app.get("env") === "development" ? err : {};
|
||||
|
||||
res.status(err.status || 500);
|
||||
res.render("error");
|
||||
});
|
||||
|
||||
module.exports = app;
|
90
james_endl-js-commission/app/bin/www
Normal file
90
james_endl-js-commission/app/bin/www
Normal file
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var app = require('../app');
|
||||
var debug = require('debug')('app:server');
|
||||
var http = require('http');
|
||||
|
||||
/**
|
||||
* Get port from environment and store in Express.
|
||||
*/
|
||||
|
||||
var port = normalizePort(process.env.PORT || '3000');
|
||||
app.set('port', port);
|
||||
|
||||
/**
|
||||
* Create HTTP server.
|
||||
*/
|
||||
|
||||
var server = http.createServer(app);
|
||||
|
||||
/**
|
||||
* Listen on provided port, on all network interfaces.
|
||||
*/
|
||||
|
||||
server.listen(port);
|
||||
server.on('error', onError);
|
||||
server.on('listening', onListening);
|
||||
|
||||
/**
|
||||
* Normalize a port into a number, string, or false.
|
||||
*/
|
||||
|
||||
function normalizePort(val) {
|
||||
var port = parseInt(val, 10);
|
||||
|
||||
if (isNaN(port)) {
|
||||
// named pipe
|
||||
return val;
|
||||
}
|
||||
|
||||
if (port >= 0) {
|
||||
// port number
|
||||
return port;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "error" event.
|
||||
*/
|
||||
|
||||
function onError(error) {
|
||||
if (error.syscall !== 'listen') {
|
||||
throw error;
|
||||
}
|
||||
|
||||
var bind = typeof port === 'string'
|
||||
? 'Pipe ' + port
|
||||
: 'Port ' + port;
|
||||
|
||||
// handle specific listen errors with friendly messages
|
||||
switch (error.code) {
|
||||
case 'EACCES':
|
||||
console.error(bind + ' requires elevated privileges');
|
||||
process.exit(1);
|
||||
break;
|
||||
case 'EADDRINUSE':
|
||||
console.error(bind + ' is already in use');
|
||||
process.exit(1);
|
||||
break;
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "listening" event.
|
||||
*/
|
||||
|
||||
function onListening() {
|
||||
var addr = server.address();
|
||||
var bind = typeof addr === 'string'
|
||||
? 'pipe ' + addr
|
||||
: 'port ' + addr.port;
|
||||
debug('Listening on ' + bind);
|
||||
}
|
1296
james_endl-js-commission/app/package-lock.json
generated
Normal file
1296
james_endl-js-commission/app/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
18
james_endl-js-commission/app/package.json
Normal file
18
james_endl-js-commission/app/package.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "app",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "node ./bin/www"
|
||||
},
|
||||
"dependencies": {
|
||||
"cookie-parser": "~1.4.4",
|
||||
"debug": "~2.6.9",
|
||||
"express": "~4.16.1",
|
||||
"http-errors": "~1.6.3",
|
||||
"jade": "~1.11.0",
|
||||
"monk": "^7.3.4",
|
||||
"morgan": "~1.9.1",
|
||||
"pug": "^3.0.2"
|
||||
}
|
||||
}
|
BIN
james_endl-js-commission/app/public/images/logo.png
(Stored with Git LFS)
Normal file
BIN
james_endl-js-commission/app/public/images/logo.png
(Stored with Git LFS)
Normal file
Binary file not shown.
109
james_endl-js-commission/app/public/javascripts/externalJS.js
Normal file
109
james_endl-js-commission/app/public/javascripts/externalJS.js
Normal file
@@ -0,0 +1,109 @@
|
||||
$(document).ready(function() {
|
||||
showAllTopics()
|
||||
});
|
||||
|
||||
|
||||
// step 7.2
|
||||
function showAllTopics() {
|
||||
var table_content = `
|
||||
<tr>
|
||||
<th>Topic Name</th>
|
||||
<th>Study Hour</th>
|
||||
<th>Chosen Status</th>
|
||||
<th>Operation</th>
|
||||
</tr>
|
||||
`;
|
||||
|
||||
$.getJSON("/users/get_table", function (data) {
|
||||
$.each(data, function () {
|
||||
// 1. for each row tag, add the attribute class=“highlight” if the status field of the topic is “yes”
|
||||
|
||||
// 2. the last <td> element contains an <a> element with text “add” or “remove”
|
||||
// (if status field equals to “yes”, text should be “remove”; otherwise, text should be “add”)
|
||||
|
||||
// 3. The table row representations should be all concatenated into the string table_content.
|
||||
table_content += `
|
||||
<tr ${this.status == "yes" ? 'class="highlight"' : ""}>
|
||||
<td>${this.name}</td>
|
||||
<td>${this.hour}</td>
|
||||
<td>${this.status}</td>
|
||||
<td>
|
||||
${
|
||||
this.status == "yes"
|
||||
? `<a href="#" class="operation" rel="${this._id}" >remove</a>`
|
||||
: `<a href="#" class="operation" rel="${this._id}" >add</a>`
|
||||
}
|
||||
</td>
|
||||
</tr>`;
|
||||
});
|
||||
|
||||
// Finally, use $(‘#plan_table’).html() to set HTML content of the table element of id “plan_table” to table_content.
|
||||
$("#plan_table").html(table_content);
|
||||
});
|
||||
}
|
||||
|
||||
// step 8.2
|
||||
function operateTopic(event) {
|
||||
// event.preventDefault() to prevent opening the link “#” when the hyperlink is clicked
|
||||
event.preventDefault();
|
||||
|
||||
// retrieve _id of the topic that you are going to add/remove from the ‘rel’ attribute using $(this).attr(‘rel’)
|
||||
var _id = $(this).attr("rel");
|
||||
|
||||
// use $.ajax() to send a HTTP PUT request for “/users/update_status” with JSON data
|
||||
// {_id: _id field retrieved, op: operation retrieved};
|
||||
$.ajax({
|
||||
type: "PUT",
|
||||
url: `/users/update_status`,
|
||||
data: {
|
||||
_id: _id,
|
||||
// retrieve the operation that your are going to perform using $(this).html().
|
||||
op: $(this).html(),
|
||||
},
|
||||
dataType: "JSON",
|
||||
}).done(function (response) {
|
||||
if (response.msg === "Successfully updated!") {
|
||||
// alert the response message and call showAllTopics() to refresh the topic table.
|
||||
alert("Successfully updated!");
|
||||
|
||||
// call showAllTopics() to refresh the topic table.
|
||||
showAllTopics();
|
||||
} else {
|
||||
alert(response.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$("#plan_table").on("click", ".operation", operateTopic);
|
||||
|
||||
|
||||
// step 9.2
|
||||
function deleteTopic(event) {
|
||||
event.preventDefault();
|
||||
|
||||
var topic_name = $("#input_name").val();
|
||||
|
||||
// check if the topic_name is valid
|
||||
if ($(`td:contains("${topic_name}")`).length > 0) {
|
||||
// If the length of the list is not 0, use $.ajax() to send a HTTP DELETE request for “/users/delete_topic/:topic_name”;
|
||||
$.ajax({
|
||||
type: "DELETE",
|
||||
url: `/users/delete_topic/${topic_name}`,
|
||||
}).done(function (res) {
|
||||
if (res.msg == "Successfully deleted!") {
|
||||
// success delete,
|
||||
// 1. call showAllTopics() to refresh the topic table.
|
||||
// 2. alert response message
|
||||
showAllTopics();
|
||||
alert(res.msg);
|
||||
}
|
||||
// clear after delete operation
|
||||
$("#input_name").val("");
|
||||
});
|
||||
} else {
|
||||
// alert the message “No such topic in the table!”
|
||||
alert("No such topic in the table!");
|
||||
}
|
||||
}
|
||||
|
||||
$("#submit_delete").on('click', deleteTopic)
|
159
james_endl-js-commission/app/public/stylesheets/style.css
Normal file
159
james_endl-js-commission/app/public/stylesheets/style.css
Normal file
@@ -0,0 +1,159 @@
|
||||
body {
|
||||
margin: 0;
|
||||
background: #163a50;
|
||||
font: 300 100%/120% "Tahoma", Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
header {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
header, nav, .contents, footer {
|
||||
box-sizing: border-box;
|
||||
max-width: 1080px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
header, nav, footer {
|
||||
background: #0f2736;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
.contents {
|
||||
padding: 1em 2em 2.5em 2em;
|
||||
}
|
||||
|
||||
/* increase line spacing for main title */
|
||||
h1 {
|
||||
line-height: 120%;
|
||||
margin-top: 0.5em;
|
||||
float: left;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
header img {
|
||||
float: left;
|
||||
}
|
||||
|
||||
/* change color and remove underline for links */
|
||||
footer a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#plan_table a {
|
||||
color: rgb(0, 47, 255);
|
||||
}
|
||||
|
||||
/* size and margin for logo image */
|
||||
header img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
margin: 0.5em;
|
||||
}
|
||||
|
||||
form {
|
||||
padding: 1em 2em;
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
min-width: 4em;
|
||||
}
|
||||
|
||||
/* style for footer */
|
||||
footer {
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
footer div {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.contents h2 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
width: 5em;
|
||||
height: 2em;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 5em;
|
||||
height: 1.6em;
|
||||
margin-right: 2em;
|
||||
}
|
||||
|
||||
#delete_div p{
|
||||
color: gray;
|
||||
}
|
||||
|
||||
|
||||
header *, nav * {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.contents {
|
||||
background: #FFFFFF;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 0.6em;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1080px) {
|
||||
header,nav {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 720px) {
|
||||
header img {
|
||||
display: none;
|
||||
}
|
||||
header h1 {
|
||||
padding: 0 0.5em;
|
||||
}
|
||||
nav div {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.contents {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.contents li{
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* style for the table */
|
||||
table, th, td {
|
||||
border: 1.8px solid black;
|
||||
border-collapse: collapse;
|
||||
text-align: center;
|
||||
vertical-align: center;
|
||||
margin: auto;
|
||||
width: 400px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: rgb(178, 177, 177);
|
||||
}
|
||||
|
||||
.highlight {
|
||||
background-color: rgb(255, 0, 0);
|
||||
}
|
||||
|
||||
#plan_table {
|
||||
margin-bottom: 2em;
|
||||
}
|
159
james_endl-js-commission/app/public/stylesheets/style.js
Normal file
159
james_endl-js-commission/app/public/stylesheets/style.js
Normal file
@@ -0,0 +1,159 @@
|
||||
body {
|
||||
margin: 0;
|
||||
background: #163a50;
|
||||
font: 300 100%/120% "Tahoma", Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
header {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
header, nav, .contents, footer {
|
||||
box-sizing: border-box;
|
||||
max-width: 1080px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
header, nav, footer {
|
||||
background: #0f2736;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
.contents {
|
||||
padding: 1em 2em 2.5em 2em;
|
||||
}
|
||||
|
||||
/* increase line spacing for main title */
|
||||
h1 {
|
||||
line-height: 120%;
|
||||
margin-top: 0.5em;
|
||||
float: left;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
header img {
|
||||
float: left;
|
||||
}
|
||||
|
||||
/* change color and remove underline for links */
|
||||
footer a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#plan_table a {
|
||||
color: rgb(0, 47, 255);
|
||||
}
|
||||
|
||||
/* size and margin for logo image */
|
||||
header img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
margin: 0.5em;
|
||||
}
|
||||
|
||||
form {
|
||||
padding: 1em 2em;
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
min-width: 4em;
|
||||
}
|
||||
|
||||
/* style for footer */
|
||||
footer {
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
footer div {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.contents h2 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
width: 5em;
|
||||
height: 2em;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 5em;
|
||||
height: 1.6em;
|
||||
margin-right: 2em;
|
||||
}
|
||||
|
||||
#delete_div p{
|
||||
color: gray;
|
||||
}
|
||||
|
||||
|
||||
header *, nav * {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.contents {
|
||||
background: #FFFFFF;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 0.6em;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1080px) {
|
||||
header,nav {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 720px) {
|
||||
header img {
|
||||
display: none;
|
||||
}
|
||||
header h1 {
|
||||
padding: 0 0.5em;
|
||||
}
|
||||
nav div {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.contents {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.contents li{
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* style for the table */
|
||||
table, th, td {
|
||||
border: 1.8px solid black;
|
||||
border-collapse: collapse;
|
||||
text-align: center;
|
||||
vertical-align: center;
|
||||
margin: auto;
|
||||
width: 400px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: rgb(178, 177, 177);
|
||||
}
|
||||
|
||||
.highlight {
|
||||
background-color: rgb(255, 0, 0);
|
||||
}
|
||||
|
||||
#plan_table {
|
||||
margin-bottom: 2em;
|
||||
}
|
9
james_endl-js-commission/app/routes/index.js
Normal file
9
james_endl-js-commission/app/routes/index.js
Normal file
@@ -0,0 +1,9 @@
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
|
||||
// Handle GET requests to the home page ("/") and render the "index" view
|
||||
router.get("/", (req, res) => {
|
||||
res.render("index", { title: "Express" });
|
||||
});
|
||||
|
||||
module.exports = router;
|
28
james_endl-js-commission/app/views/index.pug
Normal file
28
james_endl-js-commission/app/views/index.pug
Normal file
@@ -0,0 +1,28 @@
|
||||
extends layout
|
||||
|
||||
block content
|
||||
div#debug_test
|
||||
|
||||
header
|
||||
img(src='/images/logo.png' width="128" height="128")
|
||||
h1 Course Study Plan
|
||||
br
|
||||
span.subtitle COMP3322A Modern Technologies on World Wide Web
|
||||
|
||||
section.contents
|
||||
h2 Instruction
|
||||
ul
|
||||
li Add/Remove a topic to/from your study plan by clicking the respective operation.
|
||||
li Delete a topic permanently by typing its name into the input box and clicking the "Delete" button.
|
||||
hr
|
||||
|
||||
h2 Topic Plan
|
||||
div
|
||||
table#plan_table
|
||||
div#delete_div
|
||||
p Fill in a topic name to delete it from the table permanently:
|
||||
input#input_name(type='text', placeholder='topic name')
|
||||
button#submit_delete Delete
|
||||
|
||||
footer
|
||||
div <a href="#">Back to top</a>
|
10
james_endl-js-commission/app/views/layout.pug
Normal file
10
james_endl-js-commission/app/views/layout.pug
Normal file
@@ -0,0 +1,10 @@
|
||||
doctype html
|
||||
html
|
||||
head
|
||||
title= "lab6"
|
||||
link(rel='stylesheet', href='/stylesheets/style.css')
|
||||
meta(name="viewport", content="width=device-width, initial-scale=1.0")
|
||||
body
|
||||
block content
|
||||
script(src='https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js')
|
||||
script(src='/javascripts/externalJS.js')
|
28
james_endl-js-commission/docker-compose.yml
Normal file
28
james_endl-js-commission/docker-compose.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
version: "3.1"
|
||||
|
||||
services:
|
||||
mongo:
|
||||
image: mongo
|
||||
restart: always
|
||||
ports:
|
||||
- 127.0.0.1:27017:27017
|
||||
|
||||
mongo-express:
|
||||
image: mongo-express
|
||||
restart: always
|
||||
ports:
|
||||
- 127.0.0.1:8081:8081
|
||||
|
||||
webdev:
|
||||
image: node:14-buster
|
||||
# user: 1000:1000
|
||||
volumes:
|
||||
- .:/app
|
||||
working_dir: /app
|
||||
ports:
|
||||
- 127.0.0.1:3000:3000
|
||||
- 127.0.0.1:9229:9229
|
||||
environment:
|
||||
- NODE_OPTIONS=--inspect=0.0.0.0:9229
|
||||
command: sleep infinity
|
||||
|
2
james_endl-js-commission/docs/README.md
Normal file
2
james_endl-js-commission/docs/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
mac + chrome
|
||||
|
BIN
james_endl-js-commission/docs/lab6_handout.pdf
Normal file
BIN
james_endl-js-commission/docs/lab6_handout.pdf
Normal file
Binary file not shown.
49
james_endl-js-commission/docs/lab6_materials/app.js
Normal file
49
james_endl-js-commission/docs/lab6_materials/app.js
Normal file
@@ -0,0 +1,49 @@
|
||||
var createError = require('http-errors');
|
||||
var express = require('express');
|
||||
var path = require('path');
|
||||
var logger = require('morgan');
|
||||
|
||||
// use lab6-db
|
||||
var monk = require('monk');
|
||||
var db = monk('127.0.0.1:27017/lab6-db');
|
||||
|
||||
var indexRouter = require('./routes/index');
|
||||
var usersRouter = require('./routes/users');
|
||||
|
||||
var app = express();
|
||||
|
||||
// view engine setup
|
||||
app.set('views', path.join(__dirname, 'views'));
|
||||
app.set('view engine', 'pug');
|
||||
|
||||
app.use(logger('dev'));
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
app.use(express.static(path.join(__dirname, 'public')));
|
||||
|
||||
// Make our db accessible to routers
|
||||
app.use(function(req,res,next){
|
||||
req.db = db;
|
||||
next();
|
||||
});
|
||||
|
||||
app.use('/', indexRouter);
|
||||
app.use('/users', usersRouter);
|
||||
|
||||
// for requests not matching the above routes, create 404 error and forward to error handler
|
||||
app.use(function(req, res, next) {
|
||||
next(createError(404));
|
||||
});
|
||||
|
||||
// error handler
|
||||
app.use(function(err, req, res, next) {
|
||||
// set locals, only providing error in development environment
|
||||
res.locals.message = err.message;
|
||||
res.locals.error = req.app.get('env') === 'development' ? err : {};
|
||||
|
||||
// render the error page
|
||||
res.status(err.status || 500);
|
||||
res.render('error');
|
||||
});
|
||||
|
||||
module.exports = app;
|
51
james_endl-js-commission/docs/lab6_materials/externalJS.js
Normal file
51
james_endl-js-commission/docs/lab6_materials/externalJS.js
Normal file
@@ -0,0 +1,51 @@
|
||||
$(document).ready(function() {
|
||||
showAllTopics()
|
||||
});
|
||||
|
||||
|
||||
// step 7.2
|
||||
function showAllTopics(){
|
||||
var table_content = `
|
||||
<tr><th>Topic Name</th>
|
||||
<th>Study Hour</th>
|
||||
<th>Chosen Status</th>
|
||||
<th>Operation</th></tr>
|
||||
`
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
$("#plan_table").on('click', '.operation', operateTopic)
|
||||
|
||||
// step 8.2
|
||||
function operateTopic(event){
|
||||
event.preventDefault()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
$("#submit_delete").on('click', deleteTopic)
|
||||
|
||||
|
||||
// step 9.2
|
||||
function deleteTopic(event){
|
||||
event.preventDefault()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
18
james_endl-js-commission/docs/lab6_materials/generate_db.js
Normal file
18
james_endl-js-commission/docs/lab6_materials/generate_db.js
Normal file
@@ -0,0 +1,18 @@
|
||||
var conn = new Mongo();
|
||||
var db = conn.getDB("lab6-db");
|
||||
|
||||
var topic_name = ["www", "html", "css", "javascript", "nodejs", "jquery"];
|
||||
var topic_status = ["no", "no", "no", "no", "no", "no"];
|
||||
var topic_hour = [2, 4, 4, 6, 10, 6];
|
||||
|
||||
db.topicList.remove({});
|
||||
|
||||
for(let i = 0; i < topic_name.length; i++){
|
||||
db.topicList.insert(
|
||||
{
|
||||
'name': topic_name[i],
|
||||
'hour': topic_hour[i],
|
||||
'status': topic_status[i]
|
||||
}
|
||||
)
|
||||
}
|
26
james_endl-js-commission/docs/lab6_materials/index.pug
Normal file
26
james_endl-js-commission/docs/lab6_materials/index.pug
Normal file
@@ -0,0 +1,26 @@
|
||||
extends layout
|
||||
|
||||
block content
|
||||
header
|
||||
img(src='/images/logo.png' width="128" height="128")
|
||||
h1 Course Study Plan
|
||||
br
|
||||
span(class="subtitle") COMP3322A Modern Technologies on World Wide Web
|
||||
|
||||
section(class="contents")
|
||||
h2 Instruction
|
||||
ul
|
||||
li Add/Remove a topic to/from your study plan by clicking the respective operation.
|
||||
li Delete a topic permanently by typing its name into the input box and clicking the "Delete" button.
|
||||
hr
|
||||
|
||||
h2 Topic Plan
|
||||
div
|
||||
table#plan_table
|
||||
div#delete_div
|
||||
p Fill in a topic name to delete it from the table permanently:
|
||||
input#input_name(type='text', placeholder='topic name')
|
||||
button#submit_delete Delete
|
||||
|
||||
footer
|
||||
div <a href="#">Back to top</a>
|
10
james_endl-js-commission/docs/lab6_materials/layout.pug
Normal file
10
james_endl-js-commission/docs/lab6_materials/layout.pug
Normal file
@@ -0,0 +1,10 @@
|
||||
doctype html
|
||||
html
|
||||
head
|
||||
title= "lab6"
|
||||
link(rel='stylesheet', href='/stylesheets/style.css')
|
||||
meta(name="viewport" content="width=device-width, initial-scale=1.0")
|
||||
body
|
||||
block content
|
||||
script(src='https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js')
|
||||
script(src='/javascripts/externalJS.js')
|
BIN
james_endl-js-commission/docs/lab6_materials/logo.png
(Stored with Git LFS)
Normal file
BIN
james_endl-js-commission/docs/lab6_materials/logo.png
(Stored with Git LFS)
Normal file
Binary file not shown.
159
james_endl-js-commission/docs/lab6_materials/style.css
Normal file
159
james_endl-js-commission/docs/lab6_materials/style.css
Normal file
@@ -0,0 +1,159 @@
|
||||
body {
|
||||
margin: 0;
|
||||
background: #163a50;
|
||||
font: 300 100%/120% "Tahoma", Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
header {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
header, nav, .contents, footer {
|
||||
box-sizing: border-box;
|
||||
max-width: 1080px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
header, nav, footer {
|
||||
background: #0f2736;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
.contents {
|
||||
padding: 1em 2em 2.5em 2em;
|
||||
}
|
||||
|
||||
/* increase line spacing for main title */
|
||||
h1 {
|
||||
line-height: 120%;
|
||||
margin-top: 0.5em;
|
||||
float: left;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
header img {
|
||||
float: left;
|
||||
}
|
||||
|
||||
/* change color and remove underline for links */
|
||||
footer a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#plan_table a {
|
||||
color: rgb(0, 47, 255);
|
||||
}
|
||||
|
||||
/* size and margin for logo image */
|
||||
header img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
margin: 0.5em;
|
||||
}
|
||||
|
||||
form {
|
||||
padding: 1em 2em;
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
min-width: 4em;
|
||||
}
|
||||
|
||||
/* style for footer */
|
||||
footer {
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
footer div {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.contents h2 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
width: 5em;
|
||||
height: 2em;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 5em;
|
||||
height: 1.6em;
|
||||
margin-right: 2em;
|
||||
}
|
||||
|
||||
#delete_div p{
|
||||
color: gray;
|
||||
}
|
||||
|
||||
|
||||
header *, nav * {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.contents {
|
||||
background: #FFFFFF;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 0.6em;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1080px) {
|
||||
header,nav {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 720px) {
|
||||
header img {
|
||||
display: none;
|
||||
}
|
||||
header h1 {
|
||||
padding: 0 0.5em;
|
||||
}
|
||||
nav div {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.contents {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.contents li{
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* style for the table */
|
||||
table, th, td {
|
||||
border: 1.8px solid black;
|
||||
border-collapse: collapse;
|
||||
text-align: center;
|
||||
vertical-align: center;
|
||||
margin: auto;
|
||||
width: 400px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: rgb(178, 177, 177);
|
||||
}
|
||||
|
||||
.highlight {
|
||||
background-color: rgb(255, 0, 0);
|
||||
}
|
||||
|
||||
#plan_table {
|
||||
margin-bottom: 2em;
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
22
james_endl-js-commission/gen_db.js
Normal file
22
james_endl-js-commission/gen_db.js
Normal file
@@ -0,0 +1,22 @@
|
||||
var MongoClient = require("mongodb").MongoClient;
|
||||
|
||||
var topic_name = ["www", "html", "css", "javascript", "nodejs", "jquery", "louiscklaw1", "louiscklaw2", "louiscklaw3"];
|
||||
var topic_status = ["no", "no", "no", "no", "no", "no", "no", "no", "no"];
|
||||
var topic_hour = [2, 4, 4, 6, 10, 6, 1, 2, 3];
|
||||
|
||||
MongoClient.connect("mongodb://mongo:27017/", function (err, result) {
|
||||
if (!err) {
|
||||
console.log("We are connected");
|
||||
var db = result.db("lab6-db");
|
||||
|
||||
db.collection("topicList").remove({});
|
||||
|
||||
for (let i = 0; i < topic_name.length; i++) {
|
||||
db.collection("topicList").insert({
|
||||
name: topic_name[i],
|
||||
hour: topic_hour[i],
|
||||
status: topic_status[i],
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
41
james_endl-js-commission/init-express.sh
Normal file
41
james_endl-js-commission/init-express.sh
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -ex
|
||||
|
||||
rm -rf app
|
||||
|
||||
mkdir app
|
||||
|
||||
pushd app
|
||||
npx express-generator
|
||||
popd
|
||||
|
||||
pushd app
|
||||
npm install
|
||||
npm install pug
|
||||
|
||||
npm install monk
|
||||
popd
|
||||
|
||||
pushd app
|
||||
# (1) overwrite the original “app.js” in the Express app directory with the “app.js” we provided.
|
||||
# (2) overwrite the original “users.js” in ./routes with the same file that we provided;
|
||||
cp /home/logic/_workspace/COMP3322A-lab6/docs/lab6_materials/app.js app.js
|
||||
cp /home/logic/_workspace/COMP3322A-lab6/docs/lab6_materials/users.js routes/users.js
|
||||
|
||||
# (3) move “externalJS.js” to ./public/javascripts;
|
||||
# (4) move “style.css” to ./public/stylesheets;
|
||||
cp /home/logic/_workspace/COMP3322A-lab6/docs/lab6_materials/externalJS.js public/javascripts/externalJS.js
|
||||
cp /home/logic/_workspace/COMP3322A-lab6/docs/lab6_materials/style.css public/stylesheets/style.js
|
||||
|
||||
|
||||
# (5) overwrite the original “index.pug” and “layout.pug” with the same files that we provided;
|
||||
# (6) move “logo.png” to ./public/images.
|
||||
rm -rf views/*.jade
|
||||
cp /home/logic/_workspace/COMP3322A-lab6/docs/lab6_materials/index.pug views/index.pug
|
||||
cp /home/logic/_workspace/COMP3322A-lab6/docs/lab6_materials/layout.pug views/layout.pug
|
||||
cp /home/logic/_workspace/COMP3322A-lab6/docs/lab6_materials/logo.png ./public/images/logo.png
|
||||
|
||||
node app.js
|
||||
|
||||
popd
|
8
james_endl-js-commission/install_mongo.sh
Normal file
8
james_endl-js-commission/install_mongo.sh
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
# https://www.mongodb.com/docs/manual/tutorial/install-mongodb-on-ubuntu/
|
||||
|
||||
|
||||
pushd /app/docs/lab6_materials
|
||||
mongo mongo/ ./generate_db.js
|
1071
james_endl-js-commission/package-lock.json
generated
Normal file
1071
james_endl-js-commission/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
29
james_endl-js-commission/package.json
Normal file
29
james_endl-js-commission/package.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "comp3322a-lab6",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"directories": {
|
||||
"doc": "docs",
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"into_docker": "docker compose exec -it webdev bash",
|
||||
"docker_rebuild": "docker compose up --build -d"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/louiscklaw/COMP3322A-lab6.git"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://github.com/louiscklaw/COMP3322A-lab6/issues"
|
||||
},
|
||||
"homepage": "https://github.com/louiscklaw/COMP3322A-lab6#readme",
|
||||
"dependencies": {
|
||||
"mongodb": "^4.11.0"
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user