├── .gitignore
├── README.md
├── package-lock.json
├── package.json
└── provided
├── data
├── feedback.json
└── speakers.json
├── services
├── FeedbackService.js
└── SpeakerService.js
└── static
├── Hillary_Goldwynn.html
├── css
└── style.css
├── feedback.html
├── images
├── artwork
│ ├── Hillary_Goldwynn_01.jpg
│ ├── Hillary_Goldwynn_01_tn.jpg
│ ├── Hillary_Goldwynn_02.jpg
│ ├── Hillary_Goldwynn_02_tn.jpg
│ ├── Hillary_Goldwynn_03.jpg
│ ├── Hillary_Goldwynn_03_tn.jpg
│ ├── Hillary_Goldwynn_04.jpg
│ ├── Hillary_Goldwynn_04_tn.jpg
│ ├── Hillary_Goldwynn_05.jpg
│ ├── Hillary_Goldwynn_05_tn.jpg
│ ├── Hillary_Goldwynn_06.jpg
│ ├── Hillary_Goldwynn_06_tn.jpg
│ ├── Hillary_Goldwynn_07.jpg
│ ├── Hillary_Goldwynn_07_tn.jpg
│ ├── Lorenzo_Garcia_01.jpg
│ ├── Lorenzo_Garcia_01_tn.jpg
│ ├── Lorenzo_Garcia_02.jpg
│ ├── Lorenzo_Garcia_02_tn.jpg
│ ├── Lorenzo_Garcia_03.jpg
│ ├── Lorenzo_Garcia_03_tn.jpg
│ ├── Lorenzo_Garcia_04.jpg
│ ├── Lorenzo_Garcia_04_tn.jpg
│ ├── Riley_Rewington_01.jpg
│ ├── Riley_Rewington_01_tn.jpg
│ ├── Riley_Rewington_02.jpg
│ ├── Riley_Rewington_02_tn.jpg
│ ├── Riley_Rewington_03.jpg
│ ├── Riley_Rewington_03_tn.jpg
│ ├── Riley_Rewington_04.jpg
│ ├── Riley_Rewington_04_tn.jpg
│ ├── Riley_Rewington_05.jpg
│ ├── Riley_Rewington_05_tn.jpg
│ ├── Riley_Rewington_06.jpg
│ └── Riley_Rewington_06_tn.jpg
├── misc
│ └── background.jpg
└── speakers
│ ├── Hillary_Goldwynn.jpg
│ ├── Hillary_Goldwynn_tn.jpg
│ ├── Lorenzo_Garcia.jpg
│ ├── Lorenzo_Garcia_tn.jpg
│ ├── Riley_Rewington.jpg
│ └── Riley_Rewington_tn.jpg
├── index.html
├── js
├── feedback.js
└── pixgrid.js
└── speakers.html
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Building a website with Node.js and Express
2 |
3 | This repository contains the code for my course 'Building a Website with Node.js Node.js' on [LinkedIn Learning](https://www.linkedin.com/learning/building-a-website-with-node-js-and-express-js-3).
4 |
5 | The master branch contains the initial version to get started with, while the branches contain the state of the code at the beginning (e.g. 02_02**b**) and end (e.g. 02_02**e**) of a video.
6 |
7 | ## Setting up the project
8 |
9 | * In your terminal, create directory `building-website-nodejs-express` and **change into it**.
10 | * Run
11 | ```bash
12 | git clone --bare git@github.com:danielkhan/building-website-nodejs-express.git .git
13 | git config --bool core.bare false
14 | git reset --hard
15 | git branch
16 | ```
17 |
18 | Everything else will be discussed in my course.
19 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "roux-academy",
3 | "version": "1.0.0",
4 | "lockfileVersion": 1
5 | }
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "roux-academy",
3 | "version": "1.0.0",
4 | "description": "Exercise files for my course Building a Website with Node.js and Express",
5 | "main": "server.js",
6 | "scripts": {
7 | "start": "node server.js"
8 | },
9 | "keywords": [],
10 | "author": "Daniel Khan",
11 | "license": "MIT",
12 | "devDependencies": {},
13 | "dependencies": {}
14 | }
15 |
--------------------------------------------------------------------------------
/provided/data/feedback.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "Frank",
4 | "email": "frank-smith@gmail.com",
5 | "title": "Best Meetup Ever",
6 | "message": "I really love this meetup. Please don't let it end."
7 | },
8 | {
9 | "name": "Jane",
10 | "email": "jane-miller@gmail.com",
11 | "title": "Meeting Time",
12 | "message": "Would you consider moving the meeting time 30 minutes to about 6pm. It's tough to make it to the meetings on time right after work."
13 | },
14 | {
15 | "name": "Roy",
16 | "email": "roy-jones@gmail.com",
17 | "title": "Great Speaker",
18 | "message": "I really enjoyed the speaker this month. Would love to hear another presentation."
19 | }
20 | ]
21 |
--------------------------------------------------------------------------------
/provided/data/speakers.json:
--------------------------------------------------------------------------------
1 | {
2 | "speakers": [
3 | {
4 | "title": "Art in Full Bloom",
5 | "name": "Lorenzo Garcia",
6 | "shortname": "Lorenzo_Garcia",
7 | "summary": "Drawing and painting flowers may seem like a first-year art student's assignment, but Lorenzo Garcia brings depth, shadows, light, form and color to new heights with his unique and revolutionary technique of painting on canvas with ceramic glaze. This session is sure to be a hit with mixed media buffs.",
8 | "description": "
Lorenzo was born in Mexico, but grew up in Southern California after his mother immigrated to Los Angeles when he was a year old. His mother worked as a seamstress in the Fashion District and brought home scrap materials for Lorenzo to create his early mixed media art. From that point on, Lorenzo became hooked on creating art from scrap metals, fabrics, wood, canvas, and many others. During his junior year at Bischon Art School in Los Angeles, he perfected his own proprietary method of painting on canvas with ceramic glaze, which he will demonstrate on Monday in his session, 'Art in Full Bloom'.
Lorenzo paints with an extraordinary amount of color, and prefers to create art centered around nature, animals, and science. Now in his senior year at Bischon, Lorenzo has been creating mixed media totem poles made from old telephone poles, and other recycled materials, and is already planning his next new technique that will likely inspire a trend for years to come.
",
9 | "artwork": [
10 | "Lorenzo_Garcia_01_tn.jpg",
11 | "Lorenzo_Garcia_02_tn.jpg",
12 | "Lorenzo_Garcia_03_tn.jpg",
13 | "Lorenzo_Garcia_04_tn.jpg"
14 | ]
15 | },
16 | {
17 | "title": "Deep Sea Wonders",
18 | "name": "Hilary Goldywynn Post",
19 | "shortname": "Hillary_Goldwynn",
20 | "summary": "Hillary is a sophomore art sculpture student at New York University, and has won the major international prizes for painters, including the Divinity Circle and the International Painter's Medal. Hillary's exhibit features paintings that contain only water including waves, deep sea, and river.",
21 | "description": "
Hillary is a sophomore art sculpture student at New York University, and has already won all the major international prizes for new painters, including the Divinity Circle, the International Painter's Medal, and the Academy of Paris Award. Hillary's CAC exhibit features paintings that contain only water images including waves, deep sea, and river.
An avid water sports participant, Hillary understands the water in many ways in which others do not, or may not ever have the opportunity. Her goal in creating the CAC exhibit was to share with others the beauty, power, and flow of natural bodies of water throughout the world. In addition to the display, Hilary also hosts a session on Tuesday called Deep Sea Wonders, which combines her love of deep sea diving and snorkeling, with instruction for capturing the beauty of underwater explorations on canvas.
",
22 | "artwork": [
23 | "Hillary_Goldwynn_01_tn.jpg",
24 | "Hillary_Goldwynn_02_tn.jpg",
25 | "Hillary_Goldwynn_03_tn.jpg",
26 | "Hillary_Goldwynn_04_tn.jpg",
27 | "Hillary_Goldwynn_05_tn.jpg",
28 | "Hillary_Goldwynn_06_tn.jpg",
29 | "Hillary_Goldwynn_07_tn.jpg"
30 | ]
31 | },
32 | {
33 | "title": "The Art of Abstract",
34 | "name": "Riley Rudolph Rewington",
35 | "shortname": "Riley_Rewington",
36 | "summary": "The leader of the MMA artistic movement in his hometown of Portland, Riley Rudolph Rewington draws a crowd wherever he goes. Mixing street performance, video, music, and traditional art, Riley has created some of the most unique and deeply poignant abstract works of his generation.",
37 | "description": "
Riley started out as musician and street performance artist, and now blends painting and photography with audio, video, and computer multimedia to create what he calls 'Music and Multimedia Artworks.' Riley's innovations in using multimedia to express art have created a youth culture movement in his town of Portland, in which he remains at the forefront. In his role as the founder of the MMA art form, Riley has become an inspiration to many up and coming artists. However, the part Riley insists is most important to him, is that he's helped many troubled youth take control of their lives, and create their own unique, positive futuresponse. Seeing kids he's mentored graduate from high school and enroll in college, gives art the purpose that Riley so craves.
A first-year student at the Roux Academy of Art, Media, and Design, Riley is already changing the face of modern art at the university. Riley's exquisite abstract pieces have no intention of ever being understood, but instead beg the viewer to dream, create, pretend, and envision with their mind's eye. Riley will be speaking on the 'Art of Abstract' during Thursday's schedule.
",
38 | "artwork": [
39 | "Riley_Rewington_01_tn.jpg",
40 | "Riley_Rewington_02_tn.jpg",
41 | "Riley_Rewington_03_tn.jpg",
42 | "Riley_Rewington_04_tn.jpg",
43 | "Riley_Rewington_05_tn.jpg",
44 | "Riley_Rewington_06_tn.jpg"
45 | ]
46 | }
47 | ]
48 | }
--------------------------------------------------------------------------------
/provided/services/FeedbackService.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const util = require('util');
3 |
4 | const readFile = util.promisify(fs.readFile);
5 | const writeFile = util.promisify(fs.writeFile);
6 |
7 | /**
8 | * Logic for reading and writing feedback data
9 | */
10 | class FeedbackService {
11 | /**
12 | * Constructor
13 | * @param {*} datafile Path to a JSOn file that contains the feedback data
14 | */
15 | constructor(datafile) {
16 | this.datafile = datafile;
17 | }
18 |
19 | /**
20 | * Get all feedback items
21 | */
22 | async getList() {
23 | const data = await this.getData();
24 | return data;
25 | }
26 |
27 | /**
28 | * Add a new feedback item
29 | * @param {*} name The name of the user
30 | * @param {*} title The title of the feedback message
31 | * @param {*} message The feedback message
32 | */
33 | async addEntry(name, email, title, message) {
34 | const data = (await this.getData()) || [];
35 | data.unshift({ name, email, title, message });
36 | return writeFile(this.datafile, JSON.stringify(data));
37 | }
38 |
39 | /**
40 | * Fetches feedback data from the JSON file provided to the constructor
41 | */
42 | async getData() {
43 | const data = await readFile(this.datafile, 'utf8');
44 | if (!data) return [];
45 | return JSON.parse(data);
46 | }
47 | }
48 |
49 | module.exports = FeedbackService;
50 |
--------------------------------------------------------------------------------
/provided/services/SpeakerService.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const util = require("util");
3 |
4 | /**
5 | * We want to use async/await with fs.readFile - util.promisfy gives us that
6 | */
7 | const readFile = util.promisify(fs.readFile);
8 |
9 | /**
10 | * Logic for fetching speakers information
11 | */
12 | class SpeakerService {
13 | /**
14 | * Constructor
15 | * @param {*} datafile Path to a JSOn file that contains the speakers data
16 | */
17 | constructor(datafile) {
18 | this.datafile = datafile;
19 | }
20 |
21 | /**
22 | * Returns a list of speakers name and short name
23 | */
24 | async getNames() {
25 | const data = await this.getData();
26 |
27 | // We are using map() to transform the array we get into another one
28 | return data.map(speaker => {
29 | return { name: speaker.name, shortname: speaker.shortname };
30 | });
31 | }
32 |
33 | /**
34 | * Get all artwork
35 | */
36 | async getAllArtwork() {
37 | const data = await this.getData();
38 |
39 | // Array.reduce() is used to traverse all speakers and
40 | // create an array that contains all artwork
41 | const artwork = data.reduce((acc, elm) => {
42 | if (elm.artwork) {
43 | // eslint-disable-next-line no-param-reassign
44 | acc = [...acc, ...elm.artwork];
45 | }
46 | return acc;
47 | }, []);
48 | return artwork;
49 | }
50 |
51 | /**
52 | * Get all artwork of a given speaker
53 | * @param {*} shortname The speakers short name
54 | */
55 | async getArtworkForSpeaker(shortname) {
56 | const data = await this.getData();
57 | const speaker = data.find(elm => {
58 | return elm.shortname === shortname;
59 | });
60 | if (!speaker || !speaker.artwork) return null;
61 | return speaker.artwork;
62 | }
63 |
64 | /**
65 | * Get speaker information provided a shortname
66 | * @param {*} shortname
67 | */
68 | async getSpeaker(shortname) {
69 | const data = await this.getData();
70 | const speaker = data.find(elm => {
71 | return elm.shortname === shortname;
72 | });
73 | if (!speaker) return null;
74 | return {
75 | title: speaker.title,
76 | name: speaker.name,
77 | shortname: speaker.shortname,
78 | description: speaker.description
79 | };
80 | }
81 |
82 | /**
83 | * Returns a list of speakers with only the basic information
84 | */
85 | async getListShort() {
86 | const data = await this.getData();
87 | return data.map(speaker => {
88 | return {
89 | name: speaker.name,
90 | shortname: speaker.shortname,
91 | title: speaker.title
92 | };
93 | });
94 | }
95 |
96 | /**
97 | * Get a list of speakers
98 | */
99 | async getList() {
100 | const data = await this.getData();
101 | return data.map(speaker => {
102 | return {
103 | name: speaker.name,
104 | shortname: speaker.shortname,
105 | title: speaker.title,
106 | summary: speaker.summary
107 | };
108 | });
109 | }
110 |
111 | /**
112 | * Fetches speakers data from the JSON file provided to the constructor
113 | */
114 | async getData() {
115 | const data = await readFile(this.datafile, "utf8");
116 | return JSON.parse(data).speakers;
117 | }
118 | }
119 |
120 | module.exports = SpeakerService;
121 |
--------------------------------------------------------------------------------
/provided/static/Hillary_Goldwynn.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Roux Meetups--Speaker Info
6 |
8 |
9 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
45 |
46 |
Hillary is a sophomore art sculpture student at New York University, and
61 | has already won all the major international prizes for new painters, including
62 | the Divinity Circle, the International Painter's Medal, and the Academy
63 | of Paris Award. Hillary's CAC exhibit features paintings that contain
64 | only water images including waves, deep sea, and river.
65 |
An avid water sports participant, Hillary understands the water in many
66 | ways in which others do not, or may not ever have the opportunity. Her
67 | goal in creating the CAC exhibit was to share with others the beauty, power,
68 | and flow of natural bodies of water throughout the world. In addition to
69 | the display, Hilary also hosts a session on Tuesday called Deep Sea Wonders,
70 | which combines her love of deep sea diving and snorkeling, with instruction
71 | for capturing the beauty of underwater explorations on canvas.
The Roux Academy gets thousands of submissions every year for artists interesting in participating in the
96 | CAC exhibits, and selects approximately 200 distinct pieces of contemporary art for display in their
97 | collective exhibit.
98 | In addition, 12 individuals are honored as Featured Artists - each being granted his or her own exhibit
99 | hall to display entire collections or themed pieces.
100 |
Each Featured Artist has an opportunity to speak at one of our meetups and share his or her vision,
101 | perspective, and techniques with attendees on a more personal level than at our large conference. It is
102 | truly an honor to be a
103 | CAC Featured Artist and many past students artists who were featured at CAC have gone on to brilliant
104 | careers in art.
151 |
152 |
154 |
157 |
160 |
161 |
162 |
163 |
--------------------------------------------------------------------------------
/provided/static/js/feedback.js:
--------------------------------------------------------------------------------
1 | $(function feedback() {
2 | /**
3 | * Updates the DOM
4 | * @param {*} data XHR result
5 | */
6 | function updateFeedback(data) {
7 | const render = [];
8 | // Reset all status messages
9 | $('.feedback-status').empty();
10 |
11 | // All went well
12 | if (!data.errors && data.feedback) {
13 | // The input was valid - reset the form
14 | $('.feedback-form').trigger('reset');
15 |
16 | $.each(data.feedback, function createHtml(key, item) {
17 | render.push(`
18 |
19 |
20 |
21 |
22 |
${item.title}
23 | by ${item.name}
24 |
25 |
26 | ${item.message}
27 |
28 |
29 |
30 |
31 | `);
32 | });
33 | // Update feedback-items with what the REST API returned
34 | $('.feedback-items').html(render.join('\n'));
35 | // Output the success message
36 | $('.feedback-status').html(`
${data.successMessage}
`);
37 | } else {
38 | // There was an error
39 | // Create a list of errors
40 | $.each(data.errors, function createHtml(key, error) {
41 | render.push(`
42 |
${error.msg}
43 | `);
44 | });
45 | // Set the status message
46 | $('.feedback-status').html(
47 | `
64 | Hillary is a sophomore art sculpture student at New York University, and has won the major international
65 | prizes for painters, including the Divinity Circle and the International Painter's Medal.
66 | Hillary's exhibit features paintings that contain only water including waves, deep sea, and river.
67 |
84 | Hillary is a sophomore art sculpture student at New York University, and has won the major international
85 | prizes for painters, including the Divinity Circle and the International Painter's Medal.
86 | Hillary's exhibit features paintings that contain only water including waves, deep sea, and river.
87 |
104 | Hillary is a sophomore art sculpture student at New York University, and has won the major international
105 | prizes for painters, including the Divinity Circle and the International Painter's Medal.
106 | Hillary's exhibit features paintings that contain only water including waves, deep sea, and river.
107 |