diff --git a/config/config.json b/config/config.json index 37e61d87..5ecbf9f1 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..7bdad48a 100644 --- a/controllers/projects.js +++ b/controllers/projects.js @@ -1,40 +1,154 @@ let express = require('express') let db = require('../models') +const category = require('../models/category') let router = express.Router() +const methodOverride = require('method-override'); + + + + +// set up method override middleware +router.use(methodOverride('_method')); + +// DELETE /projects/:id - delete a project +router.delete('/:id', async (req, res) => { + try { + const deletedProject = await db.project.destroy({ + where: { id: req.params.id } + }) + + if (!deletedProject) throw Error() + + res.redirect('/') + } catch (error) { + res.status(400).render('main/404') + } +}) + +// DELETE /categories/:id - delete a category +router.delete('/categories/:id', async (req, res) => { + try { + const deletedCategory = await db.category.destroy({ + where: { id: req.params.id } + }) + + if (!deletedCategory) throw Error() + + res.redirect('/projects/categories') + } catch (error) { + res.status(400).render('main/404') + } +}) // 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) => { +// POST /projects - create a new project +router.post('/', async (req, res) => { + try { + const createdProject = await db.project.create({ + name: req.body.name, + githubLink: req.body.githubLink, + deployLink: req.body.deployedLink, + description: req.body.description + }) + + const [createdCategory] = await db.category.findOrCreate({ + where: { name: req.body.category }, + }) + + await createdProject.addCategory(createdCategory) + res.redirect('/') - }) - .catch((error) => { + } 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') }) -// GET /projects/:id - display a specific project -router.get('/:id', (req, res) => { - db.project.findOne({ - where: { id: req.params.id } - }) - .then((project) => { + +router.get('/category/:id', async (req, res) => { + try { + console.log("/categiries/ID:"+req.params.id); + + const category = await db.category.findOne({ + where: { id: req.params.id }, + include: db.project + }) + + if (!category) { + // return res.status(404).render('main/404') + return; + } + + res.render('projects/category', { category }) + } catch (error) { + console.log(`Error in GET /category/${req.params.id}`, error) + res.status(400).render('main/404') + } +}) + +router.get('/categories', async (req, res) => { + console.log("/categories"); + try { + const categories = await db.category.findAll() + res.render('projects/categories', { categories }) + } catch (error) { + console.log('Error in GET /categories', error) + res.status(400).render('main/404') + } +}) + +// GET /projects/new - display form for creating a new project +router.get('/:id', async (req, res) => { + console.log("/:id"); + try { + const project = await db.project.findOne({ + where: { id: req.params.id }, + include: [{ model: db.category }] // include the category associated with this project + }) + if (!project) throw Error() - res.render('projects/show', { project: project }) + + res.render('projects/show', { project }) + } catch (error) { + res.status(400).render('main/404') + } +}) + + +router.post('/:id/category', async (req, res) => { + try { + const project = await db.project.findOne({ + where: { id: req.params.id } + }) + + if (!project) throw Error() + + const [category, created] = await db.category.findOrCreate({ + where: { name: req.body.category }, + }) + + await project.addCategory(category) + + res.redirect(`/projects/${req.params.id}`) + } catch (error) { + res.status(400).render('main/404') + } +}) +/* +router.get('/categories/:id', (req, res) => { + console.log("/categoriwa/:id"); + db.category.findAll() + .then((projects) => { + res.render('projects/categories', { categories: categories }) }) .catch((error) => { + console.log('Error in GET /', error) res.status(400).render('main/404') }) }) +*/ module.exports = router diff --git a/dbTest.js b/dbTest.js new file mode 100644 index 00000000..e69de29b diff --git a/index.js b/index.js index f404f83d..efa8dfcb 100644 --- a/index.js +++ b/index.js @@ -29,7 +29,10 @@ app.get('*', (req, res) => { res.render('main/404') }) + + app.listen(PORT, function() { rowdy.print() console.log(`listening on port: ${PORT}`) }) + diff --git a/migrations/20230405222641-create-category.js b/migrations/20230405222641-create-category.js new file mode 100644 index 00000000..8e52fd79 --- /dev/null +++ b/migrations/20230405222641-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/20230405223451-create-categories-projects.js b/migrations/20230405223451-create-categories-projects.js new file mode 100644 index 00000000..4e407a24 --- /dev/null +++ b/migrations/20230405223451-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..f7dd25c6 --- /dev/null +++ b/models/category.js @@ -0,0 +1,24 @@ +'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; +}; \ No newline at end of file diff --git a/models/project.js b/models/project.js index 735a0a47..0a5c6506 100644 --- a/models/project.js +++ b/models/project.js @@ -11,6 +11,9 @@ module.exports = (sequelize, DataTypes) => { */ static associate(models) { // define association here + models.project.belongsToMany(models.category, { + through: 'categoriesProjects' + }) } } project.init({ diff --git a/package.json b/package.json index cbce809b..eeba47f0 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,13 @@ "ejs": "^2.4.2", "express": "^4.16.4", "express-ejs-layouts": "^2.1.0", + "method-override": "^3.0.0", "morgan": "^1.7.0", "pg": "^8.5.1", "rowdy-logger": "0.0.2", "sequelize": "^6.3.5" - } + }, + "description": "To practice N:M associations, we'll be adding the ability to categorize projects in an existing project organizer.", + "keywords": [], + "author": "" } diff --git a/scratch.txt b/scratch.txt new file mode 100644 index 00000000..57548865 --- /dev/null +++ b/scratch.txt @@ -0,0 +1,5 @@ +sequelize model:create --name category --attributes name:string + + + +sequelize model:create --name categoriesProjects --attributes categoryId:integer,projectId:interger \ No newline at end of file diff --git a/views/main/index.ejs b/views/main/index.ejs index 97655c09..d9fffc89 100644 --- a/views/main/index.ejs +++ b/views/main/index.ejs @@ -12,5 +12,10 @@

<%= project.name %>

+
+ +
<% }); %> + + diff --git a/views/partials/navbar.ejs b/views/partials/navbar.ejs index 081dee3b..81431969 100644 --- a/views/partials/navbar.ejs +++ b/views/partials/navbar.ejs @@ -16,6 +16,9 @@ + diff --git a/views/projects/categories.ejs b/views/projects/categories.ejs new file mode 100644 index 00000000..5bf09f88 --- /dev/null +++ b/views/projects/categories.ejs @@ -0,0 +1,10 @@ +<% categories.forEach(function(category) { %> +
+

+ <%= category.name %> +

+
+ +
+
+ <% }); %> \ No newline at end of file diff --git a/views/projects/category.ejs b/views/projects/category.ejs new file mode 100644 index 00000000..5647bbb3 --- /dev/null +++ b/views/projects/category.ejs @@ -0,0 +1,12 @@ + + +

<%= category.name %>

+

Projects with this tag:

+ \ No newline at end of file diff --git a/views/projects/new.ejs b/views/projects/new.ejs index 3342d3ee..8c8f31d2 100644 --- a/views/projects/new.ejs +++ b/views/projects/new.ejs @@ -1,25 +1,30 @@ -

Create a new project

-
-
- - -
+ Create a new project + + +

Create a new project

+ +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ -
- - -
- -
- - -
- -
- - -
- - - diff --git a/views/projects/show.ejs b/views/projects/show.ejs index aea2f8cb..6c6e9e8b 100644 --- a/views/projects/show.ejs +++ b/views/projects/show.ejs @@ -1,17 +1,27 @@

<%= project.name %>

- Github Link - Deployed Link -

<%= project.description %>

+<% project.categories.forEach(function(category) { %> -
+
+

+ <%= category.name %> +

+
+<% }); %> -← Back Home +
+
+
+ + +
+ +
\ No newline at end of file