From ddfc253f3fc12f796ea264232d70cec0ab777324 Mon Sep 17 00:00:00 2001 From: gitmgkelly <139564619+gitmgkelly@users.noreply.github.com> Date: Mon, 12 May 2025 11:10:19 -0500 Subject: [PATCH 1/7] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 76d6d581..5d1baa18 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.hubspot.com/contacts/49758588/objects/2-44649687/views/all/list ___ ## Tips: From da1095ac6a05db396858dd153b87df5d473e66f2 Mon Sep 17 00:00:00 2001 From: MGKelly Date: Mon, 12 May 2025 11:20:05 -0500 Subject: [PATCH 2/7] First commit to my Integrating With HubSpot I: Foundations practicum repository. From 987f234aaf87e8345a098d04ed994d9ad095d610 Mon Sep 17 00:00:00 2001 From: MGKelly Date: Mon, 12 May 2025 11:27:12 -0500 Subject: [PATCH 3/7] Update to code. From b8e7cdc1bff5e78bda51ee99df24b04288da297b Mon Sep 17 00:00:00 2001 From: MGKelly Date: Mon, 12 May 2025 11:29:01 -0500 Subject: [PATCH 4/7] Update From d663fce3945592d9995a22800351ff7e781109ea Mon Sep 17 00:00:00 2001 From: MGKelly Date: Mon, 12 May 2025 11:35:52 -0500 Subject: [PATCH 5/7] Update .env to include correct object name From 226b5a4ffe685daa85fb587c3dd36f5bb174f6d6 Mon Sep 17 00:00:00 2001 From: MGKelly Date: Mon, 12 May 2025 11:37:06 -0500 Subject: [PATCH 6/7] Try #2 on updating custom object name in .env From 20affedf55ccd6245320ae7657aace1012030b18 Mon Sep 17 00:00:00 2001 From: MGKelly Date: Mon, 12 May 2025 11:40:45 -0500 Subject: [PATCH 7/7] Add Express routes and Pug templates for custom object --- index.js | 121 +++++++++++++++++++++++---------------------- views/homepage.pug | 21 ++++++++ views/updates.pug | 21 ++++++++ 3 files changed, 104 insertions(+), 59 deletions(-) create mode 100644 views/homepage.pug create mode 100644 views/updates.pug diff --git a/index.js b/index.js index f337a32d..41427e7d 100644 --- a/index.js +++ b/index.js @@ -1,71 +1,74 @@ +// Load environment variables from .env +require('dotenv').config(); + +// Imports const express = require('express'); const axios = require('axios'); +const path = require('path'); + +// Create Express app const app = express(); +const PORT = process.env.PORT || 3000; +// Tell Express where to find Pug templates and static files app.set('view engine', 'pug'); -app.use(express.static(__dirname + '/public')); -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 = ''; - -// 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 - -// 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 - -// 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'; - const headers = { - Authorization: `Bearer ${PRIVATE_APP_ACCESS}`, - 'Content-Type': 'application/json' - } - try { - const resp = await axios.get(contacts, { headers }); - const data = resp.data.results; - res.render('contacts', { title: 'Contacts | HubSpot APIs', data }); - } catch (error) { - console.error(error); - } +app.set('views', path.join(__dirname, 'views')); +app.use(express.static(path.join(__dirname, 'public'))); +app.use(express.urlencoded({ extended: false })); + +// Pre-configured Axios client for HubSpot API +const hubspot = axios.create({ + baseURL: 'https://api.hubapi.com', + headers: { + Authorization: `Bearer ${process.env.HUBSPOT_ACCESS_TOKEN}`, + 'Content-Type': 'application/json' + } }); -* * App.post sample -app.post('/update', async (req, res) => { - const update = { - properties: { - "favorite_book": req.body.newVal - } - } - - const email = req.query.email; - const updateContact = `https://api.hubapi.com/crm/v3/objects/contacts/${email}?idProperty=email`; - const headers = { - Authorization: `Bearer ${PRIVATE_APP_ACCESS}`, - 'Content-Type': 'application/json' - }; +// ROUTE 1: Homepage – list all records +app.get('/', async (req, res, next) => { + try { + const resp = await hubspot.get( + `/crm/v3/objects/${process.env.HUBSPOT_OBJECT_NAME}`, + { params: { properties: 'name,bio,species', limit: 100 } } + ); + res.render('homepage', { + title: 'My Custom Objects', + items: resp.data.results + }); + } catch (err) { + next(err); + } +}); - try { - await axios.patch(updateContact, update, { headers } ); - res.redirect('back'); - } catch(err) { - console.error(err); - } +// ROUTE 2: Show form to add a record +app.get('/update-cobj', (req, res) => { + res.render('updates', { + title: 'Update Custom Object Form | IWH-I Practicum' + }); +}); +// ROUTE 3: Handle form submission & create record +app.post('/update-cobj', async (req, res, next) => { + const { name, bio, species } = req.body; + try { + await hubspot.post( + `/crm/v3/objects/${process.env.HUBSPOT_OBJECT_NAME}`, + { properties: { name, bio, species } } + ); + res.redirect('/'); + } catch (err) { + next(err); + } }); -*/ +// Simple error handler +app.use((err, req, res, next) => { + console.error(err); + res.status(500).send('Oops—something went wrong!'); +}); -// * Localhost -app.listen(3000, () => console.log('Listening on http://localhost:3000')); \ No newline at end of file +// Start the server +app.listen(PORT, () => + console.log(`Server running at http://localhost:${PORT}`) +); diff --git a/views/homepage.pug b/views/homepage.pug new file mode 100644 index 00000000..b58a7725 --- /dev/null +++ b/views/homepage.pug @@ -0,0 +1,21 @@ +doctype html +html + head + meta(charset="utf-8") + title= title + link(rel="stylesheet", href="/css/style.css") + body + h1= title + a(href="/update-cobj") Add to this table + table(border="1") + thead + tr + th Name + th Bio + th Species + tbody + each item in items + tr + td= item.properties.name + td= item.properties.bio + td= item.properties.species diff --git a/views/updates.pug b/views/updates.pug new file mode 100644 index 00000000..e20e64dc --- /dev/null +++ b/views/updates.pug @@ -0,0 +1,21 @@ +doctype html +html + head + meta(charset="utf-8") + title= title + link(rel="stylesheet", href="/css/style.css") + body + h1= title + a(href="/") ← Return to the homepage + form(action="/update-cobj", method="POST") + div + label(for="name") Name: + input#name(type="text", name="name", required) + div + label(for="bio") Bio: + textarea#bio(name="bio") + div + label(for="species") Species: + input#species(type="text", name="species") + div + button(type="submit") Create Record