diff --git a/README.md b/README.md index 76d6d581..1fd7414b 100644 --- a/README.md +++ b/README.md @@ -6,15 +6,18 @@ To read the full directions, please go to the [practicum instructions](https://a **Put your HubSpot developer test account custom objects URL link here:** https://app.hubspot.com/contacts/l/objects/${custom-obj-number}/views/all/list -___ +--- + ## Tips: + - Commit to your repository often. Even if you make small tweaks to your code, it’s best to be committing to your repository frequently. - The subject of the custom object is up to you. Feel free to get creative! - Please create a test account and include your private app access token in your repo. - Ensure you re-merge any working branches into the main branch. -- DO NOT ADD YOUR PRIVATE APP TOKEN TO YOUR REPOSITORY. +- DO NOT ADD YOUR PRIVATE APP TOKEN TO YOUR REPOSITORY. ## Pre-requisites: + - Using [Node](https://nodejs.org/en/download) and node packages - Using [Express](https://expressjs.com/en/starter/installing.html) - Using [Axios](https://axios-http.com/docs/intro) @@ -23,6 +26,11 @@ ___ - Using [Git and GitHub](https://product.hubspot.com/blog/git-and-github-tutorial-for-beginners) ## Requirements + - 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. + +## custom object link + +https://app.hubspot.com/contacts/22600910/objects/2-43438964/views/all/list diff --git a/index.js b/index.js index f337a32d..63c5a79b 100644 --- a/index.js +++ b/index.js @@ -1,27 +1,81 @@ -const express = require('express'); -const axios = require('axios'); +require("dotenv").config(); +const express = require("express"); +const axios = require("axios"); const app = express(); -app.set('view engine', 'pug'); -app.use(express.static(__dirname + '/public')); +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 = ''; +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 +app.get("/", async (req, res) => { + const customObjectUrl = `https://api.hubapi.com/crm/v3/objects/2-43438964?properties=pet_name,pet_dimensions,pet_color`; + const headers = { + Authorization: `Bearer ${PRIVATE_APP_ACCESS}`, + "Content-Type": "application/json", + }; + try { + const resp = await axios.get(customObjectUrl, { headers }); + const data = resp.data.results; + + res.render("homepage", { + title: "Homepage | Custom Object", + records: data, + }); + console.log(JSON.stringify(resp.data.results, null, 2)); + } catch (error) { + console.error("Errore nella GET /:", error.response?.data || error.message); + res.status(500).send("Error fetching data"); + } +}); // 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 +app.get("/update-cobj", async (req, res) => { + res.render("updates", { + title: "Update Custom Object Form | HubSpot 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 +app.post("/update-cobj", async (req, res) => { + const { pet_name, pet_dimensions, pet_color } = req.body; + const customObjectUrl = + "https://api.hubapi.com/crm/v3/objects/2-43438964?properties=pet_name,pet_dimensions,pet_color"; + const headers = { + Authorization: `Bearer ${PRIVATE_APP_ACCESS}`, + "Content-Type": "application/json", + }; + + const payload = { + properties: { + pet_name, + pet_dimensions, + pet_color, + }, + }; + + try { + await axios.post(customObjectUrl, payload, { headers }); + res.redirect("/"); + } catch (error) { + console.error( + "Errore nella POST /update-cobj:", + error.response?.data || error.message + ); + res.status(500).send("Errore nella creazione del record"); + } +}); /** * * This is sample code to give you a reference for how you should structure your calls. @@ -66,6 +120,5 @@ app.post('/update', async (req, res) => { }); */ - // * Localhost -app.listen(3000, () => console.log('Listening on http://localhost:3000')); \ No newline at end of file +app.listen(3000, () => console.log("Listening on http://localhost:3000")); diff --git a/package.json b/package.json index 62db37aa..70a987ca 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "license": "ISC", "dependencies": { "axios": "^1.3.5", + "dotenv": "^16.5.0", "express": "^4.18.2", - "pug": "^3.0.2" + "pug": "^3.0.3" } } diff --git a/views/contacts.pug b/views/contacts.pug deleted file mode 100644 index c600ca01..00000000 --- a/views/contacts.pug +++ /dev/null @@ -1,15 +0,0 @@ -//- ** This is a sample of a pug template and how it uses the data passed to it from index.js. - -//- 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 Contacts -//- .cards -//- each contact in data -//- .card -//- h2.card__name #{contact.properties.firstname} #{contact.properties.lastname} -//- p.card__email #{contact.properties.email} \ No newline at end of file diff --git a/views/homepage.pug b/views/homepage.pug new file mode 100644 index 00000000..84601ee4 --- /dev/null +++ b/views/homepage.pug @@ -0,0 +1,23 @@ +//- ** This is a sample of a pug template and how it uses the data passed to it from index.js. + +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/Update this table + table(border="1") + thead + tr + th Name + th Dimension + th Color + tbody + each record in records + tr + td= record.properties.pet_name + td= record.properties.pet_dimensions + td= record.properties.pet_color \ No newline at end of file diff --git a/views/updates.pug b/views/updates.pug new file mode 100644 index 00000000..728a9d96 --- /dev/null +++ b/views/updates.pug @@ -0,0 +1,26 @@ +//- ** This is a sample of a pug template and how it uses the data passed to it from index.js. + +ddoctype html +html + head + title= title + body + h1 Update Custom Object Form | Integrating With HubSpot I Practicum + + form(method="POST", action="/update-cobj") + label(for="pet_name") Name: + input(type="text", name="pet_name", required) + br + + label(for="pet_dimensions") Dimension: + input(type="text", name="pet_dimensions", required) + br + + label(for="pet_color") Color: + input(type="text", name="pet_color", required) + br + + button(type="submit") Crea + + br + a(href="/") ← Return to homepage