From 8fe090167adb303036c18b2c3c4412aae1913b57 Mon Sep 17 00:00:00 2001 From: Andrew Date: Wed, 5 Apr 2023 23:25:00 -0400 Subject: [PATCH 1/4] Add categories when creating new project --- config/config.json | 12 +-- controllers/projects.js | 77 +++++++++++-------- dbTest.js | 16 ++++ migrations/20230405222904-create-category.js | 28 +++++++ ...230405223808-create-categories-projects.js | 31 ++++++++ models/categoriesprojects.js | 24 ++++++ models/category.js | 27 +++++++ models/project.js | 46 ++++++----- views/projects/new.ejs | 39 ++++++++-- 9 files changed, 230 insertions(+), 70 deletions(-) create mode 100644 dbTest.js create mode 100644 migrations/20230405222904-create-category.js create mode 100644 migrations/20230405223808-create-categories-projects.js create mode 100644 models/categoriesprojects.js create mode 100644 models/category.js diff --git a/config/config.json b/config/config.json index 37e61d87..8b2587ba 100644 --- a/config/config.json +++ b/config/config.json @@ -1,17 +1,9 @@ { "development": { + "username": "sequelize", + "password": "sequelize", "database": "project_organizer_development", "host": "127.0.0.1", "dialect": "postgres" - }, - "test": { - "database": "project_organizer_test", - "host": "127.0.0.1", - "dialect": "postgres" - }, - "production": { - "database": "project_organizer_production", - "host": "127.0.0.1", - "dialect": "postgres" } } diff --git a/controllers/projects.js b/controllers/projects.js index 3d878a8a..b012227d 100644 --- a/controllers/projects.js +++ b/controllers/projects.js @@ -1,40 +1,49 @@ -let express = require('express') -let db = require('../models') -let router = express.Router() +let express = require("express"); +let db = require("../models"); +let router = express.Router(); -// POST /projects - create a new project -router.post('/', (req, res) => { - db.project.create({ - name: req.body.name, - githubLink: req.body.githubLink, - deployLink: req.body.deployedLink, - description: req.body.description - }) - .then((project) => { - res.redirect('/') - }) - .catch((error) => { - res.status(400).render('main/404') - }) -}) +router.post("/", async (req, res) => { + try { + const newProject = await db.project.create({ + name: req.body.name, + githubLink: req.body.githubLink, + deployLink: req.body.deployedLink, + description: req.body.description, + }); + const categoryInputs = await req.body.category.split(", "); + console.log(categoryInputs); + categoryInputs.forEach(async (categoryInput) => { + const [category] = await db.category.findOrCreate({ + where: { + name: categoryInput, + }, + }); + newProject.addCategory(category); + }); + res.redirect("../"); + } catch (error) { + res.status(400).render("main/404"); + } +}); // GET /projects/new - display form for creating a new project -router.get('/new', (req, res) => { - res.render('projects/new') -}) +router.get("/new", (req, res) => { + res.render("projects/new"); +}); // GET /projects/:id - display a specific project -router.get('/:id', (req, res) => { - db.project.findOne({ - where: { id: req.params.id } - }) - .then((project) => { - if (!project) throw Error() - res.render('projects/show', { project: project }) - }) - .catch((error) => { - res.status(400).render('main/404') - }) -}) +router.get("/:id", (req, res) => { + db.project + .findOne({ + where: { id: req.params.id }, + }) + .then((project) => { + if (!project) throw Error(); + res.render("projects/show", { project: project }); + }) + .catch((error) => { + res.status(400).render("main/404"); + }); +}); -module.exports = router +module.exports = router; diff --git a/dbTest.js b/dbTest.js new file mode 100644 index 00000000..4f746be9 --- /dev/null +++ b/dbTest.js @@ -0,0 +1,16 @@ +const db = require("./models"); + +db.project + .findOne({ + where: { id: 1 }, + include: [db.category], + }) + .then((project) => { + // by using eager loading, the project model should have a categories key + console.log(project.categories); + + // createCategory function should be available to this model - it will create the category then add it to the project + project.createCategory({ name: "express" }).then((category) => { + console.log(category.id); + }); + }); diff --git a/migrations/20230405222904-create-category.js b/migrations/20230405222904-create-category.js new file mode 100644 index 00000000..8e52fd79 --- /dev/null +++ b/migrations/20230405222904-create-category.js @@ -0,0 +1,28 @@ +'use strict'; +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable('categories', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + name: { + type: Sequelize.STRING + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + async down(queryInterface, Sequelize) { + await queryInterface.dropTable('categories'); + } +}; \ No newline at end of file diff --git a/migrations/20230405223808-create-categories-projects.js b/migrations/20230405223808-create-categories-projects.js new file mode 100644 index 00000000..4e407a24 --- /dev/null +++ b/migrations/20230405223808-create-categories-projects.js @@ -0,0 +1,31 @@ +'use strict'; +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable('categoriesProjects', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + categoryId: { + type: Sequelize.INTEGER + }, + projectId: { + type: Sequelize.INTEGER + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + async down(queryInterface, Sequelize) { + await queryInterface.dropTable('categoriesProjects'); + } +}; \ No newline at end of file diff --git a/models/categoriesprojects.js b/models/categoriesprojects.js new file mode 100644 index 00000000..ddb47da2 --- /dev/null +++ b/models/categoriesprojects.js @@ -0,0 +1,24 @@ +'use strict'; +const { + Model +} = require('sequelize'); +module.exports = (sequelize, DataTypes) => { + class categoriesProjects extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + } + } + categoriesProjects.init({ + categoryId: DataTypes.INTEGER, + projectId: DataTypes.INTEGER + }, { + sequelize, + modelName: 'categoriesProjects', + }); + return categoriesProjects; +}; \ No newline at end of file diff --git a/models/category.js b/models/category.js new file mode 100644 index 00000000..1221e7a2 --- /dev/null +++ b/models/category.js @@ -0,0 +1,27 @@ +"use strict"; +const { Model } = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class category extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + models.category.belongsToMany(models.project, { + through: "categoriesProjects", + }); + } + } + category.init( + { + name: DataTypes.STRING, + }, + { + sequelize, + modelName: "category", + } + ); + return category; +}; diff --git a/models/project.js b/models/project.js index 735a0a47..e0396ae0 100644 --- a/models/project.js +++ b/models/project.js @@ -1,7 +1,5 @@ -'use strict'; -const { - Model -} = require('sequelize'); +"use strict"; +const { Model } = require("sequelize"); module.exports = (sequelize, DataTypes) => { class project extends Model { /** @@ -11,24 +9,30 @@ module.exports = (sequelize, DataTypes) => { */ static associate(models) { // define association here + models.project.belongsToMany(models.category, { + through: "categoriesProjects", + }); } } - project.init({ - githubLink: { - type: DataTypes.TEXT, - validate: { isUrl: true } + project.init( + { + githubLink: { + type: DataTypes.TEXT, + validate: { isUrl: true }, + }, + name: DataTypes.STRING, + deployLink: { + type: DataTypes.TEXT, + validate: { isUrl: true }, + }, + description: { + type: DataTypes.TEXT, + }, }, - name: DataTypes.STRING, - deployLink: { - type: DataTypes.TEXT, - validate: { isUrl: true } - }, - description: { - type: DataTypes.TEXT - }, - }, { - sequelize, - modelName: 'project', - }); + { + sequelize, + modelName: "project", + } + ); return project; -}; \ No newline at end of file +}; diff --git a/views/projects/new.ejs b/views/projects/new.ejs index 3342d3ee..9ac769d8 100644 --- a/views/projects/new.ejs +++ b/views/projects/new.ejs @@ -3,23 +3,52 @@
- +
- +
- + +
+ +
+ +
- +
- +
From f37e58b18c46d47e71914d429cceeded2a241741 Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 6 Apr 2023 00:59:31 -0400 Subject: [PATCH 2/4] Complete deliverable --- controllers/categories.js | 32 ++++++++++++++++++++ index.js | 60 ++++++++++++++++++++------------------ views/categories/index.ejs | 11 +++++++ views/categories/show.ejs | 16 ++++++++++ views/partials/navbar.ejs | 11 +++++-- 5 files changed, 99 insertions(+), 31 deletions(-) create mode 100644 controllers/categories.js create mode 100644 views/categories/index.ejs create mode 100644 views/categories/show.ejs diff --git a/controllers/categories.js b/controllers/categories.js new file mode 100644 index 00000000..85041a7a --- /dev/null +++ b/controllers/categories.js @@ -0,0 +1,32 @@ +let express = require("express"); +let db = require("../models"); +let router = express.Router(); + +router.get("/", (req, res) => { + db.category + .findAll() + .then((categories) => { + res.render("categories/index", { categories: categories }); + }) + .catch((error) => { + console.log("Error in GET /", error); + res.status(400).render("main/404"); + }); +}); + +// GET /categories/:id - display a specific category +router.get("/:id", async (req, res) => { + try { + const category = await db.category.findOne({ + where: { id: req.params.id }, + }); + if (!category) throw Error(); + const projects = await category.getProjects(); + res.render("categories/show", { category: category, projects: projects }); + } catch (error) { + console.log(error); + res.status(400).render("main/404"); + } +}); + +module.exports = router; diff --git a/index.js b/index.js index f404f83d..baf4b471 100644 --- a/index.js +++ b/index.js @@ -1,35 +1,37 @@ -const express = require('express') -const ejsLayouts = require('express-ejs-layouts') -const db = require('./models') -const rowdy = require('rowdy-logger') +const express = require("express"); +const ejsLayouts = require("express-ejs-layouts"); +const db = require("./models"); +const rowdy = require("rowdy-logger"); -const app = express() -const PORT = process.env.PORT || 3000 -rowdy.begin(app) +const app = express(); +const PORT = process.env.PORT || 3000; +rowdy.begin(app); -app.set('view engine', 'ejs') -app.use(require('morgan')('dev')) -app.use(express.urlencoded({ extended: false })) -app.use(ejsLayouts) +app.set("view engine", "ejs"); +app.use(require("morgan")("dev")); +app.use(express.urlencoded({ extended: false })); +app.use(ejsLayouts); -app.get('/', (req, res) => { - db.project.findAll() - .then((projects) => { - res.render('main/index', { projects: projects }) - }) - .catch((error) => { - console.log('Error in GET /', error) - res.status(400).render('main/404') - }) -}) +app.get("/", (req, res) => { + db.project + .findAll() + .then((projects) => { + res.render("main/index", { projects: projects }); + }) + .catch((error) => { + console.log("Error in GET /", error); + res.status(400).render("main/404"); + }); +}); -app.use('/projects', require('./controllers/projects')) +app.use("/projects", require("./controllers/projects")); +app.use("/categories", require("./controllers/categories")); -app.get('*', (req, res) => { - res.render('main/404') -}) +app.get("*", (req, res) => { + res.render("main/404"); +}); -app.listen(PORT, function() { - rowdy.print() - console.log(`listening on port: ${PORT}`) -}) +app.listen(PORT, function () { + rowdy.print(); + console.log(`listening on port: ${PORT}`); +}); diff --git a/views/categories/index.ejs b/views/categories/index.ejs new file mode 100644 index 00000000..60bd5607 --- /dev/null +++ b/views/categories/index.ejs @@ -0,0 +1,11 @@ +

Categories

+ +<% if (categories.length < 1) { %> +

Better get coding, I've no categories!

+<% } %> <% categories.forEach(function(category) { %> + +<% }); %> diff --git a/views/categories/show.ejs b/views/categories/show.ejs new file mode 100644 index 00000000..c829eb53 --- /dev/null +++ b/views/categories/show.ejs @@ -0,0 +1,16 @@ +

Category: <%= category.name %>

+ +

Projects that fall under this category

+ +<% projects.forEach(function(project) { %> + +<% }); %> + + +
+ +← Back Home diff --git a/views/partials/navbar.ejs b/views/partials/navbar.ejs index 081dee3b..64246a51 100644 --- a/views/partials/navbar.ejs +++ b/views/partials/navbar.ejs @@ -2,7 +2,12 @@
+
From f4318551af3a91762cc715d835074dd3dfdc4f17 Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 6 Apr 2023 23:37:46 -0400 Subject: [PATCH 3/4] Include node version --- package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package.json b/package.json index cbce809b..9dd406b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,9 @@ { "name": "express-project-organizer", "version": "1.0.0", + "engines": { + "node": "18.15.0" + }, "main": "index.js", "scripts": { "start": "node index.js" From b96c223cb183fc8cb3f62592aab2581c09783fb0 Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 6 Apr 2023 23:47:37 -0400 Subject: [PATCH 4/4] Fix sequelize config --- config/config.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/config/config.json b/config/config.json index 8b2587ba..4c46361c 100644 --- a/config/config.json +++ b/config/config.json @@ -5,5 +5,9 @@ "database": "project_organizer_development", "host": "127.0.0.1", "dialect": "postgres" + }, + "production": { + "use_env_variable": "DATABASE_URL", + "dialect": "postgres" } }