From 330a4804715553da91f1ae0a88ec3f7a98b412c3 Mon Sep 17 00:00:00 2001 From: Simon Taylor Date: Fri, 25 Apr 2025 16:45:52 +0100 Subject: [PATCH 01/11] Add test account custom objects URL to readme file --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 76d6d581..b1cc9f16 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This repository is for the Integrating With HubSpot I: Foundations course. This To read the full directions, please go to the [practicum instructions](https://app.hubspot.com/academy/l/tracks/1092124/1093824/5493?language=en). -**Put your HubSpot developer test account custom objects URL link here:** https://app.hubspot.com/contacts/l/objects/${custom-obj-number}/views/all/list +**Put your HubSpot developer test account custom objects URL link here:** https://app-eu1.hubspot.com/contacts/146092380/objects/2-141961374/views/all/list ___ ## Tips: From 9231936e29fb1e693c9afe1d002b48ae36e5f68a Mon Sep 17 00:00:00 2001 From: Simon Taylor Date: Fri, 25 Apr 2025 16:47:38 +0100 Subject: [PATCH 02/11] First commit to my Integrating With HubSpot I: Foundations practicum repository. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b1cc9f16..1444d6ce 100644 --- a/README.md +++ b/README.md @@ -26,3 +26,4 @@ ___ - All work must be your own. During the grading process we will check the revision history. Submissions that do not meet this requirement will not be considered. - You must have at least two new routes in your index.js file and one new pug template for the homepage. - You must create a developer test account and link to it in your README.md file. Submissions that do not meet this requirement will not be considered. + From 7a84dc320255b032d492b774e222c212fc4355f2 Mon Sep 17 00:00:00 2001 From: Simon Taylor Date: Fri, 25 Apr 2025 21:25:50 +0100 Subject: [PATCH 03/11] Created an app.get route for /update-cobj --- index.js | 7 ++++--- views/updates.pug | 8 ++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 views/updates.pug diff --git a/index.js b/index.js index f337a32d..a6cfb16c 100644 --- a/index.js +++ b/index.js @@ -14,10 +14,11 @@ const PRIVATE_APP_ACCESS = ''; // * Code for Route 1 goes here -// TODO: ROUTE 2 - Create a new app.get route for the form to create or update new custom object data. Send this data along in the next route. - -// * Code for Route 2 goes here +// DONE : ROUTE 2 - Create a new app.get route for the form to create or update new custom object data. Send this data along in the next route. +app.get('/update-cobj', (req, res) => { + res.render('updates', { title: 'Update Custom Object Form | Integrating With HubSpot I Practicum' }); +}); // TODO: ROUTE 3 - Create a new app.post route for the custom objects form to create or update your custom object data. Once executed, redirect the user to the homepage. // * Code for Route 3 goes here diff --git a/views/updates.pug b/views/updates.pug new file mode 100644 index 00000000..1829fc33 --- /dev/null +++ b/views/updates.pug @@ -0,0 +1,8 @@ +doctype html +html + head + title= `${title}` + meta(name="viewport" content="width=device-width, initial-scale=1") + link(rel="stylesheet", href="/css/style.css") + body + a(href="/") Return to the homepage \ No newline at end of file From 31e33298d9e3a1b91d6462d67b66d97e10d84efa Mon Sep 17 00:00:00 2001 From: Simon Taylor Date: Mon, 28 Apr 2025 10:03:29 +0100 Subject: [PATCH 04/11] re-created custom object to make name unique --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1444d6ce..bddcc0ec 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This repository is for the Integrating With HubSpot I: Foundations course. This To read the full directions, please go to the [practicum instructions](https://app.hubspot.com/academy/l/tracks/1092124/1093824/5493?language=en). -**Put your HubSpot developer test account custom objects URL link here:** https://app-eu1.hubspot.com/contacts/146092380/objects/2-141961374/views/all/list +**Put your HubSpot developer test account custom objects URL link here:** https://app-eu1.hubspot.com/contacts/146092380/objects/2-142064740/views/all/list ___ ## Tips: From 78b087239fea929fa9739c969134d790a93c595a Mon Sep 17 00:00:00 2001 From: Simon Taylor Date: Mon, 28 Apr 2025 10:03:43 +0100 Subject: [PATCH 05/11] require dotenv for secure key storage --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 62db37aa..4eda7957 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "axios": "^1.3.5", + "dotenv": "^16.5.0", "express": "^4.18.2", "pug": "^3.0.2" } From 18d88cccc77fdf2095b6b89ac23393340b23cafc Mon Sep 17 00:00:00 2001 From: Simon Taylor Date: Mon, 28 Apr 2025 10:37:32 +0100 Subject: [PATCH 06/11] require dotenv for private key. and add app.post route --- index.js | 53 +++++++++++++++++++++++------------------------------ 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/index.js b/index.js index a6cfb16c..fb098b98 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,5 @@ +require('dotenv').config(); + const express = require('express'); const axios = require('axios'); const app = express(); @@ -8,65 +10,56 @@ app.use(express.urlencoded({ extended: true })); app.use(express.json()); // * Please DO NOT INCLUDE the private app access token in your repo. Don't do this practicum in your normal account. -const PRIVATE_APP_ACCESS = ''; +// Get private app access token from .env file +const PRIVATE_APP_ACCESS = process.env.PRIVATE_APP_ACCESS; // TODO: ROUTE 1 - Create a new app.get route for the homepage to call your custom object data. Pass this data along to the front-end and create a new pug template in the views folder. -// * Code for Route 1 goes here - -// DONE : ROUTE 2 - Create a new app.get route for the form to create or update new custom object data. Send this data along in the next route. - -app.get('/update-cobj', (req, res) => { - res.render('updates', { title: 'Update Custom Object Form | Integrating With HubSpot I Practicum' }); -}); -// TODO: ROUTE 3 - Create a new app.post route for the custom objects form to create or update your custom object data. Once executed, redirect the user to the homepage. - -// * Code for Route 3 goes here - -/** -* * This is sample code to give you a reference for how you should structure your calls. - -* * App.get sample -app.get('/contacts', async (req, res) => { - const contacts = 'https://api.hubspot.com/crm/v3/objects/contacts'; +app.get('/', async (req, res) => { + const animals = 'https://api.hubspot.com/crm/v3/objects/animals?properties=name,class,number_of_legs'; const headers = { Authorization: `Bearer ${PRIVATE_APP_ACCESS}`, 'Content-Type': 'application/json' } try { - const resp = await axios.get(contacts, { headers }); + const resp = await axios.get(animals, { headers }); const data = resp.data.results; - res.render('contacts', { title: 'Contacts | HubSpot APIs', data }); + res.render('homepage', { title: 'Custom Object Listing | Integrating With HubSpot I Practicum', data }); } catch (error) { console.error(error); } }); -* * App.post sample +// DONE : ROUTE 2 - Create a new app.get route for the form to create or update new custom object data. Send this data along in the next route. + +app.get('/update-cobj', (req, res) => { + res.render('updates', { title: 'Update Custom Object Form | Integrating With HubSpot I Practicum' }); +}); + +// TODO: ROUTE 3 - Create a new app.post route for the custom objects form to create or update your custom object data. Once executed, redirect the user to the homepage. + app.post('/update', async (req, res) => { - const update = { + const newAnimal = { properties: { - "favorite_book": req.body.newVal + "name" : req.body.name, + "class": req.body.class, + "number_of_legs": req.body.number_of_legs, } } - const email = req.query.email; - const updateContact = `https://api.hubapi.com/crm/v3/objects/contacts/${email}?idProperty=email`; + const createAnimal = `https://api.hubapi.com/crm/v3/objects/animals`; + const headers = { Authorization: `Bearer ${PRIVATE_APP_ACCESS}`, 'Content-Type': 'application/json' }; - try { - await axios.patch(updateContact, update, { headers } ); + await axios.post(createAnimal, newAnimal, { headers } ); res.redirect('back'); } catch(err) { console.error(err); } - }); -*/ - // * Localhost app.listen(3000, () => console.log('Listening on http://localhost:3000')); \ No newline at end of file From e7fbd35b12819dd5550b4c1bf9c2618947366348 Mon Sep 17 00:00:00 2001 From: Simon Taylor Date: Mon, 28 Apr 2025 10:37:45 +0100 Subject: [PATCH 07/11] Create homepage view for object listings --- views/homepage.pug | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 views/homepage.pug diff --git a/views/homepage.pug b/views/homepage.pug new file mode 100644 index 00000000..7790e696 --- /dev/null +++ b/views/homepage.pug @@ -0,0 +1,21 @@ +doctype html +html + head + title= `${title}` + meta(name="viewport" content="width=device-width, initial-scale=1") + link(rel="stylesheet", href="/css/style.css") + body + h1 Custom Object Table + a(href="/update-cobj") Add a new animal + table + thead + tr + th Name + th Class + th Number of Legs + tbody + each animal in data + tr + td #{animal.properties.name} + td #{animal.properties.class} + td #{animal.properties.number_of_legs} \ No newline at end of file From 0ec1a1ebb1b70774eb158c428aa6fab9cc7d5b17 Mon Sep 17 00:00:00 2001 From: Simon Taylor Date: Mon, 28 Apr 2025 10:38:01 +0100 Subject: [PATCH 08/11] Create form to add new animals --- views/updates.pug | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/views/updates.pug b/views/updates.pug index 1829fc33..a335c370 100644 --- a/views/updates.pug +++ b/views/updates.pug @@ -5,4 +5,12 @@ html meta(name="viewport" content="width=device-width, initial-scale=1") link(rel="stylesheet", href="/css/style.css") body - a(href="/") Return to the homepage \ No newline at end of file + a(href="/") Return to the homepage + form(action="/update" method="POST") + label(for="name") Name: + input(type="text" name="name" required) + label(for="class") Class: + input(type="text" name="class" required) + label(for="number_of_legs") Number of Legs: + input(type="number" name="number_of_legs" required) + button(type="submit") Submit \ No newline at end of file From fcd3bbdc69384822b06375d7a8d97a01da2f7742 Mon Sep 17 00:00:00 2001 From: Simon Taylor Date: Mon, 28 Apr 2025 10:39:25 +0100 Subject: [PATCH 09/11] updated custom styling --- public/css/style.css | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/public/css/style.css b/public/css/style.css index 85587bb4..2d3870ff 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -40,6 +40,20 @@ h1 { box-shadow: 3px 2px 6px lightgrey; } +table { + margin-top: 1rem; + width: auto; + border-collapse: collapse; +} +th, td { + padding: 0.5rem; + text-align: left; + border: 1px solid black; +} +th { + background-color: rgb(255, 225, 225); +} + label, input { margin-top: 5px; display: block; @@ -50,7 +64,7 @@ input[type="text"] { padding: .25rem; } -input[type="submit"] { +button[type="submit"] { background-color: lightgrey; border: none; padding: .375rem 1rem; From 1ed1c663beb9aba0269789fa6dd2e05775519c23 Mon Sep 17 00:00:00 2001 From: Simon Taylor Date: Mon, 28 Apr 2025 10:40:37 +0100 Subject: [PATCH 10/11] Correct link text --- views/homepage.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/homepage.pug b/views/homepage.pug index 7790e696..57152cd7 100644 --- a/views/homepage.pug +++ b/views/homepage.pug @@ -6,7 +6,7 @@ html link(rel="stylesheet", href="/css/style.css") body h1 Custom Object Table - a(href="/update-cobj") Add a new animal + a(href="/update-cobj") Add to this table table thead tr From ea34119fdfbd91357fa221964359801d1bd57c43 Mon Sep 17 00:00:00 2001 From: Simon Taylor Date: Mon, 28 Apr 2025 10:45:18 +0100 Subject: [PATCH 11/11] Fix redirect --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index fb098b98..01fb7cd4 100644 --- a/index.js +++ b/index.js @@ -55,7 +55,7 @@ app.post('/update', async (req, res) => { }; try { await axios.post(createAnimal, newAnimal, { headers } ); - res.redirect('back'); + res.redirect('/'); } catch(err) { console.error(err); }