create folders table

This commit is contained in:
Takeshi Kimata
2024-02-12 12:20:37 +09:00
parent 8de8d06399
commit 197a011c4c
13 changed files with 261 additions and 32 deletions

View File

@@ -6,7 +6,7 @@ const app = express();
const cors = require("cors"); const cors = require("cors");
const corsOptions = { const corsOptions = {
origin: "http://localhost:3000", origin: "http://localhost:3000",
methods: "GET,HEAD,PUT,PATCH,POST,DELETE" methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
}; };
app.use(cors(corsOptions)); app.use(cors(corsOptions));
@@ -15,13 +15,13 @@ app.use(express.json());
// init sequalize // init sequalize
const sequelize = new Sequelize({ const sequelize = new Sequelize({
dialect: 'sqlite', dialect: "sqlite",
storage: 'database.sqlite', storage: "database.sqlite",
}); });
// "/" // "/"
const indexRoute = require('./routes/index'); const indexRoute = require("./routes/index");
app.use('/', indexRoute); app.use("/", indexRoute);
// "/projects" // "/projects"
const projectsIndexRoute = require('./routes/projects/index')(sequelize); const projectsIndexRoute = require('./routes/projects/index')(sequelize);
@@ -29,6 +29,12 @@ const projectsNewRoute = require('./routes/projects/new')(sequelize);
app.use('/projects', projectsIndexRoute); app.use('/projects', projectsIndexRoute);
app.use('/projects', projectsNewRoute); app.use('/projects', projectsNewRoute);
// "/folders"
const foldersIndexRoute = require('./routes/folders/index')(sequelize);
const foldersNewRoute = require('./routes/folders/new')(sequelize);
app.use('/folders', foldersIndexRoute);
app.use('/folders', foldersNewRoute);
const PORT = process.env.PORT || 3001; const PORT = process.env.PORT || 3001;
app.listen(PORT, () => { app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`); console.log(`Server is running on port ${PORT}`);

View File

@@ -14,7 +14,7 @@ module.exports = {
}, },
detail: { detail: {
type: Sequelize.STRING, type: Sequelize.STRING,
allowNull: false, allowNull: true,
}, },
createdAt: { createdAt: {
type: Sequelize.DATE, type: Sequelize.DATE,

View File

@@ -0,0 +1,48 @@
'use strict';
/** @type {import('sequelize-cli').Migration} */
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('folders', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
name: {
type: Sequelize.STRING,
allowNull: false,
},
detail: {
type: Sequelize.STRING,
allowNull: true,
},
parentFolderId: {
type: Sequelize.INTEGER,
allowNull: true,
},
projectId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: 'Projects',
key: 'id',
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
},
},
createdAt: {
type: Sequelize.DATE,
allowNull: false,
},
updatedAt: {
type: Sequelize.DATE,
allowNull: false,
},
});
},
async down (queryInterface, Sequelize) {
await queryInterface.dropTable('folders');
}
};

24
backend/models/folders.js Normal file
View File

@@ -0,0 +1,24 @@
function defineFolder(sequelize, DataTypes) {
const Folder = sequelize.define("Folder", {
name: {
type: DataTypes.STRING,
allowNull: false,
},
detail: {
type: DataTypes.STRING,
allowNull: true,
},
parentFolderId: {
type: DataTypes.INTEGER,
allowNull: true,
},
projectId: {
type: DataTypes.INTEGER,
allowNull: false,
},
});
return Folder;
}
module.exports = defineFolder;

View File

@@ -6,7 +6,7 @@ function defineProject(sequelize, DataTypes) {
}, },
detail: { detail: {
type: DataTypes.STRING, type: DataTypes.STRING,
allowNull: false, allowNull: true,
}, },
}); });

View File

@@ -0,0 +1,30 @@
const express = require("express");
const router = express.Router();
const defineFolder = require('../../models/folders');
const { DataTypes } = require('sequelize');
module.exports = function(sequelize) {
const Folder = defineFolder(sequelize, DataTypes)
router.get("/", async (req, res) => {
const { projectId } = req.query;
if (!projectId) {
return res.status(400).json({ error: 'projectId is required' });
}
try {
const folders = await Folder.findAll({
where: {
projectId: projectId
}
});
res.json(folders);
} catch (error) {
console.error(error);
res.status(500).send("Internal Server Error");
}
});
return router;
};

View File

@@ -0,0 +1,32 @@
const express = require("express");
const router = express.Router();
const defineFolder = require("../../models/folders");
const { DataTypes } = require("sequelize");
module.exports = function (sequelize) {
const Folder = defineFolder(sequelize, DataTypes);
router.post("/", async (req, res) => {
try {
const { name, detail, projectId, parentFolderId } = req.body;
if (!name || !projectId) {
return res
.status(400)
.json({ error: "Name and projectId are required" });
}
const newFolder = await Folder.create({
name,
detail,
projectId,
parentFolderId,
});
res.json(newFolder);
} catch (error) {
res.status(500).json({ error: "Internal server error" });
}
});
return router;
};

View File

@@ -1,4 +1,4 @@
#!/bin/bash #!/bin/bash
npx sequelize db:migrate:undo:all npx sequelize db:migrate:undo:all
echo "Dropped 'Project' table." echo "Dropped all tables"

View File

@@ -2,7 +2,8 @@
module.exports = { module.exports = {
up: async (queryInterface, Sequelize) => { up: async (queryInterface, Sequelize) => {
return queryInterface.bulkInsert('Projects', [ // Add projects table records
await queryInterface.bulkInsert('Projects', [
{ {
name: 'Project 1', name: 'Project 1',
detail: 'Details of Project 1', detail: 'Details of Project 1',
@@ -11,13 +12,34 @@ module.exports = {
}, },
{ {
name: 'Project 2', name: 'Project 2',
detail: 'Details of Project 2',
createdAt: new Date(), createdAt: new Date(),
updatedAt: new Date(), updatedAt: new Date(),
}, },
{ {
name: 'Project 3', name: 'Project 3',
detail: 'Details of Project 3', createdAt: new Date(),
updatedAt: new Date(),
},
]);
// Add folders table records
await queryInterface.bulkInsert('folders', [
{
name: 'Folder 1',
detail: 'Details of Folder 1',
projectId: 1,
createdAt: new Date(),
updatedAt: new Date(),
},
{
name: 'Folder 2',
projectId: 1,
createdAt: new Date(),
updatedAt: new Date(),
},
{
name: 'Folder 3',
projectId: 1,
createdAt: new Date(), createdAt: new Date(),
updatedAt: new Date(), updatedAt: new Date(),
}, },
@@ -25,6 +47,6 @@ module.exports = {
}, },
down: async (queryInterface, Sequelize) => { down: async (queryInterface, Sequelize) => {
// do nothing // do nothingg
}, },
}; };

View File

@@ -0,0 +1,64 @@
"use client";
import { useEffect, useState } from "react";
import Config from "@/config/config";
const apiServer = Config.apiServer;
/**
* fetch folder records
*
* @param {string} url - API endpoint url
* @returns {Promise<Array>} - project record array
* @throws {Error}
*/
async function fetchFolders(url) {
try {
const response = await fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error("Error fetching data:", error.message);
}
}
export default function Page({ params }: { params: { id: string } }) {
const [folders, setFolders] = useState([]);
const url = `${apiServer}/folders?projectId=${params.id}`;
useEffect(() => {
async function fetchDataEffect() {
try {
const data = await fetchFolders(url);
setFolders(data);
} catch (error) {
console.error("Error in effect:", error.message);
}
}
fetchDataEffect();
}, []);
return (
<div>
<div>Project: {params.id}</div>
<div className="flex flex-wrap gap-4 mt-5">
{folders.map((folder, index) => (
<div key={index}>
<div>{folder.name}</div>
<div>{folder.detail}</div>
<div>{folder.projectId}</div>
</div>
))}
</div>
</div>
);
}

View File

@@ -149,7 +149,7 @@ export default function ProjectsPage() {
projectName.text, projectName.text,
projectDetail.text projectDetail.text
); );
setProjects([...projects, newProject]) setProjects([...projects, newProject]);
closeModal(); closeModal();
} }
}; };

View File

@@ -6,10 +6,12 @@ import {
Divider, Divider,
Image, Image,
} from "@nextui-org/react"; } from "@nextui-org/react";
import NextLink from "next/link";
export function ProjectCard({ projectName, projectDetail }) { export function ProjectCard({ projectName, projectDetail }) {
return ( return (
<Card className="w-[250px]"> <NextLink href={`/projects/${1}`}>
<Card className="w-[250px] hover:bg-slate-200">
<CardHeader className="flex gap-3"> <CardHeader className="flex gap-3">
<Image <Image
alt="nextui logo" alt="nextui logo"
@@ -27,5 +29,6 @@ export function ProjectCard({ projectName, projectDetail }) {
<p>{projectDetail}</p> <p>{projectDetail}</p>
</CardBody> </CardBody>
</Card> </Card>
</NextLink>
); );
} }