fix: eslint warnings (#252)
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
const databasePath = path.resolve(__dirname, '../database/database.sqlite');
|
const databasePath = path.resolve(__dirname, '../database/database.sqlite');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
const { roles, defaultDangerKey } = require('../routes/users/authSettings');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const { roles, defaultDangerKey } = require('../routes/users/authSettings');
|
||||||
const defineUser = require('../models/users');
|
const defineUser = require('../models/users');
|
||||||
|
|
||||||
function authMiddleware(sequelize) {
|
function authMiddleware(sequelize) {
|
||||||
@@ -23,6 +23,7 @@ function authMiddleware(sequelize) {
|
|||||||
req.userId = decoded.userId;
|
req.userId = decoded.userId;
|
||||||
next();
|
next();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.error('Token verification failed:', error);
|
||||||
res.status(401).json({ error: 'Invalid token' });
|
res.status(401).json({ error: 'Invalid token' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
const { memberRoles } = require('../routes/users/authSettings');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const { memberRoles } = require('../routes/users/authSettings');
|
||||||
const defineMember = require('../models/members');
|
const defineMember = require('../models/members');
|
||||||
const defineProject = require('../models/projects');
|
const defineProject = require('../models/projects');
|
||||||
const defineFolder = require('../models/folders');
|
const defineFolder = require('../models/folders');
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
down: async (queryInterface, Sequelize) => {
|
down: async (queryInterface) => {
|
||||||
await queryInterface.dropTable('users');
|
await queryInterface.dropTable('users');
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
down: async (queryInterface, Sequelize) => {
|
down: async (queryInterface) => {
|
||||||
await queryInterface.dropTable('projects');
|
await queryInterface.dropTable('projects');
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
async down(queryInterface, Sequelize) {
|
async down(queryInterface) {
|
||||||
await queryInterface.dropTable('folders');
|
await queryInterface.dropTable('folders');
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
async down(queryInterface, Sequelize) {
|
async down(queryInterface) {
|
||||||
await queryInterface.dropTable('runs');
|
await queryInterface.dropTable('runs');
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
async down(queryInterface, Sequelize) {
|
async down(queryInterface) {
|
||||||
await queryInterface.dropTable('cases');
|
await queryInterface.dropTable('cases');
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
down: async (queryInterface, Sequelize) => {
|
down: async (queryInterface) => {
|
||||||
await queryInterface.dropTable('steps');
|
await queryInterface.dropTable('steps');
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
down: async (queryInterface, Sequelize) => {
|
down: async (queryInterface) => {
|
||||||
await queryInterface.dropTable('caseSteps');
|
await queryInterface.dropTable('caseSteps');
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
async down(queryInterface, Sequelize) {
|
async down(queryInterface) {
|
||||||
await queryInterface.dropTable('attachments');
|
await queryInterface.dropTable('attachments');
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
down: async (queryInterface, Sequelize) => {
|
down: async (queryInterface) => {
|
||||||
await queryInterface.dropTable('caseAttachments');
|
await queryInterface.dropTable('caseAttachments');
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
down: async (queryInterface, Sequelize) => {
|
down: async (queryInterface) => {
|
||||||
await queryInterface.dropTable('runCases');
|
await queryInterface.dropTable('runCases');
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
down: async (queryInterface, Sequelize) => {
|
down: async (queryInterface) => {
|
||||||
await queryInterface.dropTable('members');
|
await queryInterface.dropTable('members');
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
/** @type {import('sequelize-cli').Migration} */
|
/** @type {import('sequelize-cli').Migration} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
async up(queryInterface, Sequelize) {
|
async up(queryInterface) {
|
||||||
/**
|
/**
|
||||||
* Add altering commands here.
|
* Add altering commands here.
|
||||||
*
|
*
|
||||||
@@ -15,7 +15,7 @@ module.exports = {
|
|||||||
await queryInterface.renameColumn('users', 'avatarPath', 'avatar_path');
|
await queryInterface.renameColumn('users', 'avatarPath', 'avatar_path');
|
||||||
},
|
},
|
||||||
|
|
||||||
async down(queryInterface, Sequelize) {
|
async down() {
|
||||||
/**
|
/**
|
||||||
* Add reverting commands here.
|
* Add reverting commands here.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const Sequelize = require('sequelize');
|
|
||||||
const process = require('process');
|
const process = require('process');
|
||||||
|
const Sequelize = require('sequelize');
|
||||||
const basename = path.basename(__filename);
|
const basename = path.basename(__filename);
|
||||||
const env = process.env.NODE_ENV || 'development';
|
const env = process.env.NODE_ENV || 'development';
|
||||||
const config = require(__dirname + '/../config/config.json')[env];
|
const config = require(__dirname + '/../config/config.json')[env];
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineCase = require('../../models/cases');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineCase = require('../../models/cases');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineCase = require('../../models/cases');
|
|
||||||
const defineStep = require('../../models/steps');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineCase = require('../../models/cases');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
const { verifyProjectDeveloperFromCaseId } = require('../../middleware/verifyEditable')(sequelize);
|
const { verifyProjectDeveloperFromCaseId } = require('../../middleware/verifyEditable')(sequelize);
|
||||||
const Case = defineCase(sequelize, DataTypes);
|
const Case = defineCase(sequelize, DataTypes);
|
||||||
const Step = defineStep(sequelize, DataTypes);
|
|
||||||
|
|
||||||
router.put('/:caseId', verifySignedIn, verifyProjectDeveloperFromCaseId, async (req, res) => {
|
router.put('/:caseId', verifySignedIn, verifyProjectDeveloperFromCaseId, async (req, res) => {
|
||||||
const caseId = req.params.caseId;
|
const caseId = req.params.caseId;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineCase = require('../../models/cases');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineCase = require('../../models/cases');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const Case = defineCase(sequelize, DataTypes);
|
const Case = defineCase(sequelize, DataTypes);
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
const { DataTypes } = require('sequelize');
|
||||||
const defineProject = require('../../models/projects');
|
const defineProject = require('../../models/projects');
|
||||||
const defineFolder = require('../../models/folders');
|
const defineFolder = require('../../models/folders');
|
||||||
const defineCase = require('../../models/cases');
|
const defineCase = require('../../models/cases');
|
||||||
const defineRunCase = require('../../models/runCases');
|
const defineRunCase = require('../../models/runCases');
|
||||||
const { DataTypes } = require('sequelize');
|
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const Project = defineProject(sequelize, DataTypes);
|
const Project = defineProject(sequelize, DataTypes);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineCase = require('../../models/cases');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineCase = require('../../models/cases');
|
||||||
|
|
||||||
const requiredFields = ['title', 'state', 'priority', 'type', 'automationStatus', 'template'];
|
const requiredFields = ['title', 'state', 'priority', 'type', 'automationStatus', 'template'];
|
||||||
|
|
||||||
@@ -50,6 +50,7 @@ module.exports = function (sequelize) {
|
|||||||
|
|
||||||
res.json(newCase);
|
res.json(newCase);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.error('Error creating new case:', error);
|
||||||
res.status(500).json({ error: 'Internal server error' });
|
res.status(500).json({ error: 'Internal server error' });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
const { DataTypes } = require('sequelize');
|
||||||
const defineCase = require('../../models/cases');
|
const defineCase = require('../../models/cases');
|
||||||
const defineStep = require('../../models/steps');
|
const defineStep = require('../../models/steps');
|
||||||
const defineAttachment = require('../../models/attachments');
|
const defineAttachment = require('../../models/attachments');
|
||||||
const { DataTypes } = require('sequelize');
|
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const Case = defineCase(sequelize, DataTypes);
|
const Case = defineCase(sequelize, DataTypes);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineFolder = require('../../models/folders');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineFolder = require('../../models/folders');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineFolder = require('../../models/folders');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineFolder = require('../../models/folders');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineFolder = require('../../models/folders');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineFolder = require('../../models/folders');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineFolder = require('../../models/folders');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineFolder = require('../../models/folders');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
@@ -25,6 +25,7 @@ module.exports = function (sequelize) {
|
|||||||
|
|
||||||
res.json(newFolder);
|
res.json(newFolder);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.error('Error creating new folder:', error);
|
||||||
res.status(500).json({ error: 'Internal server error' });
|
res.status(500).json({ error: 'Internal server error' });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
const { DataTypes } = require('sequelize');
|
||||||
const defineProject = require('../../models/projects');
|
const defineProject = require('../../models/projects');
|
||||||
const defineFolder = require('../../models/folders');
|
const defineFolder = require('../../models/folders');
|
||||||
const defineCase = require('../../models/cases');
|
const defineCase = require('../../models/cases');
|
||||||
const defineRun = require('../../models/runs');
|
const defineRun = require('../../models/runs');
|
||||||
const defineRunCase = require('../../models/runCases');
|
const defineRunCase = require('../../models/runCases');
|
||||||
const { DataTypes } = require('sequelize');
|
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
const { DataTypes } = require('sequelize');
|
||||||
const defineMember = require('../../models/members');
|
const defineMember = require('../../models/members');
|
||||||
const defineProject = require('../../models/projects');
|
const defineProject = require('../../models/projects');
|
||||||
const { DataTypes } = require('sequelize');
|
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineMember = require('../../models/members');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineMember = require('../../models/members');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineMember = require('../../models/members');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineMember = require('../../models/members');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
const { DataTypes } = require('sequelize');
|
||||||
const defineUser = require('../../models/users');
|
const defineUser = require('../../models/users');
|
||||||
const defineMember = require('../../models/members');
|
const defineMember = require('../../models/members');
|
||||||
const { DataTypes } = require('sequelize');
|
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineMember = require('../../models/members');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineMember = require('../../models/members');
|
||||||
const { memberRoles } = require('../../routes/users/authSettings');
|
const { memberRoles } = require('../../routes/users/authSettings');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
const { DataTypes } = require('sequelize');
|
||||||
const defineProject = require('../../models/projects');
|
const defineProject = require('../../models/projects');
|
||||||
const defineFolder = require('../../models/folders');
|
const defineFolder = require('../../models/folders');
|
||||||
const defineRun = require('../../models/runs');
|
const defineRun = require('../../models/runs');
|
||||||
const { DataTypes } = require('sequelize');
|
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineProject = require('../../models/projects');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineProject = require('../../models/projects');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineProject = require('../../models/projects');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineProject = require('../../models/projects');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
const { DataTypes } = require('sequelize');
|
||||||
const defineProject = require('../../models/projects');
|
const defineProject = require('../../models/projects');
|
||||||
const defineFolder = require('../../models/folders');
|
const defineFolder = require('../../models/folders');
|
||||||
const { DataTypes } = require('sequelize');
|
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineRunCase = require('../../models/runCases');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineRunCase = require('../../models/runCases');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineRunCase = require('../../models/runCases');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineRunCase = require('../../models/runCases');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineRun = require('../../models/runs');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineRun = require('../../models/runs');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineRun = require('../../models/runs');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineRun = require('../../models/runs');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const Run = defineRun(sequelize, DataTypes);
|
const Run = defineRun(sequelize, DataTypes);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineRun = require('../../models/runs');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineRun = require('../../models/runs');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineRun = require('../../models/runs');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineRun = require('../../models/runs');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
@@ -26,6 +26,7 @@ module.exports = function (sequelize) {
|
|||||||
|
|
||||||
res.json(newRun);
|
res.json(newRun);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.error('Error creating new run:', error);
|
||||||
res.status(500).json({ error: 'Internal server error' });
|
res.status(500).json({ error: 'Internal server error' });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
const { DataTypes, literal } = require('sequelize');
|
||||||
const defineRun = require('../../models/runs');
|
const defineRun = require('../../models/runs');
|
||||||
const defineRunCase = require('../../models/runCases');
|
const defineRunCase = require('../../models/runCases');
|
||||||
const { DataTypes, literal } = require('sequelize');
|
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
const { DataTypes } = require('sequelize');
|
||||||
const defineStep = require('../../models/steps');
|
const defineStep = require('../../models/steps');
|
||||||
const defineCaseStep = require('../../models/caseSteps');
|
const defineCaseStep = require('../../models/caseSteps');
|
||||||
const { DataTypes } = require('sequelize');
|
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const Step = defineStep(sequelize, DataTypes);
|
const Step = defineStep(sequelize, DataTypes);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineUser = require('../../models/users');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineUser = require('../../models/users');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineUser = require('../../models/users');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
const defineUser = require('../../models/users');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn, verifyAdmin } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn, verifyAdmin } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
const { DataTypes, Op } = require('sequelize');
|
||||||
const defineUser = require('../../models/users');
|
const defineUser = require('../../models/users');
|
||||||
const defineMember = require('../../models/members');
|
const defineMember = require('../../models/members');
|
||||||
const { DataTypes, Op } = require('sequelize');
|
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineUser = require('../../models/users');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
const bcrypt = require('bcrypt');
|
const bcrypt = require('bcrypt');
|
||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
|
const defineUser = require('../../models/users');
|
||||||
const { defaultDangerKey } = require('./authSettings');
|
const { defaultDangerKey } = require('./authSettings');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineUser = require('../../models/users');
|
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
const { roles, defaultDangerKey } = require('./authSettings');
|
|
||||||
const bcrypt = require('bcrypt');
|
const bcrypt = require('bcrypt');
|
||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
|
const defineUser = require('../../models/users');
|
||||||
|
const { roles, defaultDangerKey } = require('./authSettings');
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const User = defineUser(sequelize, DataTypes);
|
const User = defineUser(sequelize, DataTypes);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { DataTypes } from 'sequelize';
|
import { DataTypes } from 'sequelize';
|
||||||
import defineUser from '../../models/users.js';
|
import defineUser from '../../models/users.js';
|
||||||
import { roles } from './authSettings.js';
|
|
||||||
import authMiddleware from '../../middleware/auth.js';
|
import authMiddleware from '../../middleware/auth.js';
|
||||||
|
import { roles } from './authSettings.js';
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
export default function (sequelize) {
|
export default function (sequelize) {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||||
import request from 'supertest';
|
import request from 'supertest';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import updateRoute from './update';
|
|
||||||
import { Sequelize } from 'sequelize';
|
import { Sequelize } from 'sequelize';
|
||||||
|
import updateRoute from './update';
|
||||||
import { roles } from './authSettings';
|
import { roles } from './authSettings';
|
||||||
|
|
||||||
const adminRoleIndex = roles.findIndex((entry) => entry.uid === 'administrator');
|
const adminRoleIndex = roles.findIndex((entry) => entry.uid === 'administrator');
|
||||||
@@ -28,7 +28,7 @@ const mockUser = {
|
|||||||
update: vi.fn(),
|
update: vi.fn(),
|
||||||
};
|
};
|
||||||
vi.mock('../../models/users', () => ({
|
vi.mock('../../models/users', () => ({
|
||||||
default: (sequelize, DataTypes) => mockUser,
|
default: () => mockUser,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// test
|
// test
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ const fs = require('fs');
|
|||||||
const bcrypt = require('bcrypt');
|
const bcrypt = require('bcrypt');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
up: async (queryInterface, Sequelize) => {
|
up: async (queryInterface) => {
|
||||||
const hashedPassword = await bcrypt.hash('password', 10);
|
const hashedPassword = await bcrypt.hash('password', 10);
|
||||||
|
|
||||||
// Add projects table records
|
// Add projects table records
|
||||||
@@ -696,7 +696,7 @@ module.exports = {
|
|||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
|
|
||||||
down: async (queryInterface, Sequelize) => {
|
down: async () => {
|
||||||
// do nothingg
|
// do nothing
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
// Use express from backend node_modules
|
// Use express from backend node_modules
|
||||||
const express = require('./backend/node_modules/express');
|
|
||||||
const { createServer: createHttpServer } = require('http');
|
const { createServer: createHttpServer } = require('http');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const { execSync } = require('child_process');
|
const { execSync } = require('child_process');
|
||||||
|
const express = require('./backend/node_modules/express');
|
||||||
|
|
||||||
async function runMigrations() {
|
async function runMigrations() {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import React from 'react';
|
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -63,7 +62,7 @@ export default function ProjectDialog({ isOpen, editingProject, onCancel, onSubm
|
|||||||
|
|
||||||
setIsProjectPublic(true);
|
setIsProjectPublic(true);
|
||||||
}
|
}
|
||||||
}, [editingProject]);
|
}, [editingProject, projectDetail, projectName]);
|
||||||
|
|
||||||
const clear = () => {
|
const clear = () => {
|
||||||
setProjectName({
|
setProjectName({
|
||||||
|
|||||||
@@ -19,7 +19,11 @@ export const ThemeSwitch: FC<ThemeSwitchProps> = ({ className, classNames }) =>
|
|||||||
const isSSR = useIsSSR();
|
const isSSR = useIsSSR();
|
||||||
|
|
||||||
const onChange = () => {
|
const onChange = () => {
|
||||||
theme === 'light' ? setTheme('dark') : setTheme('light');
|
if (theme === 'light') {
|
||||||
|
setTheme('dark');
|
||||||
|
} else {
|
||||||
|
setTheme('light');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const { Component, slots, isSelected, getBaseProps, getInputProps, getWrapperProps } = useSwitch({
|
const { Component, slots, isSelected, getBaseProps, getInputProps, getWrapperProps } = useSwitch({
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default function PublicityChip({ context }: Props) {
|
|||||||
return context.isSignedIn() ? (
|
return context.isSignedIn() ? (
|
||||||
<Avatar
|
<Avatar
|
||||||
size={16}
|
size={16}
|
||||||
name={context.token!.user!.username}
|
name={context.token?.user?.username}
|
||||||
variant="beam"
|
variant="beam"
|
||||||
colors={['#0A0310', '#49007E', '#FF005B', '#FF7D10', '#FFB238']}
|
colors={['#0A0310', '#49007E', '#FF005B', '#FF7D10', '#FFB238']}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ export default function DropdownAccount({ messages, locale, onItemPress }: Props
|
|||||||
startContent={<UserAvatar context={context} />}
|
startContent={<UserAvatar context={context} />}
|
||||||
endContent={<ChevronDown size={16} />}
|
endContent={<ChevronDown size={16} />}
|
||||||
>
|
>
|
||||||
{context.isSignedIn() ? context.token!.user!.username : messages.signIn}
|
{context.isSignedIn() ? context.token?.user?.username : messages.signIn}
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownTrigger>
|
</DropdownTrigger>
|
||||||
{context.isSignedIn() ? (
|
{context.isSignedIn() ? (
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import { useState, useContext } from 'react';
|
import { useState, useContext } from 'react';
|
||||||
import { TokenContext } from '@/utils/TokenProvider';
|
|
||||||
import { Link, useRouter } from '@/src/i18n/routing';
|
|
||||||
import { usePathname } from 'next/navigation';
|
import { usePathname } from 'next/navigation';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import {
|
import {
|
||||||
@@ -12,16 +10,17 @@ import {
|
|||||||
NavbarBrand,
|
NavbarBrand,
|
||||||
NavbarItem,
|
NavbarItem,
|
||||||
Link as NextUiLink,
|
Link as NextUiLink,
|
||||||
Chip,
|
|
||||||
ListboxItem,
|
ListboxItem,
|
||||||
Listbox,
|
Listbox,
|
||||||
} from '@heroui/react';
|
} from '@heroui/react';
|
||||||
import { ArrowRightFromLine, ArrowRightToLine, File, Globe, MoveUpRight, PenTool } from 'lucide-react';
|
import { ArrowRightFromLine, ArrowRightToLine, File, Globe, MoveUpRight, PenTool } from 'lucide-react';
|
||||||
|
import DropdownAccount from './DropdownAccount';
|
||||||
|
import DropdownLanguage from './DropdownLanguage';
|
||||||
import { ThemeSwitch } from '@/components/ThemeSwitch';
|
import { ThemeSwitch } from '@/components/ThemeSwitch';
|
||||||
import { GithubIcon } from '@/components/icons';
|
import { GithubIcon } from '@/components/icons';
|
||||||
import { locales } from '@/config/selection';
|
import { locales } from '@/config/selection';
|
||||||
import DropdownAccount from './DropdownAccount';
|
import { Link, useRouter } from '@/src/i18n/routing';
|
||||||
import DropdownLanguage from './DropdownLanguage';
|
import { TokenContext } from '@/utils/TokenProvider';
|
||||||
import UserAvatar from '@/components/UserAvatar';
|
import UserAvatar from '@/components/UserAvatar';
|
||||||
import { LocaleCodeType } from '@/types/locale';
|
import { LocaleCodeType } from '@/types/locale';
|
||||||
import Config from '@/config/config';
|
import Config from '@/config/config';
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import { useState, useEffect, useContext } from 'react';
|
import { useState, useEffect, useContext } from 'react';
|
||||||
import { Link, NextUiLinkClasses } from '@/src/i18n/routing';
|
|
||||||
import { Button, Card, CardHeader, CardFooter } from '@heroui/react';
|
import { Button, Card, CardHeader, CardFooter } from '@heroui/react';
|
||||||
import { TokenContext } from '@/utils/TokenProvider';
|
|
||||||
import Avatar from 'boring-avatars';
|
import Avatar from 'boring-avatars';
|
||||||
|
import { ArrowRight } from 'lucide-react';
|
||||||
|
import { Link, NextUiLinkClasses } from '@/src/i18n/routing';
|
||||||
|
import { TokenContext } from '@/utils/TokenProvider';
|
||||||
import { fetchMyProjects } from '@/utils/projectsControl';
|
import { fetchMyProjects } from '@/utils/projectsControl';
|
||||||
import { ProjectType } from '@/types/project';
|
import { ProjectType } from '@/types/project';
|
||||||
import PublicityChip from '@/components/PublicityChip';
|
import PublicityChip from '@/components/PublicityChip';
|
||||||
import { LocaleCodeType } from '@/types/locale';
|
import { LocaleCodeType } from '@/types/locale';
|
||||||
import { ArrowRight } from 'lucide-react';
|
import { logError } from '@/utils/errorHandler';
|
||||||
|
|
||||||
type AccountPageMessages = {
|
type AccountPageMessages = {
|
||||||
yourProjects: string;
|
yourProjects: string;
|
||||||
@@ -36,8 +37,8 @@ export default function AccountPage({ messages, locale }: Props) {
|
|||||||
try {
|
try {
|
||||||
const data = await fetchMyProjects(context.token.access_token);
|
const data = await fetchMyProjects(context.token.access_token);
|
||||||
setMyProjects(data);
|
setMyProjects(data);
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error in effect:', error.message);
|
logError('Error fetching data:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,13 +54,13 @@ export default function AccountPage({ messages, locale }: Props) {
|
|||||||
<CardHeader className="flex gap-6">
|
<CardHeader className="flex gap-6">
|
||||||
<Avatar
|
<Avatar
|
||||||
size={48}
|
size={48}
|
||||||
name={context.token!.user!.username}
|
name={context.token?.user?.username}
|
||||||
variant="beam"
|
variant="beam"
|
||||||
colors={['#0A0310', '#49007E', '#FF005B', '#FF7D10', '#FFB238']}
|
colors={['#0A0310', '#49007E', '#FF005B', '#FF7D10', '#FFB238']}
|
||||||
/>
|
/>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<p className="text-xl font-bold">{context.token!.user!.username}</p>
|
<p className="text-xl font-bold">{context.token?.user?.username}</p>
|
||||||
<p className="text-lg text-default-500">{context.token!.user!.email}</p>
|
<p className="text-lg text-default-500">{context.token?.user?.email}</p>
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { UserType } from '@/types/user';
|
import { UserType } from '@/types/user';
|
||||||
import Config from '@/config/config';
|
import Config from '@/config/config';
|
||||||
import { roles } from '@/config/selection';
|
import { roles } from '@/config/selection';
|
||||||
|
import { logError } from '@/utils/errorHandler';
|
||||||
const apiServer = Config.apiServer;
|
const apiServer = Config.apiServer;
|
||||||
|
|
||||||
async function signUp(newUser: UserType) {
|
async function signUp(newUser: UserType) {
|
||||||
@@ -21,8 +22,8 @@ async function signUp(newUser: UserType) {
|
|||||||
}
|
}
|
||||||
const token = await response.json();
|
const token = await response.json();
|
||||||
return token;
|
return token;
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error sign up:', error);
|
logError('Error sign up:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,8 +46,8 @@ async function signIn(signInUser: UserType) {
|
|||||||
}
|
}
|
||||||
const token = await response.json();
|
const token = await response.json();
|
||||||
return token;
|
return token;
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error sign in:', error);
|
logError('Error sign in:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import React from 'react';
|
|
||||||
import { useState, useContext } from 'react';
|
import { useState, useContext } from 'react';
|
||||||
import { Input, Button, Card, CardHeader, CardBody } from '@heroui/react';
|
import { Input, Button, Card, CardHeader, CardBody } from '@heroui/react';
|
||||||
import { Link } from '@/src/i18n/routing';
|
|
||||||
import { ChevronRight, Eye, EyeOff } from 'lucide-react';
|
import { ChevronRight, Eye, EyeOff } from 'lucide-react';
|
||||||
import { UserType, AuthMessages } from '@/types/user';
|
|
||||||
import { roles } from '@/config/selection';
|
|
||||||
import { signUp, signIn, signInAsGuest } from './authControl';
|
import { signUp, signIn, signInAsGuest } from './authControl';
|
||||||
import { isValidEmail, isValidPassword } from './validate';
|
import { isValidEmail, isValidPassword } from './validate';
|
||||||
|
import { Link } from '@/src/i18n/routing';
|
||||||
|
import { UserType, AuthMessages } from '@/types/user';
|
||||||
|
import { roles } from '@/config/selection';
|
||||||
import { TokenContext } from '@/utils/TokenProvider';
|
import { TokenContext } from '@/utils/TokenProvider';
|
||||||
import { useRouter } from '@/src/i18n/routing';
|
import { useRouter } from '@/src/i18n/routing';
|
||||||
import Config from '@/config/config';
|
import Config from '@/config/config';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { LocaleCodeType } from '@/types/locale';
|
|
||||||
import { getTranslations } from 'next-intl/server';
|
import { getTranslations } from 'next-intl/server';
|
||||||
|
import { LocaleCodeType } from '@/types/locale';
|
||||||
|
|
||||||
export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) {
|
export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) {
|
||||||
const t = await getTranslations({ locale, namespace: 'Auth' });
|
const t = await getTranslations({ locale, namespace: 'Auth' });
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { PageType } from '@/types/base';
|
|
||||||
import AuthPage from '../authPage';
|
|
||||||
import { getTranslations } from 'next-intl/server';
|
import { getTranslations } from 'next-intl/server';
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
|
import AuthPage from '../authPage';
|
||||||
|
import { PageType } from '@/types/base';
|
||||||
import { LocaleCodeType } from '@/types/locale';
|
import { LocaleCodeType } from '@/types/locale';
|
||||||
|
|
||||||
export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) {
|
export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { PageType } from '@/types/base';
|
|
||||||
import AuthPage from '../authPage';
|
|
||||||
import { getTranslations } from 'next-intl/server';
|
import { getTranslations } from 'next-intl/server';
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
|
import AuthPage from '../authPage';
|
||||||
|
import { PageType } from '@/types/base';
|
||||||
import { LocaleCodeType } from '@/types/locale';
|
import { LocaleCodeType } from '@/types/locale';
|
||||||
|
|
||||||
export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) {
|
export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) {
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import React from 'react';
|
|
||||||
import { useState, useEffect, useContext } from 'react';
|
import { useState, useEffect, useContext } from 'react';
|
||||||
|
import { Button, addToast } from '@heroui/react';
|
||||||
|
import UsersTable from './UsersTable';
|
||||||
import { UserType, AdminMessages } from '@/types/user';
|
import { UserType, AdminMessages } from '@/types/user';
|
||||||
import { TokenContext } from '@/utils/TokenProvider';
|
import { TokenContext } from '@/utils/TokenProvider';
|
||||||
import { useRouter } from '@/src/i18n/routing';
|
import { useRouter } from '@/src/i18n/routing';
|
||||||
import UsersTable from './UsersTable';
|
|
||||||
import Config from '@/config/config';
|
import Config from '@/config/config';
|
||||||
import { LocaleCodeType } from '@/types/locale';
|
import { LocaleCodeType } from '@/types/locale';
|
||||||
import { updateUserRole } from '@/utils/usersControl';
|
import { updateUserRole } from '@/utils/usersControl';
|
||||||
import { Button, addToast } from '@heroui/react';
|
|
||||||
import { roles } from '@/config/selection';
|
import { roles } from '@/config/selection';
|
||||||
import DeleteConfirmDialog from '@/components/DeleteConfirmDialog';
|
import DeleteConfirmDialog from '@/components/DeleteConfirmDialog';
|
||||||
|
import { logError } from '@/utils/errorHandler';
|
||||||
const apiServer = Config.apiServer;
|
const apiServer = Config.apiServer;
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -36,8 +36,8 @@ async function fetchUsers(jwt: string) {
|
|||||||
}
|
}
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return data;
|
return data;
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error fetching data:', error.message);
|
logError('Error fetching data:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,8 +66,8 @@ export default function AdminPage({ messages, locale }: Props) {
|
|||||||
if (tokenContext.token.user) {
|
if (tokenContext.token.user) {
|
||||||
setMyself(tokenContext.token.user);
|
setMyself(tokenContext.token.user);
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error in effect:', error.message);
|
logError('Error fetching users:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ import {
|
|||||||
DropdownItem,
|
DropdownItem,
|
||||||
} from '@heroui/react';
|
} from '@heroui/react';
|
||||||
import { ChevronDown } from 'lucide-react';
|
import { ChevronDown } from 'lucide-react';
|
||||||
|
import Avatar from 'boring-avatars';
|
||||||
import { UserType, AdminMessages } from '@/types/user';
|
import { UserType, AdminMessages } from '@/types/user';
|
||||||
import { roles } from '@/config/selection';
|
import { roles } from '@/config/selection';
|
||||||
import Avatar from 'boring-avatars';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
users: UserType[];
|
users: UserType[];
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Table, TableBody, TableRow, TableHeader, TableCell, Chip, TableColumn }
|
|||||||
import { LocaleCodeType } from '@/types/locale';
|
import { LocaleCodeType } from '@/types/locale';
|
||||||
import { HealthMessages } from '@/types/health';
|
import { HealthMessages } from '@/types/health';
|
||||||
import Config from '@/config/config';
|
import Config from '@/config/config';
|
||||||
|
import { logError } from '@/utils/errorHandler';
|
||||||
const apiServer = Config.apiServer;
|
const apiServer = Config.apiServer;
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -21,8 +22,8 @@ async function fetchHealth() {
|
|||||||
}
|
}
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return data;
|
return data;
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.log('Error fetching health data:', error);
|
logError('Error fetching health data:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,8 +39,8 @@ export default function HealthPage({ messages, locale }: Props) {
|
|||||||
const data = await fetchHealth();
|
const data = await fetchHealth();
|
||||||
setStatus(data.status);
|
setStatus(data.status);
|
||||||
setIsFetching(false);
|
setIsFetching(false);
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error in effect:', error.message);
|
logError('Error in effect:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import '@/styles/globals.css';
|
import '@/styles/globals.css';
|
||||||
import { fontSans } from '@/config/fonts';
|
|
||||||
import { Providers } from './providers';
|
|
||||||
import Header from './Header';
|
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { getTranslations } from 'next-intl/server';
|
import { getTranslations } from 'next-intl/server';
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
import { LocaleCodeType } from '@/types/locale';
|
|
||||||
import { headers } from 'next/headers';
|
import { headers } from 'next/headers';
|
||||||
|
import Header from './Header';
|
||||||
|
import { Providers } from './providers';
|
||||||
|
import { LocaleCodeType } from '@/types/locale';
|
||||||
|
import { fontSans } from '@/config/fonts';
|
||||||
|
|
||||||
export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) {
|
export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) {
|
||||||
const headersList = headers();
|
const headersList = headers();
|
||||||
|
|||||||
@@ -2,12 +2,13 @@
|
|||||||
import { useEffect, useState, useContext } from 'react';
|
import { useEffect, useState, useContext } from 'react';
|
||||||
import { Button } from '@heroui/react';
|
import { Button } from '@heroui/react';
|
||||||
import { Plus } from 'lucide-react';
|
import { Plus } from 'lucide-react';
|
||||||
|
import ProjectsTable from './ProjectsTable';
|
||||||
import { TokenContext } from '@/utils/TokenProvider';
|
import { TokenContext } from '@/utils/TokenProvider';
|
||||||
import { ProjectDialogMessages, ProjectType, ProjectsMessages } from '@/types/project';
|
import { ProjectDialogMessages, ProjectType, ProjectsMessages } from '@/types/project';
|
||||||
import ProjectsTable from './ProjectsTable';
|
|
||||||
import ProjectDialog from '@/components/ProjectDialog';
|
import ProjectDialog from '@/components/ProjectDialog';
|
||||||
import { fetchProjects, createProject } from '@/utils/projectsControl';
|
import { fetchProjects, createProject } from '@/utils/projectsControl';
|
||||||
import { LocaleCodeType } from '@/types/locale';
|
import { LocaleCodeType } from '@/types/locale';
|
||||||
|
import { logError } from '@/utils/errorHandler';
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
messages: ProjectsMessages;
|
messages: ProjectsMessages;
|
||||||
@@ -27,8 +28,8 @@ export default function ProjectsPage({ messages, projectDialogMessages, locale }
|
|||||||
try {
|
try {
|
||||||
const data = await fetchProjects(context.token.access_token);
|
const data = await fetchProjects(context.token.access_token);
|
||||||
setProjects(data);
|
setProjects(data);
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error in effect:', error.message);
|
logError('Error fetching data:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { useState, useMemo, useCallback, ReactNode } from 'react';
|
import { useState, useMemo, useCallback, ReactNode } from 'react';
|
||||||
import { Table, TableHeader, TableColumn, TableBody, TableRow, TableCell, SortDescriptor } from '@heroui/react';
|
import { Table, TableHeader, TableColumn, TableBody, TableRow, TableCell, SortDescriptor } from '@heroui/react';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
import { Link, NextUiLinkClasses } from '@/src/i18n/routing';
|
import { Link, NextUiLinkClasses } from '@/src/i18n/routing';
|
||||||
import { ProjectType, ProjectsMessages } from '@/types/project';
|
import { ProjectType, ProjectsMessages } from '@/types/project';
|
||||||
import dayjs from 'dayjs';
|
|
||||||
import PublicityChip from '@/components/PublicityChip';
|
import PublicityChip from '@/components/PublicityChip';
|
||||||
import { LocaleCodeType } from '@/types/locale';
|
import { LocaleCodeType } from '@/types/locale';
|
||||||
|
|
||||||
@@ -39,7 +39,8 @@ export default function ProjectsTable({ projects, messages, locale }: Props) {
|
|||||||
return text.length > maxLength ? text.slice(0, maxLength) + '...' : text;
|
return text.length > maxLength ? text.slice(0, maxLength) + '...' : text;
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderCell = useCallback((project: ProjectType, columnKey: string): ReactNode => {
|
const renderCell = useCallback(
|
||||||
|
(project: ProjectType, columnKey: string): ReactNode => {
|
||||||
const cellValue = project[columnKey as keyof ProjectType];
|
const cellValue = project[columnKey as keyof ProjectType];
|
||||||
|
|
||||||
switch (columnKey) {
|
switch (columnKey) {
|
||||||
@@ -47,9 +48,13 @@ export default function ProjectsTable({ projects, messages, locale }: Props) {
|
|||||||
return <span>{cellValue as number}</span>;
|
return <span>{cellValue as number}</span>;
|
||||||
case 'isPublic':
|
case 'isPublic':
|
||||||
return (
|
return (
|
||||||
<PublicityChip isPublic={cellValue as boolean} publicText={messages.public} privateText={messages.private} />
|
<PublicityChip
|
||||||
|
isPublic={cellValue as boolean}
|
||||||
|
publicText={messages.public}
|
||||||
|
privateText={messages.private}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
case 'name':
|
case 'name': {
|
||||||
const maxLength = 30;
|
const maxLength = 30;
|
||||||
const truncatedDetail = truncateText(project.detail, maxLength);
|
const truncatedDetail = truncateText(project.detail, maxLength);
|
||||||
return (
|
return (
|
||||||
@@ -62,12 +67,15 @@ export default function ProjectsTable({ projects, messages, locale }: Props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
case 'updatedAt':
|
case 'updatedAt':
|
||||||
return <span>{dayjs(cellValue as number).format('YYYY/MM/DD HH:mm')}</span>;
|
return <span>{dayjs(cellValue as number).format('YYYY/MM/DD HH:mm')}</span>;
|
||||||
default:
|
default:
|
||||||
return cellValue as string;
|
return cellValue as string;
|
||||||
}
|
}
|
||||||
}, []);
|
},
|
||||||
|
[locale, messages.private, messages.public]
|
||||||
|
);
|
||||||
|
|
||||||
const classNames = useMemo(
|
const classNames = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import React from 'react';
|
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { Button, Input, Textarea, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter } from '@heroui/react';
|
import { Button, Input, Textarea, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter } from '@heroui/react';
|
||||||
import { FolderType, FoldersMessages } from '@/types/folder';
|
import { FolderType, FoldersMessages } from '@/types/folder';
|
||||||
@@ -47,7 +46,7 @@ export default function FolderDialog({ isOpen, editingFolder, onCancel, onSubmit
|
|||||||
text: '',
|
text: '',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [editingFolder]);
|
}, [editingFolder, folderDetail, folderName]);
|
||||||
|
|
||||||
const clear = () => {
|
const clear = () => {
|
||||||
setFolderName({
|
setFolderName({
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import { FolderType, FoldersMessages } from '@/types/folder';
|
|
||||||
import { useState, useEffect, useContext } from 'react';
|
import { useState, useEffect, useContext } from 'react';
|
||||||
import { Button, Listbox, ListboxItem } from '@heroui/react';
|
import { Button, Listbox, ListboxItem } from '@heroui/react';
|
||||||
import { Folder, Plus } from 'lucide-react';
|
import { Folder, Plus } from 'lucide-react';
|
||||||
|
import FolderDialog from './FolderDialog';
|
||||||
|
import FolderEditMenu from './FolderEditMenu';
|
||||||
|
import { fetchFolders, createFolder, updateFolder, deleteFolder } from './foldersControl';
|
||||||
import { usePathname, useRouter } from '@/src/i18n/routing';
|
import { usePathname, useRouter } from '@/src/i18n/routing';
|
||||||
import { TokenContext } from '@/utils/TokenProvider';
|
import { TokenContext } from '@/utils/TokenProvider';
|
||||||
import useGetCurrentIds from '@/utils/useGetCurrentIds';
|
import useGetCurrentIds from '@/utils/useGetCurrentIds';
|
||||||
import FolderDialog from './FolderDialog';
|
|
||||||
import FolderEditMenu from './FolderEditMenu';
|
|
||||||
import DeleteConfirmDialog from '@/components/DeleteConfirmDialog';
|
import DeleteConfirmDialog from '@/components/DeleteConfirmDialog';
|
||||||
import { fetchFolders, createFolder, updateFolder, deleteFolder } from './foldersControl';
|
import { FolderType, FoldersMessages } from '@/types/folder';
|
||||||
|
import { logError } from '@/utils/errorHandler';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
@@ -49,13 +50,13 @@ export default function FoldersPane({ projectId, messages, locale }: Props) {
|
|||||||
const smallestFolderId = Math.min(...folders.map((folder) => folder.id));
|
const smallestFolderId = Math.min(...folders.map((folder) => folder.id));
|
||||||
router.push(`/projects/${projectId}/folders/${smallestFolderId}/cases`, { locale: locale });
|
router.push(`/projects/${projectId}/folders/${smallestFolderId}/cases`, { locale: locale });
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error in effect:', error.message);
|
logError('Error fetching folders:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchDataEffect();
|
fetchDataEffect();
|
||||||
}, [context, folderId]);
|
}, [context, folderId, locale, pathname, projectId, router]);
|
||||||
|
|
||||||
const openDialogForCreate = () => {
|
const openDialogForCreate = () => {
|
||||||
setIsFolderDialogOpen(true);
|
setIsFolderDialogOpen(true);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import React from 'react';
|
import { useState } from 'react';
|
||||||
import { useState, useEffect } from 'react';
|
|
||||||
import { Button, Input, Textarea, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter } from '@heroui/react';
|
import { Button, Input, Textarea, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter } from '@heroui/react';
|
||||||
import { CasesMessages } from '@/types/case';
|
import { CasesMessages } from '@/types/case';
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { CaseType, CasesMessages } from '@/types/case';
|
|||||||
import DeleteConfirmDialog from '@/components/DeleteConfirmDialog';
|
import DeleteConfirmDialog from '@/components/DeleteConfirmDialog';
|
||||||
import { PriorityMessages } from '@/types/priority';
|
import { PriorityMessages } from '@/types/priority';
|
||||||
import { LocaleCodeType } from '@/types/locale';
|
import { LocaleCodeType } from '@/types/locale';
|
||||||
|
import { logError } from '@/utils/errorHandler';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
@@ -30,8 +31,8 @@ export default function CasesPane({ projectId, folderId, messages, priorityMessa
|
|||||||
try {
|
try {
|
||||||
const data = await fetchCases(context.token.access_token, Number(folderId));
|
const data = await fetchCases(context.token.access_token, Number(folderId));
|
||||||
setCases(data);
|
setCases(data);
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error in effect:', error.message);
|
logError('Error fetching cases:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
SortDescriptor,
|
SortDescriptor,
|
||||||
ButtonGroup,
|
ButtonGroup,
|
||||||
} from '@heroui/react';
|
} from '@heroui/react';
|
||||||
import { Plus, MoreVertical, Trash, Download, FileDown, ChevronDown, FileJson, FileSpreadsheet } from 'lucide-react';
|
import { Plus, MoreVertical, Trash, FileDown, ChevronDown, FileJson, FileSpreadsheet } from 'lucide-react';
|
||||||
import { Link } from '@/src/i18n/routing';
|
import { Link } from '@/src/i18n/routing';
|
||||||
import { CaseType, CasesMessages } from '@/types/case';
|
import { CaseType, CasesMessages } from '@/types/case';
|
||||||
import { PriorityMessages } from '@/types/priority';
|
import { PriorityMessages } from '@/types/priority';
|
||||||
@@ -122,6 +122,7 @@ export default function TestCaseTable({
|
|||||||
default:
|
default:
|
||||||
return cellValue as string;
|
return cellValue as string;
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleDeleteCases = () => {
|
const handleDeleteCases = () => {
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import { useState, useEffect, useContext, ChangeEvent, DragEvent } from 'react';
|
import { useState, useEffect, useContext, ChangeEvent, DragEvent } from 'react';
|
||||||
import { Input, Textarea, Select, SelectItem, Button, Divider, Tooltip, addToast, Badge } from '@heroui/react';
|
import { Input, Textarea, Select, SelectItem, Button, Divider, Tooltip, addToast, Badge } from '@heroui/react';
|
||||||
import { useRouter } from '@/src/i18n/routing';
|
|
||||||
import { Save, Plus, ArrowLeft, Circle } from 'lucide-react';
|
import { Save, Plus, ArrowLeft, Circle } from 'lucide-react';
|
||||||
import { priorities, testTypes, templates } from '@/config/selection';
|
|
||||||
import CaseStepsEditor from './CaseStepsEditor';
|
import CaseStepsEditor from './CaseStepsEditor';
|
||||||
import CaseAttachmentsEditor from './CaseAttachmentsEditor';
|
import CaseAttachmentsEditor from './CaseAttachmentsEditor';
|
||||||
import { fetchCase, updateCase } from '@/utils/caseControl';
|
|
||||||
import { updateSteps } from './stepControl';
|
import { updateSteps } from './stepControl';
|
||||||
import { fetchCreateAttachments, fetchDownloadAttachment, fetchDeleteAttachment } from './attachmentControl';
|
import { fetchCreateAttachments, fetchDownloadAttachment, fetchDeleteAttachment } from './attachmentControl';
|
||||||
|
import { fetchCase, updateCase } from '@/utils/caseControl';
|
||||||
|
import { priorities, testTypes, templates } from '@/config/selection';
|
||||||
|
import { useRouter } from '@/src/i18n/routing';
|
||||||
import { TokenContext } from '@/utils/TokenProvider';
|
import { TokenContext } from '@/utils/TokenProvider';
|
||||||
import { useFormGuard } from '@/utils/formGuard';
|
import { useFormGuard } from '@/utils/formGuard';
|
||||||
import { CaseType, AttachmentType, CaseMessages, StepType } from '@/types/case';
|
import { CaseType, AttachmentType, CaseMessages, StepType } from '@/types/case';
|
||||||
import { PriorityMessages } from '@/types/priority';
|
import { PriorityMessages } from '@/types/priority';
|
||||||
import { TestTypeMessages } from '@/types/testType';
|
import { TestTypeMessages } from '@/types/testType';
|
||||||
|
import { logError } from '@/utils/errorHandler';
|
||||||
|
|
||||||
const defaultTestCase = {
|
const defaultTestCase = {
|
||||||
id: 0,
|
id: 0,
|
||||||
@@ -220,13 +221,13 @@ export default function CaseEditor({
|
|||||||
step.editState = 'notChanged';
|
step.editState = 'notChanged';
|
||||||
});
|
});
|
||||||
setTestCase(data);
|
setTestCase(data);
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error in effect:', error.message);
|
logError('Error fetching case data', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchDataEffect();
|
fetchDataEffect();
|
||||||
}, [tokenContext]);
|
}, [caseId, tokenContext]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Textarea, Button, Tooltip, Avatar } from '@heroui/react';
|
import { Textarea, Button, Tooltip, Avatar } from '@heroui/react';
|
||||||
import { CaseMessages, StepType } from '@/types/case';
|
|
||||||
import { Plus, Trash } from 'lucide-react';
|
import { Plus, Trash } from 'lucide-react';
|
||||||
|
import { CaseMessages, StepType } from '@/types/case';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isDisabled: boolean;
|
isDisabled: boolean;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import Config from '@/config/config';
|
import Config from '@/config/config';
|
||||||
|
import { logError } from '@/utils/errorHandler';
|
||||||
const apiServer = Config.apiServer;
|
const apiServer = Config.apiServer;
|
||||||
|
|
||||||
async function fetchDownloadAttachment(attachmentId: number, downloadFileName: string) {
|
async function fetchDownloadAttachment(attachmentId: number, downloadFileName: string) {
|
||||||
@@ -26,8 +27,8 @@ async function fetchDownloadAttachment(attachmentId: number, downloadFileName: s
|
|||||||
document.body.appendChild(link);
|
document.body.appendChild(link);
|
||||||
link.click();
|
link.click();
|
||||||
document.body.removeChild(link);
|
document.body.removeChild(link);
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error downloading file:', error);
|
logError('Error downloading attachment', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -51,8 +52,8 @@ async function fetchCreateAttachments(caseId: number, files: File[]) {
|
|||||||
|
|
||||||
const responseData = await response.json();
|
const responseData = await response.json();
|
||||||
return responseData;
|
return responseData;
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error uploading files:', error);
|
logError('Error uploading files', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,8 +72,8 @@ async function fetchDeleteAttachment(attachmentId: number) {
|
|||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error deleting file:', error);
|
logError('Error deleting file:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { PriorityMessages } from '@/types/priority';
|
|
||||||
import CaseEditor from './CaseEditor';
|
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
|
import CaseEditor from './CaseEditor';
|
||||||
|
import { PriorityMessages } from '@/types/priority';
|
||||||
import { TestTypeMessages } from '@/types/testType';
|
import { TestTypeMessages } from '@/types/testType';
|
||||||
|
|
||||||
export default function Page({
|
export default function Page({
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import Config from '@/config/config';
|
import Config from '@/config/config';
|
||||||
import { StepType } from '@/types/case';
|
import { StepType } from '@/types/case';
|
||||||
|
import { logError } from '@/utils/errorHandler';
|
||||||
const apiServer = Config.apiServer;
|
const apiServer = Config.apiServer;
|
||||||
|
|
||||||
async function updateSteps(jwt: string, caseId: number, steps: StepType[]) {
|
async function updateSteps(jwt: string, caseId: number, steps: StepType[]) {
|
||||||
@@ -20,8 +21,8 @@ async function updateSteps(jwt: string, caseId: number, steps: StepType[]) {
|
|||||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||||
}
|
}
|
||||||
return await response.json();
|
return await response.json();
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error deleting project:', error);
|
logError('Error updating steps', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import Config from '@/config/config';
|
import Config from '@/config/config';
|
||||||
|
import { logError } from '@/utils/errorHandler';
|
||||||
const apiServer = Config.apiServer;
|
const apiServer = Config.apiServer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,8 +22,8 @@ async function fetchFolders(jwt: string, projectId: number) {
|
|||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return data;
|
return data;
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error fetching data:', error.message);
|
logError('Error fetching data:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,8 +61,8 @@ async function createFolder(
|
|||||||
}
|
}
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return data;
|
return data;
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error creating new project:', error);
|
logError('Error creating new folder:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,8 +103,8 @@ async function updateFolder(
|
|||||||
}
|
}
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return data;
|
return data;
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error updating project:', error);
|
logError('Error updating folder:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,8 +128,8 @@ async function deleteFolder(jwt: string, folderId: number) {
|
|||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error deleting project:', error);
|
logError('Error deleting folder:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import FoldersPane from './FoldersPane';
|
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
|
import FoldersPane from './FoldersPane';
|
||||||
|
|
||||||
export default function FoldersLayout({
|
export default function FoldersLayout({
|
||||||
children,
|
children,
|
||||||
|
|||||||
@@ -1,22 +1,23 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import { useState, useEffect, useContext } from 'react';
|
import { useState, useEffect, useContext } from 'react';
|
||||||
import { title, subtitle } from '@/components/primitives';
|
|
||||||
import { Card, CardBody, Chip, Divider } from '@heroui/react';
|
import { Card, CardBody, Chip, Divider } from '@heroui/react';
|
||||||
import { Folder, Clipboard, FlaskConical } from 'lucide-react';
|
import { Folder, Clipboard, FlaskConical } from 'lucide-react';
|
||||||
import { ProgressSeriesType } from '@/types/run';
|
|
||||||
import { HomeMessages } from './page';
|
|
||||||
import { TokenContext } from '@/utils/TokenProvider';
|
|
||||||
import { aggregateBasicInfo, aggregateTestPriority, aggregateTestType, aggregateProgress } from './aggregate';
|
|
||||||
import Config from '@/config/config';
|
|
||||||
import { useTheme } from 'next-themes';
|
import { useTheme } from 'next-themes';
|
||||||
|
import { aggregateBasicInfo, aggregateTestPriority, aggregateTestType, aggregateProgress } from './aggregate';
|
||||||
|
import { HomeMessages } from './page';
|
||||||
import TestTypesChart from './TestTypesDonutChart';
|
import TestTypesChart from './TestTypesDonutChart';
|
||||||
import TestPriorityChart from './TestPriorityDonutChart';
|
import TestPriorityChart from './TestPriorityDonutChart';
|
||||||
import TestProgressBarChart from './TestProgressColumnChart';
|
import TestProgressBarChart from './TestProgressColumnChart';
|
||||||
|
import Config from '@/config/config';
|
||||||
|
import { TokenContext } from '@/utils/TokenProvider';
|
||||||
|
import { ProgressSeriesType } from '@/types/run';
|
||||||
|
import { title, subtitle } from '@/components/primitives';
|
||||||
import { TestRunCaseStatusMessages } from '@/types/status';
|
import { TestRunCaseStatusMessages } from '@/types/status';
|
||||||
import { TestTypeMessages } from '@/types/testType';
|
import { TestTypeMessages } from '@/types/testType';
|
||||||
import { PriorityMessages } from '@/types/priority';
|
import { PriorityMessages } from '@/types/priority';
|
||||||
import { ProjectType } from '@/types/project';
|
import { ProjectType } from '@/types/project';
|
||||||
import { CasePriorityCountType, CaseTypeCountType } from '@/types/chart';
|
import { CasePriorityCountType, CaseTypeCountType } from '@/types/chart';
|
||||||
|
import { logError } from '@/utils/errorHandler';
|
||||||
|
|
||||||
const apiServer = Config.apiServer;
|
const apiServer = Config.apiServer;
|
||||||
|
|
||||||
@@ -38,8 +39,8 @@ async function fetchProject(jwt: string, projectId: number) {
|
|||||||
}
|
}
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return data;
|
return data;
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error fetching data:', error.message);
|
logError('Error fetching data:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +60,7 @@ export function ProjectHome({
|
|||||||
priorityMessages,
|
priorityMessages,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const context = useContext(TokenContext);
|
const context = useContext(TokenContext);
|
||||||
const { theme, setTheme } = useTheme();
|
const { theme } = useTheme();
|
||||||
const [project, setProject] = useState<ProjectType>({
|
const [project, setProject] = useState<ProjectType>({
|
||||||
id: 0,
|
id: 0,
|
||||||
name: '',
|
name: '',
|
||||||
@@ -88,13 +89,13 @@ export function ProjectHome({
|
|||||||
try {
|
try {
|
||||||
const data = await fetchProject(context.token.access_token, Number(projectId));
|
const data = await fetchProject(context.token.access_token, Number(projectId));
|
||||||
setProject(data);
|
setProject(data);
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error in effect:', error.message);
|
logError('Error in effect:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchDataEffect();
|
fetchDataEffect();
|
||||||
}, [context]);
|
}, [context, projectId]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function aggregate() {
|
async function aggregate() {
|
||||||
@@ -118,7 +119,7 @@ export function ProjectHome({
|
|||||||
}
|
}
|
||||||
|
|
||||||
aggregate();
|
aggregate();
|
||||||
}, [project]);
|
}, [project, testRunCaseStatusMessages]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto max-w-5xl pt-6 px-6 flex-grow">
|
<div className="container mx-auto max-w-5xl pt-6 px-6 flex-grow">
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import { priorities } from '@/config/selection';
|
import { priorities } from '@/config/selection';
|
||||||
@@ -34,7 +33,7 @@ export default function TestPriorityDonutChart({ priorityCounts, priorityMessage
|
|||||||
const colors = priorities.map((entry) => entry.chartColor);
|
const colors = priorities.map((entry) => entry.chartColor);
|
||||||
const legend = {
|
const legend = {
|
||||||
labels: {
|
labels: {
|
||||||
colors: priorities.map((entry) => {
|
colors: priorities.map(() => {
|
||||||
if (theme === 'light') {
|
if (theme === 'light') {
|
||||||
return 'black';
|
return 'black';
|
||||||
} else {
|
} else {
|
||||||
@@ -52,7 +51,7 @@ export default function TestPriorityDonutChart({ priorityCounts, priorityMessage
|
|||||||
};
|
};
|
||||||
|
|
||||||
updateChartDate();
|
updateChartDate();
|
||||||
}, [priorityCounts, theme]);
|
}, [priorityCounts, priorityMessages, theme]);
|
||||||
|
|
||||||
return <Chart options={chartData.options} series={chartData.series} type="donut" width={'100%'} height={'100%'} />;
|
return <Chart options={chartData.options} series={chartData.series} type="donut" width={'100%'} height={'100%'} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import { ProgressSeriesType } from '@/types/run';
|
import { ProgressSeriesType } from '@/types/run';
|
||||||
@@ -24,7 +23,7 @@ export default function TestProgressBarChart({ progressSeries, progressCategorie
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const updateChartDate = () => {
|
const updateChartDate = () => {
|
||||||
if (progressSeries) {
|
if (progressSeries) {
|
||||||
const legendsLabelColors = testRunCaseStatus.map((itr) => {
|
const legendsLabelColors = testRunCaseStatus.map(() => {
|
||||||
if (theme === 'light') {
|
if (theme === 'light') {
|
||||||
return 'black';
|
return 'black';
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import { testTypes } from '@/config/selection';
|
import { testTypes } from '@/config/selection';
|
||||||
@@ -33,7 +32,7 @@ export default function TestTypesDonutChart({ typesCounts, testTypeMessages, the
|
|||||||
const colors = testTypes.map((entry) => entry.chartColor);
|
const colors = testTypes.map((entry) => entry.chartColor);
|
||||||
const legend = {
|
const legend = {
|
||||||
labels: {
|
labels: {
|
||||||
colors: testTypes.map((entry) => {
|
colors: testTypes.map(() => {
|
||||||
if (theme === 'light') {
|
if (theme === 'light') {
|
||||||
return 'black';
|
return 'black';
|
||||||
} else {
|
} else {
|
||||||
@@ -51,7 +50,7 @@ export default function TestTypesDonutChart({ typesCounts, testTypeMessages, the
|
|||||||
};
|
};
|
||||||
|
|
||||||
updateChartDate();
|
updateChartDate();
|
||||||
}, [typesCounts, theme]);
|
}, [typesCounts, theme, testTypeMessages]);
|
||||||
|
|
||||||
return <Chart options={chartData.options} series={chartData.series} type="donut" width={'100%'} height={'100%'} />;
|
return <Chart options={chartData.options} series={chartData.series} type="donut" width={'100%'} height={'100%'} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ function aggregateBasicInfo(project: ProjectType) {
|
|||||||
|
|
||||||
function aggregateTestType(project: ProjectType): CaseTypeCountType[] {
|
function aggregateTestType(project: ProjectType): CaseTypeCountType[] {
|
||||||
// count how many test cases are for each type
|
// count how many test cases are for each type
|
||||||
const typesCounts: number[] = testTypes.map((entry) => {
|
const typesCounts: number[] = testTypes.map(() => {
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
project.Folders.forEach((folder) => {
|
project.Folders.forEach((folder) => {
|
||||||
@@ -38,7 +38,7 @@ function aggregateTestType(project: ProjectType): CaseTypeCountType[] {
|
|||||||
|
|
||||||
function aggregateTestPriority(project: ProjectType) {
|
function aggregateTestPriority(project: ProjectType) {
|
||||||
// count how many test cases are for each priority
|
// count how many test cases are for each priority
|
||||||
const priorityCounts: number[] = priorities.map((entry) => {
|
const priorityCounts: number[] = priorities.map(() => {
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
project.Folders.forEach((folder) => {
|
project.Folders.forEach((folder) => {
|
||||||
@@ -58,10 +58,10 @@ function aggregateTestPriority(project: ProjectType) {
|
|||||||
|
|
||||||
function aggregateProgress(project: ProjectType, testRunCaseStatusMessages: TestRunCaseStatusMessages) {
|
function aggregateProgress(project: ProjectType, testRunCaseStatusMessages: TestRunCaseStatusMessages) {
|
||||||
type ChartSeries = { name: string; data: number[] };
|
type ChartSeries = { name: string; data: number[] };
|
||||||
let series: ChartSeries[] = testRunCaseStatus.map((status) => {
|
const series: ChartSeries[] = testRunCaseStatus.map((status) => {
|
||||||
return { name: testRunCaseStatusMessages[status.uid], data: [] };
|
return { name: testRunCaseStatusMessages[status.uid], data: [] };
|
||||||
});
|
});
|
||||||
let categories: string[] = [];
|
const categories: string[] = [];
|
||||||
|
|
||||||
project.Runs.forEach((run) => {
|
project.Runs.forEach((run) => {
|
||||||
if (!run.RunCases) {
|
if (!run.RunCases) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { LocaleCodeType } from '@/types/locale';
|
|
||||||
import { ProjectHome } from './ProjectHome';
|
|
||||||
import { getTranslations } from 'next-intl/server';
|
import { getTranslations } from 'next-intl/server';
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
|
import { ProjectHome } from './ProjectHome';
|
||||||
|
import { LocaleCodeType } from '@/types/locale';
|
||||||
import { PriorityMessages } from '@/types/priority';
|
import { PriorityMessages } from '@/types/priority';
|
||||||
import { TestTypeMessages } from '@/types/testType';
|
import { TestTypeMessages } from '@/types/testType';
|
||||||
import { TestRunCaseStatusMessages } from '@/types/status';
|
import { TestRunCaseStatusMessages } from '@/types/status';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { ProjectMessages } from '@/types/project';
|
|
||||||
import Sidebar from './Sidebar';
|
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
|
import Sidebar from './Sidebar';
|
||||||
|
import { ProjectMessages } from '@/types/project';
|
||||||
|
|
||||||
export default function SidebarLayout({
|
export default function SidebarLayout({
|
||||||
children,
|
children,
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import React from 'react';
|
|
||||||
import { useState, useEffect, useContext } from 'react';
|
import { useState, useEffect, useContext } from 'react';
|
||||||
import { Button, Input, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter } from '@heroui/react';
|
import { Button, Input, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter } from '@heroui/react';
|
||||||
|
import CandidatesTable from './CandidatesTable';
|
||||||
import { TokenContext } from '@/utils/TokenProvider';
|
import { TokenContext } from '@/utils/TokenProvider';
|
||||||
import { UserType } from '@/types/user';
|
import { UserType } from '@/types/user';
|
||||||
import { searchUsers } from '@/utils/usersControl';
|
import { searchUsers } from '@/utils/usersControl';
|
||||||
import CandidatesTable from './CandidatesTable';
|
|
||||||
import { MembersMessages } from '@/types/member';
|
import { MembersMessages } from '@/types/member';
|
||||||
|
import { logError } from '@/utils/errorHandler';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@@ -34,13 +34,13 @@ export default function AddMemberDialog({ isOpen, projectId, onCancel, onAddMemb
|
|||||||
try {
|
try {
|
||||||
const data = await searchUsers(context.token.access_token, Number(projectId), searchText);
|
const data = await searchUsers(context.token.access_token, Number(projectId), searchText);
|
||||||
setCandidates(data);
|
setCandidates(data);
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error in effect:', error.message);
|
logError('Error fetching data:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchDataEffect();
|
fetchDataEffect();
|
||||||
}, [searchText]);
|
}, [context, projectId, searchText]);
|
||||||
|
|
||||||
const handleExit = () => {
|
const handleExit = () => {
|
||||||
setSearchText('');
|
setSearchText('');
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useMemo, useCallback } from 'react';
|
import { useMemo, useCallback } from 'react';
|
||||||
import { Button, Table, TableHeader, TableColumn, TableBody, TableRow, TableCell } from '@heroui/react';
|
import { Button, Table, TableHeader, TableColumn, TableBody, TableRow, TableCell } from '@heroui/react';
|
||||||
import { UserType } from '@/types/user';
|
|
||||||
import Avatar from 'boring-avatars';
|
import Avatar from 'boring-avatars';
|
||||||
|
import { UserType } from '@/types/user';
|
||||||
import { MembersMessages } from '@/types/member';
|
import { MembersMessages } from '@/types/member';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -18,7 +18,8 @@ export default function MembersTable({ candidates, onAddPress, messages }: Props
|
|||||||
{ name: messages.add, uid: 'add', sortable: false },
|
{ name: messages.add, uid: 'add', sortable: false },
|
||||||
];
|
];
|
||||||
|
|
||||||
const renderCell = useCallback((candidate: UserType, columnKey: string) => {
|
const renderCell = useCallback(
|
||||||
|
(candidate: UserType, columnKey: string) => {
|
||||||
const cellValue = candidate[columnKey as keyof UserType];
|
const cellValue = candidate[columnKey as keyof UserType];
|
||||||
|
|
||||||
switch (columnKey) {
|
switch (columnKey) {
|
||||||
@@ -44,7 +45,9 @@ export default function MembersTable({ candidates, onAddPress, messages }: Props
|
|||||||
default:
|
default:
|
||||||
return cellValue;
|
return cellValue;
|
||||||
}
|
}
|
||||||
}, []);
|
},
|
||||||
|
[messages.add, onAddPress]
|
||||||
|
);
|
||||||
|
|
||||||
const classNames = useMemo(
|
const classNames = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
|
|||||||
@@ -1,23 +1,22 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import React from 'react';
|
|
||||||
import { useState, useEffect, useContext } from 'react';
|
import { useState, useEffect, useContext } from 'react';
|
||||||
import { Button } from '@heroui/react';
|
import { Button } from '@heroui/react';
|
||||||
import { Plus } from 'lucide-react';
|
import { Plus } from 'lucide-react';
|
||||||
import { MemberType, UserType } from '@/types/user';
|
|
||||||
import { MembersMessages } from '@/types/member';
|
|
||||||
import { TokenContext } from '@/utils/TokenProvider';
|
|
||||||
import MembersTable from './MembersTable';
|
import MembersTable from './MembersTable';
|
||||||
import AddMemberDialog from './AddMemberDialog';
|
import AddMemberDialog from './AddMemberDialog';
|
||||||
import { fetchProjectMembers, addMember, deleteMember, updateMember } from './membersControl';
|
import { fetchProjectMembers, addMember, deleteMember, updateMember } from './membersControl';
|
||||||
|
import { MemberType, UserType } from '@/types/user';
|
||||||
|
import { MembersMessages } from '@/types/member';
|
||||||
|
import { TokenContext } from '@/utils/TokenProvider';
|
||||||
import DeleteConfirmDialog from '@/components/DeleteConfirmDialog';
|
import DeleteConfirmDialog from '@/components/DeleteConfirmDialog';
|
||||||
|
import { logError } from '@/utils/errorHandler';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
messages: MembersMessages;
|
messages: MembersMessages;
|
||||||
locale: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function MembersPage({ projectId, messages, locale }: Props) {
|
export default function MembersPage({ projectId, messages }: Props) {
|
||||||
const context = useContext(TokenContext);
|
const context = useContext(TokenContext);
|
||||||
const [members, setMembers] = useState<MemberType[]>([]);
|
const [members, setMembers] = useState<MemberType[]>([]);
|
||||||
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
||||||
@@ -31,13 +30,13 @@ export default function MembersPage({ projectId, messages, locale }: Props) {
|
|||||||
try {
|
try {
|
||||||
const data = await fetchProjectMembers(context.token.access_token, projectId);
|
const data = await fetchProjectMembers(context.token.access_token, projectId);
|
||||||
setMembers(data);
|
setMembers(data);
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error in effect:', error.message);
|
logError('Error fetching members:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchDataEffect();
|
fetchDataEffect();
|
||||||
}, [context]);
|
}, [context, projectId]);
|
||||||
|
|
||||||
const handleAddMember = async (userAdded: UserType) => {
|
const handleAddMember = async (userAdded: UserType) => {
|
||||||
if (userAdded.id) {
|
if (userAdded.id) {
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ import {
|
|||||||
DropdownItem,
|
DropdownItem,
|
||||||
} from '@heroui/react';
|
} from '@heroui/react';
|
||||||
import { ChevronDown } from 'lucide-react';
|
import { ChevronDown } from 'lucide-react';
|
||||||
|
import Avatar from 'boring-avatars';
|
||||||
import { MemberType, UserType } from '@/types/user';
|
import { MemberType, UserType } from '@/types/user';
|
||||||
import { memberRoles } from '@/config/selection';
|
import { memberRoles } from '@/config/selection';
|
||||||
import Avatar from 'boring-avatars';
|
|
||||||
import { MembersMessages } from '@/types/member';
|
import { MembersMessages } from '@/types/member';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { logError } from '@/utils/errorHandler';
|
||||||
import Config from '@/config/config';
|
import Config from '@/config/config';
|
||||||
const apiServer = Config.apiServer;
|
const apiServer = Config.apiServer;
|
||||||
|
|
||||||
@@ -19,8 +20,8 @@ async function fetchProjectMembers(jwt: string, projectId: string) {
|
|||||||
}
|
}
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return data;
|
return data;
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error fetching data:', error.message);
|
logError('Error fetching data:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,8 +43,8 @@ async function addMember(jwt: string, userId: number, projectId: number) {
|
|||||||
}
|
}
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return data;
|
return data;
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error fetching data:', error.message);
|
logError('Error fetching data:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,8 +64,8 @@ async function deleteMember(jwt: string, userId: number, projectId: number) {
|
|||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error fetching data:', error.message);
|
logError('Error fetching data:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,8 +87,8 @@ async function updateMember(jwt: string, userId: number, projectId: number, role
|
|||||||
}
|
}
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return data;
|
return data;
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error fetching data:', error.message);
|
logError('Error fetching data:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { LocaleCodeType } from '@/types/locale';
|
|
||||||
import MembersPage from './MembersPage';
|
|
||||||
import { getTranslations } from 'next-intl/server';
|
import { getTranslations } from 'next-intl/server';
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
|
import MembersPage from './MembersPage';
|
||||||
|
import { LocaleCodeType } from '@/types/locale';
|
||||||
|
|
||||||
export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) {
|
export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) {
|
||||||
const t = await getTranslations({ locale, namespace: 'Members' });
|
const t = await getTranslations({ locale, namespace: 'Members' });
|
||||||
@@ -34,7 +34,7 @@ export default function Page({ params }: { params: { projectId: string; locale:
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MembersPage projectId={params.projectId} messages={messages} locale={params.locale} />
|
<MembersPage projectId={params.projectId} messages={messages} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import React from 'react';
|
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { Button, Input, Textarea, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter } from '@heroui/react';
|
import { Button, Input, Textarea, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter } from '@heroui/react';
|
||||||
import { RunType, RunsMessages } from '@/types/run';
|
import { RunType, RunsMessages } from '@/types/run';
|
||||||
@@ -47,7 +46,7 @@ export default function RunDialog({ isOpen, editingRun, onCancel, onSubmit, mess
|
|||||||
text: '',
|
text: '',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [editingRun]);
|
}, [editingRun, runDescription, runName]);
|
||||||
|
|
||||||
const clear = () => {
|
const clear = () => {
|
||||||
setRunName({
|
setRunName({
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { RunType, RunsMessages } from '@/types/run';
|
|||||||
import DeleteConfirmDialog from '@/components/DeleteConfirmDialog';
|
import DeleteConfirmDialog from '@/components/DeleteConfirmDialog';
|
||||||
import { TokenContext } from '@/utils/TokenProvider';
|
import { TokenContext } from '@/utils/TokenProvider';
|
||||||
import { LocaleCodeType } from '@/types/locale';
|
import { LocaleCodeType } from '@/types/locale';
|
||||||
|
import { logError } from '@/utils/errorHandler';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
@@ -61,13 +62,13 @@ export default function RunsPage({ projectId, locale, messages }: Props) {
|
|||||||
try {
|
try {
|
||||||
const data = await fetchRuns(context.token.access_token, Number(projectId));
|
const data = await fetchRuns(context.token.access_token, Number(projectId));
|
||||||
setRuns(data);
|
setRuns(data);
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error in effect:', error.message);
|
logError('Error fetching runs', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchDataEffect();
|
fetchDataEffect();
|
||||||
}, [context]);
|
}, [context, projectId]);
|
||||||
|
|
||||||
const onSubmit = async (name: string, description: string) => {
|
const onSubmit = async (name: string, description: string) => {
|
||||||
if (editingRun && editingRun.createdAt) {
|
if (editingRun && editingRun.createdAt) {
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ import {
|
|||||||
DropdownItem,
|
DropdownItem,
|
||||||
SortDescriptor,
|
SortDescriptor,
|
||||||
} from '@heroui/react';
|
} from '@heroui/react';
|
||||||
import { Link, NextUiLinkClasses } from '@/src/i18n/routing';
|
|
||||||
import { MoreVertical } from 'lucide-react';
|
import { MoreVertical } from 'lucide-react';
|
||||||
import { RunsMessages, RunType } from '@/types/run';
|
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
import { Link, NextUiLinkClasses } from '@/src/i18n/routing';
|
||||||
|
import { RunsMessages, RunType } from '@/types/run';
|
||||||
import { LocaleCodeType } from '@/types/locale';
|
import { LocaleCodeType } from '@/types/locale';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -70,7 +70,7 @@ export default function RunsTable({ projectId, isDisabled, runs, onDeleteRun, me
|
|||||||
switch (columnKey) {
|
switch (columnKey) {
|
||||||
case 'id':
|
case 'id':
|
||||||
return <span>{cellValue as number}</span>;
|
return <span>{cellValue as number}</span>;
|
||||||
case 'name':
|
case 'name': {
|
||||||
const maxLength = 30;
|
const maxLength = 30;
|
||||||
const truncatedDescription = truncateText(run.description, maxLength);
|
const truncatedDescription = truncateText(run.description, maxLength);
|
||||||
return (
|
return (
|
||||||
@@ -83,6 +83,7 @@ export default function RunsTable({ projectId, isDisabled, runs, onDeleteRun, me
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
case 'updatedAt':
|
case 'updatedAt':
|
||||||
return <span>{dayjs(cellValue as string).format('YYYY/MM/DD HH:mm')}</span>;
|
return <span>{dayjs(cellValue as string).format('YYYY/MM/DD HH:mm')}</span>;
|
||||||
case 'actions':
|
case 'actions':
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ import { useFormGuard } from '@/utils/formGuard';
|
|||||||
import { PriorityMessages } from '@/types/priority';
|
import { PriorityMessages } from '@/types/priority';
|
||||||
import { RunStatusMessages, TestRunCaseStatusMessages } from '@/types/status';
|
import { RunStatusMessages, TestRunCaseStatusMessages } from '@/types/status';
|
||||||
import { TestTypeMessages } from '@/types/testType';
|
import { TestTypeMessages } from '@/types/testType';
|
||||||
|
import { logError } from '@/utils/errorHandler';
|
||||||
|
|
||||||
const defaultTestRun = {
|
const defaultTestRun = {
|
||||||
id: 0,
|
id: 0,
|
||||||
@@ -132,12 +133,13 @@ export default function RunEditor({
|
|||||||
setFolders(foldersData);
|
setFolders(foldersData);
|
||||||
setSelectedFolder(foldersData[0]);
|
setSelectedFolder(foldersData[0]);
|
||||||
initTestCases();
|
initTestCases();
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error in effect:', error.message);
|
logError('Error fetching run data', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchDataEffect();
|
fetchDataEffect();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [tokenContext]);
|
}, [tokenContext]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -146,8 +148,8 @@ export default function RunEditor({
|
|||||||
try {
|
try {
|
||||||
const filteredData = testCases.filter((testCase) => testCase.folderId === selectedFolder.id);
|
const filteredData = testCases.filter((testCase) => testCase.folderId === selectedFolder.id);
|
||||||
setFilteredTestCases(filteredData);
|
setFilteredTestCases(filteredData);
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
console.error('Error fetching cases data:', error.message);
|
logError('Error filtering test cases', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import { testRunCaseStatus } from '@/config/selection';
|
import { testRunCaseStatus } from '@/config/selection';
|
||||||
@@ -34,7 +33,7 @@ export default function RunProgressDounut({ statusCounts, testRunCaseStatusMessa
|
|||||||
const colors = testRunCaseStatus.map((entry) => entry.chartColor);
|
const colors = testRunCaseStatus.map((entry) => entry.chartColor);
|
||||||
const legend = {
|
const legend = {
|
||||||
labels: {
|
labels: {
|
||||||
colors: testRunCaseStatus.map((entry) => {
|
colors: testRunCaseStatus.map(() => {
|
||||||
if (theme === 'light') {
|
if (theme === 'light') {
|
||||||
return 'black';
|
return 'black';
|
||||||
} else {
|
} else {
|
||||||
@@ -52,7 +51,7 @@ export default function RunProgressDounut({ statusCounts, testRunCaseStatusMessa
|
|||||||
};
|
};
|
||||||
|
|
||||||
updateChartDate();
|
updateChartDate();
|
||||||
}, [statusCounts, theme]);
|
}, [statusCounts, testRunCaseStatusMessages, theme]);
|
||||||
|
|
||||||
return <Chart options={chartData.options} series={chartData.series} type="donut" width={'100%'} height={'100%'} />;
|
return <Chart options={chartData.options} series={chartData.series} type="donut" width={'100%'} height={'100%'} />;
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user