refactor: class model function
This commit is contained in:
parent
80de2108b8
commit
4ced73bca2
30
config/config.js
Normal file
30
config/config.js
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import dotenv from "dotenv";
|
||||
|
||||
dotenv.config();
|
||||
|
||||
export default {
|
||||
development: {
|
||||
username: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD,
|
||||
database: process.env.DB_NAME,
|
||||
host: process.env.DB_HOST,
|
||||
dialect: "mysql",
|
||||
timezone: "+07:00",
|
||||
},
|
||||
test: {
|
||||
username: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD,
|
||||
database: process.env.DB_NAME_TEST,
|
||||
host: process.env.DB_HOST,
|
||||
dialect: "mysql",
|
||||
timezone: "+07:00",
|
||||
},
|
||||
production: {
|
||||
username: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD,
|
||||
database: process.env.DB_NAME,
|
||||
host: process.env.DB_HOST,
|
||||
dialect: "mysql",
|
||||
timezone: "+07:00",
|
||||
},
|
||||
};
|
||||
|
|
@ -272,7 +272,6 @@ export const getLevelsByTopicId = async (req, res) => {
|
|||
.json({ message: "No levels found for the given topic." });
|
||||
}
|
||||
|
||||
// Mencari pembelajaran terakhir yang selesai
|
||||
const lastCompletedLearning = await models.StdLearning.findOne({
|
||||
where: {
|
||||
ID: ID,
|
||||
|
|
@ -290,7 +289,6 @@ export const getLevelsByTopicId = async (req, res) => {
|
|||
|
||||
let currentLearningLevel = null;
|
||||
|
||||
// Jika ada pembelajaran yang selesai, kita dapat memeriksa level berikutnya dari NEXT_LEARNING
|
||||
if (lastCompletedLearning?.NEXT_LEARNING) {
|
||||
currentLearningLevel = await models.Level.findOne({
|
||||
where: {
|
||||
|
|
@ -303,7 +301,6 @@ export const getLevelsByTopicId = async (req, res) => {
|
|||
|
||||
const nextLearningLevel = currentLearningLevel;
|
||||
|
||||
// Memasukkan level berikutnya (jika ada) ke dalam UNLOCKED_LEVELS
|
||||
const unlockedLevels = lastCompletedLearning
|
||||
? await models.Level.findAll({
|
||||
where: {
|
||||
|
|
@ -321,8 +318,10 @@ export const getLevelsByTopicId = async (req, res) => {
|
|||
|
||||
const unlockedLevelNames = unlockedLevels.map((lvl) => lvl.NAME_LEVEL);
|
||||
|
||||
// Menambahkan level berikutnya ke dalam UNLOCKED_LEVELS jika belum termasuk
|
||||
if (nextLearningLevel && !unlockedLevelNames.includes(nextLearningLevel.NAME_LEVEL)) {
|
||||
if (
|
||||
nextLearningLevel &&
|
||||
!unlockedLevelNames.includes(nextLearningLevel.NAME_LEVEL)
|
||||
) {
|
||||
unlockedLevelNames.push(nextLearningLevel.NAME_LEVEL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,95 @@ export const getClassById = async (req, res) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const getClassForAdmin = async (req, res) => {
|
||||
const { page = 1, limit = 10, search = "", sort = "time" } = req.query;
|
||||
|
||||
try {
|
||||
const { count, rows: classes } = await models.Class.findAndCountAll({
|
||||
where: {
|
||||
...(search && {
|
||||
[models.Op.or]: [
|
||||
{
|
||||
NAME_CLASS: {
|
||||
[models.Op.like]: `%${search}%`,
|
||||
},
|
||||
},
|
||||
models.Sequelize.where(
|
||||
models.Sequelize.literal(
|
||||
`(SELECT COUNT(*) FROM student WHERE student.ID_CLASS = class.ID_CLASS)`
|
||||
),
|
||||
{
|
||||
[models.Op.like]: `%${search}%`,
|
||||
}
|
||||
),
|
||||
{
|
||||
TOTAL_STUDENT: {
|
||||
[models.Op.like]: `%${search}%`,
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
attributes: [
|
||||
"ID_CLASS",
|
||||
"NAME_CLASS",
|
||||
"TOTAL_STUDENT",
|
||||
"TIME_CLASS",
|
||||
[
|
||||
models.Sequelize.literal(
|
||||
`(SELECT COUNT(*) FROM student WHERE student.ID_CLASS = class.ID_CLASS)`
|
||||
),
|
||||
"STUDENTS",
|
||||
],
|
||||
],
|
||||
distinct: true,
|
||||
});
|
||||
|
||||
const formattedClasses = classes.map((classItem) => ({
|
||||
ID_CLASS: classItem.ID_CLASS,
|
||||
NAME_CLASS: classItem.NAME_CLASS,
|
||||
STUDENTS: classItem.get("STUDENTS"),
|
||||
TOTAL_STUDENT: classItem.TOTAL_STUDENT,
|
||||
TIME_CLASS: classItem.TIME_CLASS,
|
||||
}));
|
||||
|
||||
if (sort === "class") {
|
||||
formattedClasses.sort((a, b) => a.NAME_CLASS.localeCompare(b.NAME_CLASS));
|
||||
} else if (sort === "total") {
|
||||
formattedClasses.sort((a, b) => a.TOTAL_STUDENT - b.TOTAL_STUDENT);
|
||||
} else if (sort === "students") {
|
||||
formattedClasses.sort((a, b) => a.STUDENTS - b.STUDENTS);
|
||||
} else {
|
||||
formattedClasses.sort(
|
||||
(a, b) => new Date(b.TIME_CLASS) - new Date(a.TIME_CLASS)
|
||||
);
|
||||
}
|
||||
|
||||
const paginatedClasses = formattedClasses.slice(
|
||||
(page - 1) * limit,
|
||||
page * limit
|
||||
);
|
||||
|
||||
const totalPages = Math.ceil(count / limit);
|
||||
const currentPage = parseInt(page);
|
||||
|
||||
response(
|
||||
200,
|
||||
{
|
||||
classes: paginatedClasses,
|
||||
currentPage,
|
||||
totalPages,
|
||||
totalItems: count,
|
||||
},
|
||||
"Classes retrieved successfully",
|
||||
res
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
response(500, null, "Error retrieving classes data!", res);
|
||||
}
|
||||
};
|
||||
|
||||
export const createClass = async (req, res) => {
|
||||
const { NAME_CLASS, TOTAL_STUDENT } = req.body;
|
||||
|
||||
|
|
@ -85,9 +174,28 @@ export const deleteClassById = async (req, res) => {
|
|||
return response(404, null, "Class not found", res);
|
||||
}
|
||||
|
||||
await models.Student.update(
|
||||
{ ID_CLASS: null },
|
||||
{
|
||||
where: { ID_CLASS: id },
|
||||
}
|
||||
);
|
||||
|
||||
await models.Monitoring.update(
|
||||
{ ID_CLASS: null },
|
||||
{
|
||||
where: { ID_CLASS: id },
|
||||
}
|
||||
);
|
||||
|
||||
await classes.destroy();
|
||||
|
||||
response(200, null, "Class deleted successfully", res);
|
||||
response(
|
||||
200,
|
||||
null,
|
||||
"Class deleted successfully and related models updated",
|
||||
res
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
response(500, null, "Internal Server Error", res);
|
||||
|
|
|
|||
|
|
@ -111,8 +111,11 @@ export const updateMonitoringClass = async ({
|
|||
};
|
||||
|
||||
export const monitoringStudentsProgress = async (req, res) => {
|
||||
const { page = 1, limit = 10, search = "", sort = "time" } = req.query;
|
||||
|
||||
try {
|
||||
const result = await models.Monitoring.findAll({
|
||||
const { count, rows: monitorings } =
|
||||
await models.Monitoring.findAndCountAll({
|
||||
include: [
|
||||
{
|
||||
model: models.StdLearning,
|
||||
|
|
@ -159,10 +162,37 @@ export const monitoringStudentsProgress = async (req, res) => {
|
|||
],
|
||||
},
|
||||
],
|
||||
where: {
|
||||
...(search && {
|
||||
[models.Op.or]: [
|
||||
{
|
||||
"$stdLearningMonitoring.learningUser.students.NISN$": {
|
||||
[models.Op.like]: `%${search}%`,
|
||||
},
|
||||
},
|
||||
{
|
||||
"$stdLearningMonitoring.learningUser.NAME_USERS$": {
|
||||
[models.Op.like]: `%${search}%`,
|
||||
},
|
||||
},
|
||||
{
|
||||
"$stdLearningMonitoring.level.levelTopic.topicSection.NAME_SECTION$":
|
||||
{
|
||||
[models.Op.like]: `%${search}%`,
|
||||
},
|
||||
},
|
||||
{
|
||||
"$stdLearningMonitoring.level.levelTopic.NAME_TOPIC$": {
|
||||
[models.Op.like]: `%${search}%`,
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
distinct: true,
|
||||
});
|
||||
|
||||
const formattedResult = result.map((monitoring) => {
|
||||
return {
|
||||
const formattedResult = monitorings.map((monitoring) => ({
|
||||
ID_MONITORING: monitoring.ID_MONITORING,
|
||||
NISN: monitoring.stdLearningMonitoring?.learningUser?.students?.NISN,
|
||||
NAME_USERS: monitoring.stdLearningMonitoring?.learningUser?.NAME_USERS,
|
||||
|
|
@ -174,12 +204,37 @@ export const monitoringStudentsProgress = async (req, res) => {
|
|||
NAME_CLASS:
|
||||
monitoring.stdLearningMonitoring?.learningUser?.students?.studentClass
|
||||
?.NAME_CLASS ?? null,
|
||||
};
|
||||
});
|
||||
}));
|
||||
|
||||
if (sort === "nisn") {
|
||||
formattedResult.sort((a, b) => a.NISN.localeCompare(b.NISN));
|
||||
} else if (sort === "name") {
|
||||
formattedResult.sort((a, b) => a.NAME_USERS.localeCompare(b.NAME_USERS));
|
||||
} else if (sort === "section") {
|
||||
formattedResult.sort((a, b) =>
|
||||
a.NAME_SECTION.localeCompare(b.NAME_SECTION)
|
||||
);
|
||||
} else if (sort === "topic") {
|
||||
formattedResult.sort((a, b) => a.NAME_TOPIC.localeCompare(b.NAME_TOPIC));
|
||||
} else {
|
||||
formattedResult.sort((a, b) => new Date(b.TIME) - new Date(a.TIME));
|
||||
}
|
||||
|
||||
const paginatedResult = formattedResult.slice(
|
||||
(page - 1) * limit,
|
||||
page * limit
|
||||
);
|
||||
const totalPages = Math.ceil(count / limit);
|
||||
const currentPage = parseInt(page);
|
||||
|
||||
response(
|
||||
200,
|
||||
formattedResult,
|
||||
{
|
||||
monitorings: paginatedResult,
|
||||
currentPage,
|
||||
totalPages,
|
||||
totalItems: count,
|
||||
},
|
||||
"Success retrieving student monitoring progress!",
|
||||
res
|
||||
);
|
||||
|
|
@ -191,6 +246,7 @@ export const monitoringStudentsProgress = async (req, res) => {
|
|||
|
||||
export const monitoringStudentProgressById = async (req, res) => {
|
||||
const { id } = req.params;
|
||||
const { page = 1, limit = 10, search = "", sort = "start" } = req.query;
|
||||
|
||||
try {
|
||||
const monitoring = await models.Monitoring.findOne({
|
||||
|
|
@ -213,6 +269,32 @@ export const monitoringStudentProgressById = async (req, res) => {
|
|||
model: models.Level,
|
||||
as: "level",
|
||||
attributes: ["ID_TOPIC", "NAME_LEVEL"],
|
||||
include: [
|
||||
{
|
||||
model: models.Topic,
|
||||
as: "levelTopic",
|
||||
attributes: ["NAME_TOPIC"],
|
||||
include: [
|
||||
{
|
||||
model: models.Section,
|
||||
as: "topicSection",
|
||||
attributes: ["NAME_SECTION"],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
model: models.User,
|
||||
as: "learningUser",
|
||||
attributes: ["NAME_USERS"],
|
||||
include: [
|
||||
{
|
||||
model: models.Student,
|
||||
as: "students",
|
||||
attributes: ["NISN"],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -231,10 +313,38 @@ export const monitoringStudentProgressById = async (req, res) => {
|
|||
|
||||
const userID = stdLearning.ID;
|
||||
const topicID = stdLearning.level.ID_TOPIC;
|
||||
const studentName = stdLearning.learningUser.NAME_USERS;
|
||||
const nisn = stdLearning.learningUser.students.NISN;
|
||||
const topicName = stdLearning.level.levelTopic.NAME_TOPIC;
|
||||
const sectionName = stdLearning.level.levelTopic.topicSection.NAME_SECTION;
|
||||
|
||||
const levels = await models.StdLearning.findAll({
|
||||
// Fetch levels with pagination, search, and sort
|
||||
const levels = await models.StdLearning.findAndCountAll({
|
||||
where: {
|
||||
ID: userID,
|
||||
...(search && {
|
||||
[models.Op.or]: [
|
||||
{
|
||||
"$level.NAME_LEVEL$": { [models.Op.like]: `%${search}%` },
|
||||
},
|
||||
{
|
||||
SCORE: { [models.Op.like]: `%${search}%` },
|
||||
},
|
||||
{
|
||||
FEEDBACK_STUDENT: { [models.Op.like]: `%${search}%` },
|
||||
},
|
||||
// {
|
||||
// [models.Sequelize.fn('DATE_FORMAT', models.Sequelize.col('STUDENT_START'), '%Y-%m-%d')]: {
|
||||
// [models.Op.like]: `%${search}%`,
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// [models.Sequelize.fn('DATE_FORMAT', models.Sequelize.col('STUDENT_FINISH'), '%Y-%m-%d')]: {
|
||||
// [models.Op.like]: `%${search}%`,
|
||||
// },
|
||||
// },
|
||||
],
|
||||
}),
|
||||
},
|
||||
include: [
|
||||
{
|
||||
|
|
@ -252,18 +362,10 @@ export const monitoringStudentProgressById = async (req, res) => {
|
|||
"STUDENT_START",
|
||||
"STUDENT_FINISH",
|
||||
],
|
||||
distinct: true,
|
||||
});
|
||||
|
||||
if (levels.length === 0) {
|
||||
return response(
|
||||
404,
|
||||
null,
|
||||
"No levels found for the given user and topic!",
|
||||
res
|
||||
);
|
||||
}
|
||||
|
||||
const levelArray = levels
|
||||
const levelArray = levels.rows
|
||||
.map((learning) => ({
|
||||
NAME_LEVEL: learning.level.NAME_LEVEL,
|
||||
SCORE: learning.SCORE,
|
||||
|
|
@ -272,18 +374,35 @@ export const monitoringStudentProgressById = async (req, res) => {
|
|||
STUDENT_FINISH: learning.STUDENT_FINISH,
|
||||
}))
|
||||
.sort((a, b) => {
|
||||
if (a.NAME_LEVEL === "Pretest") return -1;
|
||||
if (b.NAME_LEVEL === "Pretest") return 1;
|
||||
|
||||
const levelNumberA = parseInt(a.NAME_LEVEL.replace("Level ", ""), 10);
|
||||
const levelNumberB = parseInt(b.NAME_LEVEL.replace("Level ", ""), 10);
|
||||
return levelNumberA - levelNumberB;
|
||||
if (sort === "level") {
|
||||
return a.NAME_LEVEL.localeCompare(b.NAME_LEVEL);
|
||||
} else if (sort === "score") {
|
||||
return b.SCORE - a.SCORE;
|
||||
} else if (sort === "feedback") {
|
||||
return a.FEEDBACK_STUDENT.localeCompare(b.FEEDBACK_STUDENT);
|
||||
} else if (sort === "start") {
|
||||
return new Date(a.STUDENT_START) - new Date(b.STUDENT_START);
|
||||
} else if (sort === "finish") {
|
||||
return new Date(a.STUDENT_FINISH) - new Date(b.STUDENT_FINISH);
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
// Pagination logic
|
||||
const paginatedResult = levelArray.slice((page - 1) * limit, page * limit);
|
||||
const totalPages = Math.ceil(levels.count / limit);
|
||||
const currentPage = parseInt(page);
|
||||
|
||||
const result = {
|
||||
ID_MONITORING: monitoring.ID_MONITORING,
|
||||
levels: levelArray,
|
||||
FEEDBACK_GURU: monitoring.FEEDBACK_GURU,
|
||||
NAME_SECTION: sectionName,
|
||||
NAME_TOPIC: topicName,
|
||||
NAME_USERS: studentName,
|
||||
NISN: nisn,
|
||||
levels: paginatedResult,
|
||||
currentPage,
|
||||
totalPages,
|
||||
totalItems: levels.count,
|
||||
};
|
||||
|
||||
response(200, result, "Success retrieving student progress!", res);
|
||||
|
|
|
|||
51
database/migrations/20241012202559-create-users.cjs
Normal file
51
database/migrations/20241012202559-create-users.cjs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
const { Sequelize } = require("sequelize");
|
||||
|
||||
module.exports = {
|
||||
async up(queryInterface) {
|
||||
await queryInterface.createTable("users", {
|
||||
ID: {
|
||||
type: Sequelize.UUID,
|
||||
primaryKey: true,
|
||||
defaultValue: Sequelize.UUIDV4,
|
||||
allowNull: false,
|
||||
},
|
||||
NAME_USERS: {
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: false,
|
||||
},
|
||||
EMAIL: {
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: false,
|
||||
},
|
||||
PASSWORD: {
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: false,
|
||||
},
|
||||
ROLE: {
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
},
|
||||
PICTURE: {
|
||||
type: Sequelize.STRING(1024),
|
||||
allowNull: true,
|
||||
},
|
||||
REFRESH_TOKEN: {
|
||||
type: Sequelize.STRING(256),
|
||||
allowNull: true,
|
||||
},
|
||||
TIME_USERS: {
|
||||
type: Sequelize.DATE,
|
||||
defaultValue: Sequelize.NOW,
|
||||
},
|
||||
});
|
||||
|
||||
await queryInterface.addConstraint("users", {
|
||||
fields: ["EMAIL"],
|
||||
type: "unique",
|
||||
name: "user_unique_email",
|
||||
});
|
||||
},
|
||||
async down(queryInterface) {
|
||||
await queryInterface.dropTable("users");
|
||||
},
|
||||
};
|
||||
21
database/seeders/20241012193900-create-admin-user.cjs
Normal file
21
database/seeders/20241012193900-create-admin-user.cjs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
const bcrypt = require('bcrypt');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
|
||||
module.exports = {
|
||||
up: async (queryInterface) => {
|
||||
const hashedPassword = await bcrypt.hash('adminsealspolinema24', 10);
|
||||
await queryInterface.bulkInsert('users', [
|
||||
{
|
||||
ID: uuidv4(),
|
||||
NAME_USERS: 'Administrator',
|
||||
EMAIL: 'adminseals@gmail.com',
|
||||
PASSWORD: hashedPassword,
|
||||
ROLE: 'admin',
|
||||
TIME_USERS: new Date(),
|
||||
},
|
||||
]);
|
||||
},
|
||||
down: async (queryInterface) => {
|
||||
await queryInterface.bulkDelete('users', { EMAIL: 'adminseals@gmail.com' });
|
||||
},
|
||||
};
|
||||
14
generateMigration.js
Normal file
14
generateMigration.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { execSync } from "child_process";
|
||||
|
||||
const name = process.argv[2];
|
||||
if (!name) {
|
||||
console.error("Error: Migration name is required.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
execSync(
|
||||
`npx sequelize-cli migration:generate --migrations-path database/migrations --config config/config.js --name ${name}`,
|
||||
{ stdio: "inherit" }
|
||||
);
|
||||
|
||||
execSync("node renameFiles.js", { stdio: "inherit" });
|
||||
14
generateSeed.js
Normal file
14
generateSeed.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { execSync } from "child_process";
|
||||
|
||||
const name = process.argv[2];
|
||||
if (!name) {
|
||||
console.error("Error: Migration name is required.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
execSync(
|
||||
`npx sequelize-cli seed:generate --seeders-path database/seeders --config config/config.js --name ${name}`,
|
||||
{ stdio: "inherit" }
|
||||
);
|
||||
|
||||
execSync("node renameFiles.js", { stdio: "inherit" });
|
||||
|
|
@ -21,7 +21,7 @@ const ClassModel = (DataTypes) => {
|
|||
},
|
||||
},
|
||||
TOTAL_STUDENT: {
|
||||
type: DataTypes.INTEGER,
|
||||
type: DataTypes.INTEGER(11),
|
||||
allowNull: true,
|
||||
},
|
||||
TIME_CLASS: {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ const StudentModel = (DataTypes) => {
|
|||
},
|
||||
},
|
||||
NISN: {
|
||||
type: DataTypes.INTEGER,
|
||||
type: DataTypes.BIGINT(11),
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
validate: {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ const TeacherModel = (DataTypes) => {
|
|||
},
|
||||
},
|
||||
NIP: {
|
||||
type: DataTypes.INTEGER,
|
||||
type: DataTypes.BIGINT(11),
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
validate: {
|
||||
|
|
|
|||
|
|
@ -14,14 +14,14 @@ const UserModel = (DataTypes) => {
|
|||
},
|
||||
},
|
||||
NAME_USERS: {
|
||||
type: DataTypes.STRING,
|
||||
type: DataTypes.STRING(100),
|
||||
allowNull: false,
|
||||
validate: {
|
||||
notEmpty: true,
|
||||
},
|
||||
},
|
||||
EMAIL: {
|
||||
type: DataTypes.STRING,
|
||||
type: DataTypes.STRING(100),
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
validate: {
|
||||
|
|
@ -30,19 +30,20 @@ const UserModel = (DataTypes) => {
|
|||
},
|
||||
},
|
||||
PASSWORD: {
|
||||
type: DataTypes.STRING,
|
||||
type: DataTypes.STRING(100),
|
||||
allowNull: false,
|
||||
},
|
||||
ROLE: {
|
||||
type: DataTypes.STRING,
|
||||
type: DataTypes.STRING(100),
|
||||
allowNull: true,
|
||||
},
|
||||
PICTURE: {
|
||||
type: DataTypes.STRING,
|
||||
type: DataTypes.STRING(1024),
|
||||
allowNull: true,
|
||||
},
|
||||
REFRESH_TOKEN: {
|
||||
type: DataTypes.STRING,
|
||||
type: DataTypes.STRING(256),
|
||||
allowNull: true,
|
||||
},
|
||||
TIME_USERS: {
|
||||
type: DataTypes.DATE,
|
||||
|
|
|
|||
863
package-lock.json
generated
863
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
|
|
@ -6,7 +6,13 @@
|
|||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"api-start": "nodemon index.js"
|
||||
"api-start": "nodemon index.js",
|
||||
"db:migrate": "npx sequelize-cli db:migrate --migrations-path database/migrations --config config/config.js",
|
||||
"db:seed": "npx sequelize-cli db:seed:all --seeders-path database/seeders --config config/config.js",
|
||||
"db:migrate:undo": "npx sequelize-cli db:migrate:undo --migrations-path database/migrations --config config/config.js",
|
||||
"db:seed:undo": "npx sequelize-cli db:seed:undo --seeders-path database/seeders --config config/config.js",
|
||||
"migrate:generate": "node generateMigration.js",
|
||||
"seed:generate": "node generateSeed.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
|
|
@ -23,6 +29,8 @@
|
|||
"mysql2": "^3.11.0",
|
||||
"nodemailer": "^6.9.14",
|
||||
"nodemon": "^3.1.4",
|
||||
"sequelize": "^6.37.3"
|
||||
"sequelize": "^6.37.3",
|
||||
"sequelize-cli": "^6.6.2",
|
||||
"uuid": "^10.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
30
renameFiles.js
Normal file
30
renameFiles.js
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
function renameFilesInDirectory(directory) {
|
||||
fs.readdir(directory, (err, files) => {
|
||||
if (err) {
|
||||
console.error(`Error reading directory ${directory}:`, err);
|
||||
return;
|
||||
}
|
||||
|
||||
files.forEach((file) => {
|
||||
const ext = path.extname(file);
|
||||
if (ext === ".js") {
|
||||
const oldPath = path.join(directory, file);
|
||||
const newPath = path.join(directory, file.replace(".js", ".cjs"));
|
||||
|
||||
fs.rename(oldPath, newPath, (renameErr) => {
|
||||
if (renameErr) {
|
||||
console.error(`Error renaming file ${file}:`, renameErr);
|
||||
} else {
|
||||
console.log(`Renamed: ${file} -> ${path.basename(newPath)}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
renameFilesInDirectory("./database/migrations");
|
||||
renameFilesInDirectory("./database/seeders");
|
||||
|
|
@ -1,11 +1,13 @@
|
|||
import express from "express";
|
||||
import { getClasses, getClassById, getStudentsByClassId, getStudentsWithNoClass, createClass, updateClassById, deleteClassById, updateStudentClassByName } from "../../controllers/monitoringControllers/class.js";
|
||||
import { getClasses, getClassById, getStudentsByClassId, getClassForAdmin, getStudentsWithNoClass, createClass, updateClassById, deleteClassById, updateStudentClassByName } from "../../controllers/monitoringControllers/class.js";
|
||||
import { verifyLoginUser, adminOrTeacherOnly } from "../../middlewares/User/authUser.js";
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.get("/classes", verifyLoginUser, getClasses);
|
||||
|
||||
router.get("/class/admin", verifyLoginUser, getClassForAdmin);
|
||||
|
||||
router.get("/class/:id", verifyLoginUser, getClassById);
|
||||
|
||||
router.get("/class/student/unassigned", verifyLoginUser, adminOrTeacherOnly, getStudentsWithNoClass);
|
||||
|
|
@ -14,7 +16,7 @@ router.get("/class/student/:classId", verifyLoginUser, adminOrTeacherOnly, getSt
|
|||
|
||||
router.post("/class", verifyLoginUser, createClass);
|
||||
|
||||
router.put("/class/update/:classId", verifyLoginUser, updateClassById);
|
||||
router.put("/class/update/:id", verifyLoginUser, updateClassById);
|
||||
|
||||
router.delete("/class/delete/:id", verifyLoginUser, deleteClassById);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user