diff --git a/.gitignore b/.gitignore index d0eb167..e427ff3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,3 @@ node_modules/ */node_modules/ */build/ - -**/node_modules/ -**/build/ -.DS_Store -.env \ No newline at end of file diff --git a/backend/src/db/api/organizations.js b/backend/src/db/api/organizations.js index fbf7550..f39346f 100644 --- a/backend/src/db/api/organizations.js +++ b/backend/src/db/api/organizations.js @@ -152,11 +152,6 @@ module.exports = class OrganizationsDBApi { transaction, }); - output.taskcategory_organizations = - await organizations.getTaskcategory_organizations({ - transaction, - }); - return output; } diff --git a/backend/src/db/api/taskcategory.js b/backend/src/db/api/taskcategory.js deleted file mode 100644 index c393480..0000000 --- a/backend/src/db/api/taskcategory.js +++ /dev/null @@ -1,313 +0,0 @@ -const db = require('../models'); -const FileDBApi = require('./file'); -const crypto = require('crypto'); -const Utils = require('../utils'); - -const Sequelize = db.Sequelize; -const Op = Sequelize.Op; - -module.exports = class TaskcategoryDBApi { - static async create(data, options) { - const currentUser = (options && options.currentUser) || { id: null }; - const transaction = (options && options.transaction) || undefined; - - const taskcategory = await db.taskcategory.create( - { - id: data.id || undefined, - - name: data.name || null, - importHash: data.importHash || null, - createdById: currentUser.id, - updatedById: currentUser.id, - }, - { transaction }, - ); - - await taskcategory.setOrganizations(data.organizations || null, { - transaction, - }); - - return taskcategory; - } - - static async bulkImport(data, options) { - const currentUser = (options && options.currentUser) || { id: null }; - const transaction = (options && options.transaction) || undefined; - - // Prepare data - wrapping individual data transformations in a map() method - const taskcategoryData = data.map((item, index) => ({ - id: item.id || undefined, - - name: item.name || null, - importHash: item.importHash || null, - createdById: currentUser.id, - updatedById: currentUser.id, - createdAt: new Date(Date.now() + index * 1000), - })); - - // Bulk create items - const taskcategory = await db.taskcategory.bulkCreate(taskcategoryData, { - transaction, - }); - - // For each item created, replace relation files - - return taskcategory; - } - - static async update(id, data, options) { - const currentUser = (options && options.currentUser) || { id: null }; - const transaction = (options && options.transaction) || undefined; - const globalAccess = currentUser.app_role?.globalAccess; - - const taskcategory = await db.taskcategory.findByPk( - id, - {}, - { transaction }, - ); - - const updatePayload = {}; - - if (data.name !== undefined) updatePayload.name = data.name; - - updatePayload.updatedById = currentUser.id; - - await taskcategory.update(updatePayload, { transaction }); - - if (data.organizations !== undefined) { - await taskcategory.setOrganizations( - data.organizations, - - { transaction }, - ); - } - - return taskcategory; - } - - static async deleteByIds(ids, options) { - const currentUser = (options && options.currentUser) || { id: null }; - const transaction = (options && options.transaction) || undefined; - - const taskcategory = await db.taskcategory.findAll({ - where: { - id: { - [Op.in]: ids, - }, - }, - transaction, - }); - - await db.sequelize.transaction(async (transaction) => { - for (const record of taskcategory) { - await record.update({ deletedBy: currentUser.id }, { transaction }); - } - for (const record of taskcategory) { - await record.destroy({ transaction }); - } - }); - - return taskcategory; - } - - static async remove(id, options) { - const currentUser = (options && options.currentUser) || { id: null }; - const transaction = (options && options.transaction) || undefined; - - const taskcategory = await db.taskcategory.findByPk(id, options); - - await taskcategory.update( - { - deletedBy: currentUser.id, - }, - { - transaction, - }, - ); - - await taskcategory.destroy({ - transaction, - }); - - return taskcategory; - } - - static async findBy(where, options) { - const transaction = (options && options.transaction) || undefined; - - const taskcategory = await db.taskcategory.findOne( - { where }, - { transaction }, - ); - - if (!taskcategory) { - return taskcategory; - } - - const output = taskcategory.get({ plain: true }); - - output.organizations = await taskcategory.getOrganizations({ - transaction, - }); - - return output; - } - - static async findAll(filter, globalAccess, options) { - const limit = filter.limit || 0; - let offset = 0; - let where = {}; - const currentPage = +filter.page; - - const user = (options && options.currentUser) || null; - const userOrganizations = (user && user.organizations?.id) || null; - - if (userOrganizations) { - if (options?.currentUser?.organizationsId) { - where.organizationsId = options.currentUser.organizationsId; - } - } - - offset = currentPage * limit; - - const orderBy = null; - - const transaction = (options && options.transaction) || undefined; - - let include = [ - { - model: db.organizations, - as: 'organizations', - }, - ]; - - if (filter) { - if (filter.id) { - where = { - ...where, - ['id']: Utils.uuid(filter.id), - }; - } - - if (filter.name) { - where = { - ...where, - [Op.and]: Utils.ilike('taskcategory', 'name', filter.name), - }; - } - - if (filter.active !== undefined) { - where = { - ...where, - active: filter.active === true || filter.active === 'true', - }; - } - - if (filter.organizations) { - const listItems = filter.organizations.split('|').map((item) => { - return Utils.uuid(item); - }); - - where = { - ...where, - organizationsId: { [Op.or]: listItems }, - }; - } - - if (filter.createdAtRange) { - const [start, end] = filter.createdAtRange; - - if (start !== undefined && start !== null && start !== '') { - where = { - ...where, - ['createdAt']: { - ...where.createdAt, - [Op.gte]: start, - }, - }; - } - - if (end !== undefined && end !== null && end !== '') { - where = { - ...where, - ['createdAt']: { - ...where.createdAt, - [Op.lte]: end, - }, - }; - } - } - } - - if (globalAccess) { - delete where.organizationsId; - } - - const queryOptions = { - where, - include, - distinct: true, - order: - filter.field && filter.sort - ? [[filter.field, filter.sort]] - : [['createdAt', 'desc']], - transaction: options?.transaction, - logging: console.log, - }; - - if (!options?.countOnly) { - queryOptions.limit = limit ? Number(limit) : undefined; - queryOptions.offset = offset ? Number(offset) : undefined; - } - - try { - const { rows, count } = await db.taskcategory.findAndCountAll( - queryOptions, - ); - - return { - rows: options?.countOnly ? [] : rows, - count: count, - }; - } catch (error) { - console.error('Error executing query:', error); - throw error; - } - } - - static async findAllAutocomplete( - query, - limit, - offset, - globalAccess, - organizationId, - ) { - let where = {}; - - if (!globalAccess && organizationId) { - where.organizationId = organizationId; - } - - if (query) { - where = { - [Op.or]: [ - { ['id']: Utils.uuid(query) }, - Utils.ilike('taskcategory', 'name', query), - ], - }; - } - - const records = await db.taskcategory.findAll({ - attributes: ['id', 'name'], - where, - limit: limit ? Number(limit) : undefined, - offset: offset ? Number(offset) : undefined, - orderBy: [['name', 'ASC']], - }); - - return records.map((record) => ({ - id: record.id, - label: record.name, - })); - } -}; diff --git a/backend/src/db/migrations/1744211739374.js b/backend/src/db/migrations/1744211739374.js deleted file mode 100644 index 79ec107..0000000 --- a/backend/src/db/migrations/1744211739374.js +++ /dev/null @@ -1,90 +0,0 @@ -module.exports = { - /** - * @param {QueryInterface} queryInterface - * @param {Sequelize} Sequelize - * @returns {Promise} - */ - async up(queryInterface, Sequelize) { - /** - * @type {Transaction} - */ - const transaction = await queryInterface.sequelize.transaction(); - try { - await queryInterface.createTable( - 'taskcategory', - { - id: { - type: Sequelize.DataTypes.UUID, - defaultValue: Sequelize.DataTypes.UUIDV4, - primaryKey: true, - }, - createdById: { - type: Sequelize.DataTypes.UUID, - references: { - key: 'id', - model: 'users', - }, - }, - updatedById: { - type: Sequelize.DataTypes.UUID, - references: { - key: 'id', - model: 'users', - }, - }, - createdAt: { type: Sequelize.DataTypes.DATE }, - updatedAt: { type: Sequelize.DataTypes.DATE }, - deletedAt: { type: Sequelize.DataTypes.DATE }, - importHash: { - type: Sequelize.DataTypes.STRING(255), - allowNull: true, - unique: true, - }, - }, - { transaction }, - ); - - await queryInterface.addColumn( - 'taskcategory', - 'organizationsId', - { - type: Sequelize.DataTypes.UUID, - - references: { - model: 'organizations', - key: 'id', - }, - }, - { transaction }, - ); - - await transaction.commit(); - } catch (err) { - await transaction.rollback(); - throw err; - } - }, - /** - * @param {QueryInterface} queryInterface - * @param {Sequelize} Sequelize - * @returns {Promise} - */ - async down(queryInterface, Sequelize) { - /** - * @type {Transaction} - */ - const transaction = await queryInterface.sequelize.transaction(); - try { - await queryInterface.removeColumn('taskcategory', 'organizationsId', { - transaction, - }); - - await queryInterface.dropTable('taskcategory', { transaction }); - - await transaction.commit(); - } catch (err) { - await transaction.rollback(); - throw err; - } - }, -}; diff --git a/backend/src/db/migrations/1744211761699.js b/backend/src/db/migrations/1744211761699.js deleted file mode 100644 index d2bd29a..0000000 --- a/backend/src/db/migrations/1744211761699.js +++ /dev/null @@ -1,49 +0,0 @@ -module.exports = { - /** - * @param {QueryInterface} queryInterface - * @param {Sequelize} Sequelize - * @returns {Promise} - */ - async up(queryInterface, Sequelize) { - /** - * @type {Transaction} - */ - const transaction = await queryInterface.sequelize.transaction(); - try { - await queryInterface.addColumn( - 'taskcategory', - 'name', - { - type: Sequelize.DataTypes.TEXT, - }, - { transaction }, - ); - - await transaction.commit(); - } catch (err) { - await transaction.rollback(); - throw err; - } - }, - /** - * @param {QueryInterface} queryInterface - * @param {Sequelize} Sequelize - * @returns {Promise} - */ - async down(queryInterface, Sequelize) { - /** - * @type {Transaction} - */ - const transaction = await queryInterface.sequelize.transaction(); - try { - await queryInterface.removeColumn('taskcategory', 'name', { - transaction, - }); - - await transaction.commit(); - } catch (err) { - await transaction.rollback(); - throw err; - } - }, -}; diff --git a/backend/src/db/models/organizations.js b/backend/src/db/models/organizations.js index c3bf841..f05abdc 100644 --- a/backend/src/db/models/organizations.js +++ b/backend/src/db/models/organizations.js @@ -66,14 +66,6 @@ module.exports = function (sequelize, DataTypes) { constraints: false, }); - db.organizations.hasMany(db.taskcategory, { - as: 'taskcategory_organizations', - foreignKey: { - name: 'organizationsId', - }, - constraints: false, - }); - //end loop db.organizations.belongsTo(db.users, { diff --git a/backend/src/db/models/taskcategory.js b/backend/src/db/models/taskcategory.js deleted file mode 100644 index 9934868..0000000 --- a/backend/src/db/models/taskcategory.js +++ /dev/null @@ -1,57 +0,0 @@ -const config = require('../../config'); -const providers = config.providers; -const crypto = require('crypto'); -const bcrypt = require('bcrypt'); -const moment = require('moment'); - -module.exports = function (sequelize, DataTypes) { - const taskcategory = sequelize.define( - 'taskcategory', - { - id: { - type: DataTypes.UUID, - defaultValue: DataTypes.UUIDV4, - primaryKey: true, - }, - - name: { - type: DataTypes.TEXT, - }, - - importHash: { - type: DataTypes.STRING(255), - allowNull: true, - unique: true, - }, - }, - { - timestamps: true, - paranoid: true, - freezeTableName: true, - }, - ); - - taskcategory.associate = (db) => { - /// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity - - //end loop - - db.taskcategory.belongsTo(db.organizations, { - as: 'organizations', - foreignKey: { - name: 'organizationsId', - }, - constraints: false, - }); - - db.taskcategory.belongsTo(db.users, { - as: 'createdBy', - }); - - db.taskcategory.belongsTo(db.users, { - as: 'updatedBy', - }); - }; - - return taskcategory; -}; diff --git a/backend/src/db/seeders/20200430130760-user-roles.js b/backend/src/db/seeders/20200430130760-user-roles.js index 74ecefe..904f9e8 100644 --- a/backend/src/db/seeders/20200430130760-user-roles.js +++ b/backend/src/db/seeders/20200430130760-user-roles.js @@ -116,7 +116,6 @@ module.exports = { 'roles', 'permissions', 'organizations', - 'taskcategory', , ]; await queryInterface.bulkInsert( @@ -677,31 +676,6 @@ primary key ("roles_permissionsId", "permissionId") permissionId: getId('DELETE_TASKS'), }, - { - createdAt, - updatedAt, - roles_permissionsId: getId('Administrator'), - permissionId: getId('CREATE_TASKCATEGORY'), - }, - { - createdAt, - updatedAt, - roles_permissionsId: getId('Administrator'), - permissionId: getId('READ_TASKCATEGORY'), - }, - { - createdAt, - updatedAt, - roles_permissionsId: getId('Administrator'), - permissionId: getId('UPDATE_TASKCATEGORY'), - }, - { - createdAt, - updatedAt, - roles_permissionsId: getId('Administrator'), - permissionId: getId('DELETE_TASKCATEGORY'), - }, - { createdAt, updatedAt, @@ -877,31 +851,6 @@ primary key ("roles_permissionsId", "permissionId") permissionId: getId('DELETE_ORGANIZATIONS'), }, - { - createdAt, - updatedAt, - roles_permissionsId: getId('SuperAdmin'), - permissionId: getId('CREATE_TASKCATEGORY'), - }, - { - createdAt, - updatedAt, - roles_permissionsId: getId('SuperAdmin'), - permissionId: getId('READ_TASKCATEGORY'), - }, - { - createdAt, - updatedAt, - roles_permissionsId: getId('SuperAdmin'), - permissionId: getId('UPDATE_TASKCATEGORY'), - }, - { - createdAt, - updatedAt, - roles_permissionsId: getId('SuperAdmin'), - permissionId: getId('DELETE_TASKCATEGORY'), - }, - { createdAt, updatedAt, diff --git a/backend/src/db/seeders/20231127130745-sample-data.js b/backend/src/db/seeders/20231127130745-sample-data.js index bfac9eb..067288a 100644 --- a/backend/src/db/seeders/20231127130745-sample-data.js +++ b/backend/src/db/seeders/20231127130745-sample-data.js @@ -9,8 +9,6 @@ const Tasks = db.tasks; const Organizations = db.organizations; -const Taskcategory = db.taskcategory; - const CommentsData = [ { content: 'Great progress on the homepage design!', @@ -135,7 +133,7 @@ const TasksData = [ description: 'Develop the backend API for the mobile app.', - status: 'ToDo', + status: 'InProgress', // type code here for "relation_one" field @@ -171,7 +169,7 @@ const TasksData = [ description: 'Develop content for the new marketing ads.', - status: 'Done', + status: 'ToDo', // type code here for "relation_one" field @@ -187,45 +185,19 @@ const TasksData = [ const OrganizationsData = [ { - name: 'Comte de Buffon', + name: 'Neils Bohr', }, { - name: 'Richard Feynman', + name: 'Emil Fischer', }, { - name: 'Isaac Newton', + name: 'Stephen Hawking', }, { - name: 'Wilhelm Wundt', - }, -]; - -const TaskcategoryData = [ - { - // type code here for "relation_one" field - - name: 'Edward Teller', - }, - - { - // type code here for "relation_one" field - - name: 'Robert Koch', - }, - - { - // type code here for "relation_one" field - - name: 'Jonas Salk', - }, - - { - // type code here for "relation_one" field - - name: 'Erwin Schrodinger', + name: 'Linus Pauling', }, ]; @@ -649,52 +621,6 @@ async function associateTaskWithOrganization() { } } -async function associateTaskcategoryWithOrganization() { - const relatedOrganization0 = await Organizations.findOne({ - offset: Math.floor(Math.random() * (await Organizations.count())), - }); - const Taskcategory0 = await Taskcategory.findOne({ - order: [['id', 'ASC']], - offset: 0, - }); - if (Taskcategory0?.setOrganization) { - await Taskcategory0.setOrganization(relatedOrganization0); - } - - const relatedOrganization1 = await Organizations.findOne({ - offset: Math.floor(Math.random() * (await Organizations.count())), - }); - const Taskcategory1 = await Taskcategory.findOne({ - order: [['id', 'ASC']], - offset: 1, - }); - if (Taskcategory1?.setOrganization) { - await Taskcategory1.setOrganization(relatedOrganization1); - } - - const relatedOrganization2 = await Organizations.findOne({ - offset: Math.floor(Math.random() * (await Organizations.count())), - }); - const Taskcategory2 = await Taskcategory.findOne({ - order: [['id', 'ASC']], - offset: 2, - }); - if (Taskcategory2?.setOrganization) { - await Taskcategory2.setOrganization(relatedOrganization2); - } - - const relatedOrganization3 = await Organizations.findOne({ - offset: Math.floor(Math.random() * (await Organizations.count())), - }); - const Taskcategory3 = await Taskcategory.findOne({ - order: [['id', 'ASC']], - offset: 3, - }); - if (Taskcategory3?.setOrganization) { - await Taskcategory3.setOrganization(relatedOrganization3); - } -} - module.exports = { up: async (queryInterface, Sequelize) => { await Comments.bulkCreate(CommentsData); @@ -705,8 +631,6 @@ module.exports = { await Organizations.bulkCreate(OrganizationsData); - await Taskcategory.bulkCreate(TaskcategoryData); - await Promise.all([ // Similar logic for "relation_many" @@ -731,8 +655,6 @@ module.exports = { await associateTaskWithProject(), await associateTaskWithOrganization(), - - await associateTaskcategoryWithOrganization(), ]); }, @@ -744,7 +666,5 @@ module.exports = { await queryInterface.bulkDelete('tasks', null, {}); await queryInterface.bulkDelete('organizations', null, {}); - - await queryInterface.bulkDelete('taskcategory', null, {}); }, }; diff --git a/backend/src/db/seeders/20250409151539.js b/backend/src/db/seeders/20250409151539.js deleted file mode 100644 index f6595ae..0000000 --- a/backend/src/db/seeders/20250409151539.js +++ /dev/null @@ -1,87 +0,0 @@ -const { v4: uuid } = require('uuid'); -const db = require('../models'); -const Sequelize = require('sequelize'); -const config = require('../../config'); - -module.exports = { - /** - * @param{import("sequelize").QueryInterface} queryInterface - * @return {Promise} - */ - async up(queryInterface) { - const createdAt = new Date(); - const updatedAt = new Date(); - - /** @type {Map} */ - const idMap = new Map(); - - /** - * @param {string} key - * @return {string} - */ - function getId(key) { - if (idMap.has(key)) { - return idMap.get(key); - } - const id = uuid(); - idMap.set(key, id); - return id; - } - - /** - * @param {string} name - */ - function createPermissions(name) { - return [ - { - id: getId(`CREATE_${name.toUpperCase()}`), - createdAt, - updatedAt, - name: `CREATE_${name.toUpperCase()}`, - }, - { - id: getId(`READ_${name.toUpperCase()}`), - createdAt, - updatedAt, - name: `READ_${name.toUpperCase()}`, - }, - { - id: getId(`UPDATE_${name.toUpperCase()}`), - createdAt, - updatedAt, - name: `UPDATE_${name.toUpperCase()}`, - }, - { - id: getId(`DELETE_${name.toUpperCase()}`), - createdAt, - updatedAt, - name: `DELETE_${name.toUpperCase()}`, - }, - ]; - } - - const entities = ['taskcategory']; - - const createdPermissions = entities.flatMap(createPermissions); - - // Add permissions to database - await queryInterface.bulkInsert('permissions', createdPermissions); - // Get permissions ids - const permissionsIds = createdPermissions.map((p) => p.id); - // Get admin role - const adminRole = await db.roles.findOne({ - where: { name: config.roles.super_admin }, - }); - - if (adminRole) { - // Add permissions to admin role if it exists - await adminRole.addPermissions(permissionsIds); - } - }, - down: async (queryInterface, Sequelize) => { - await queryInterface.bulkDelete( - 'permissions', - entities.flatMap(createPermissions), - ); - }, -}; diff --git a/backend/src/index.js b/backend/src/index.js index d85dbeb..61a114c 100644 --- a/backend/src/index.js +++ b/backend/src/index.js @@ -35,8 +35,6 @@ const permissionsRoutes = require('./routes/permissions'); const organizationsRoutes = require('./routes/organizations'); -const taskcategoryRoutes = require('./routes/taskcategory'); - const getBaseUrl = (url) => { if (!url) return ''; return url.endsWith('/api') ? url.slice(0, -4) : url; @@ -144,12 +142,6 @@ app.use( organizationsRoutes, ); -app.use( - '/api/taskcategory', - passport.authenticate('jwt', { session: false }), - taskcategoryRoutes, -); - app.use( '/api/openai', passport.authenticate('jwt', { session: false }), diff --git a/backend/src/routes/taskcategory.js b/backend/src/routes/taskcategory.js deleted file mode 100644 index 2274ab5..0000000 --- a/backend/src/routes/taskcategory.js +++ /dev/null @@ -1,456 +0,0 @@ -const express = require('express'); - -const TaskcategoryService = require('../services/taskcategory'); -const TaskcategoryDBApi = require('../db/api/taskcategory'); -const wrapAsync = require('../helpers').wrapAsync; - -const config = require('../config'); - -const router = express.Router(); - -const { parse } = require('json2csv'); - -const { checkCrudPermissions } = require('../middlewares/check-permissions'); - -router.use(checkCrudPermissions('taskcategory')); - -/** - * @swagger - * components: - * schemas: - * Taskcategory: - * type: object - * properties: - - * name: - * type: string - * default: name - - */ - -/** - * @swagger - * tags: - * name: Taskcategory - * description: The Taskcategory managing API - */ - -/** - * @swagger - * /api/taskcategory: - * post: - * security: - * - bearerAuth: [] - * tags: [Taskcategory] - * summary: Add new item - * description: Add new item - * requestBody: - * required: true - * content: - * application/json: - * schema: - * properties: - * data: - * description: Data of the updated item - * type: object - * $ref: "#/components/schemas/Taskcategory" - * responses: - * 200: - * description: The item was successfully added - * content: - * application/json: - * schema: - * $ref: "#/components/schemas/Taskcategory" - * 401: - * $ref: "#/components/responses/UnauthorizedError" - * 405: - * description: Invalid input data - * 500: - * description: Some server error - */ -router.post( - '/', - wrapAsync(async (req, res) => { - const referer = - req.headers.referer || - `${req.protocol}://${req.hostname}${req.originalUrl}`; - const link = new URL(referer); - await TaskcategoryService.create( - req.body.data, - req.currentUser, - true, - link.host, - ); - const payload = true; - res.status(200).send(payload); - }), -); - -/** - * @swagger - * /api/budgets/bulk-import: - * post: - * security: - * - bearerAuth: [] - * tags: [Taskcategory] - * summary: Bulk import items - * description: Bulk import items - * requestBody: - * required: true - * content: - * application/json: - * schema: - * properties: - * data: - * description: Data of the updated items - * type: array - * items: - * $ref: "#/components/schemas/Taskcategory" - * responses: - * 200: - * description: The items were successfully imported - * content: - * application/json: - * schema: - * $ref: "#/components/schemas/Taskcategory" - * 401: - * $ref: "#/components/responses/UnauthorizedError" - * 405: - * description: Invalid input data - * 500: - * description: Some server error - * - */ -router.post( - '/bulk-import', - wrapAsync(async (req, res) => { - const referer = - req.headers.referer || - `${req.protocol}://${req.hostname}${req.originalUrl}`; - const link = new URL(referer); - await TaskcategoryService.bulkImport(req, res, true, link.host); - const payload = true; - res.status(200).send(payload); - }), -); - -/** - * @swagger - * /api/taskcategory/{id}: - * put: - * security: - * - bearerAuth: [] - * tags: [Taskcategory] - * summary: Update the data of the selected item - * description: Update the data of the selected item - * parameters: - * - in: path - * name: id - * description: Item ID to update - * required: true - * schema: - * type: string - * requestBody: - * description: Set new item data - * required: true - * content: - * application/json: - * schema: - * properties: - * id: - * description: ID of the updated item - * type: string - * data: - * description: Data of the updated item - * type: object - * $ref: "#/components/schemas/Taskcategory" - * required: - * - id - * responses: - * 200: - * description: The item data was successfully updated - * content: - * application/json: - * schema: - * $ref: "#/components/schemas/Taskcategory" - * 400: - * description: Invalid ID supplied - * 401: - * $ref: "#/components/responses/UnauthorizedError" - * 404: - * description: Item not found - * 500: - * description: Some server error - */ -router.put( - '/:id', - wrapAsync(async (req, res) => { - await TaskcategoryService.update( - req.body.data, - req.body.id, - req.currentUser, - ); - const payload = true; - res.status(200).send(payload); - }), -); - -/** - * @swagger - * /api/taskcategory/{id}: - * delete: - * security: - * - bearerAuth: [] - * tags: [Taskcategory] - * summary: Delete the selected item - * description: Delete the selected item - * parameters: - * - in: path - * name: id - * description: Item ID to delete - * required: true - * schema: - * type: string - * responses: - * 200: - * description: The item was successfully deleted - * content: - * application/json: - * schema: - * $ref: "#/components/schemas/Taskcategory" - * 400: - * description: Invalid ID supplied - * 401: - * $ref: "#/components/responses/UnauthorizedError" - * 404: - * description: Item not found - * 500: - * description: Some server error - */ -router.delete( - '/:id', - wrapAsync(async (req, res) => { - await TaskcategoryService.remove(req.params.id, req.currentUser); - const payload = true; - res.status(200).send(payload); - }), -); - -/** - * @swagger - * /api/taskcategory/deleteByIds: - * post: - * security: - * - bearerAuth: [] - * tags: [Taskcategory] - * summary: Delete the selected item list - * description: Delete the selected item list - * requestBody: - * required: true - * content: - * application/json: - * schema: - * properties: - * ids: - * description: IDs of the updated items - * type: array - * responses: - * 200: - * description: The items was successfully deleted - * content: - * application/json: - * schema: - * $ref: "#/components/schemas/Taskcategory" - * 401: - * $ref: "#/components/responses/UnauthorizedError" - * 404: - * description: Items not found - * 500: - * description: Some server error - */ -router.post( - '/deleteByIds', - wrapAsync(async (req, res) => { - await TaskcategoryService.deleteByIds(req.body.data, req.currentUser); - const payload = true; - res.status(200).send(payload); - }), -); - -/** - * @swagger - * /api/taskcategory: - * get: - * security: - * - bearerAuth: [] - * tags: [Taskcategory] - * summary: Get all taskcategory - * description: Get all taskcategory - * responses: - * 200: - * description: Taskcategory list successfully received - * content: - * application/json: - * schema: - * type: array - * items: - * $ref: "#/components/schemas/Taskcategory" - * 401: - * $ref: "#/components/responses/UnauthorizedError" - * 404: - * description: Data not found - * 500: - * description: Some server error - */ -router.get( - '/', - wrapAsync(async (req, res) => { - const filetype = req.query.filetype; - - const globalAccess = req.currentUser.app_role.globalAccess; - - const currentUser = req.currentUser; - const payload = await TaskcategoryDBApi.findAll(req.query, globalAccess, { - currentUser, - }); - if (filetype && filetype === 'csv') { - const fields = ['id', 'name']; - const opts = { fields }; - try { - const csv = parse(payload.rows, opts); - res.status(200).attachment(csv); - res.send(csv); - } catch (err) { - console.error(err); - } - } else { - res.status(200).send(payload); - } - }), -); - -/** - * @swagger - * /api/taskcategory/count: - * get: - * security: - * - bearerAuth: [] - * tags: [Taskcategory] - * summary: Count all taskcategory - * description: Count all taskcategory - * responses: - * 200: - * description: Taskcategory count successfully received - * content: - * application/json: - * schema: - * type: array - * items: - * $ref: "#/components/schemas/Taskcategory" - * 401: - * $ref: "#/components/responses/UnauthorizedError" - * 404: - * description: Data not found - * 500: - * description: Some server error - */ -router.get( - '/count', - wrapAsync(async (req, res) => { - const globalAccess = req.currentUser.app_role.globalAccess; - - const currentUser = req.currentUser; - const payload = await TaskcategoryDBApi.findAll(req.query, globalAccess, { - countOnly: true, - currentUser, - }); - - res.status(200).send(payload); - }), -); - -/** - * @swagger - * /api/taskcategory/autocomplete: - * get: - * security: - * - bearerAuth: [] - * tags: [Taskcategory] - * summary: Find all taskcategory that match search criteria - * description: Find all taskcategory that match search criteria - * responses: - * 200: - * description: Taskcategory list successfully received - * content: - * application/json: - * schema: - * type: array - * items: - * $ref: "#/components/schemas/Taskcategory" - * 401: - * $ref: "#/components/responses/UnauthorizedError" - * 404: - * description: Data not found - * 500: - * description: Some server error - */ -router.get('/autocomplete', async (req, res) => { - const globalAccess = req.currentUser.app_role.globalAccess; - - const organizationId = req.currentUser.organization?.id; - - const payload = await TaskcategoryDBApi.findAllAutocomplete( - req.query.query, - req.query.limit, - req.query.offset, - globalAccess, - organizationId, - ); - - res.status(200).send(payload); -}); - -/** - * @swagger - * /api/taskcategory/{id}: - * get: - * security: - * - bearerAuth: [] - * tags: [Taskcategory] - * summary: Get selected item - * description: Get selected item - * parameters: - * - in: path - * name: id - * description: ID of item to get - * required: true - * schema: - * type: string - * responses: - * 200: - * description: Selected item successfully received - * content: - * application/json: - * schema: - * $ref: "#/components/schemas/Taskcategory" - * 400: - * description: Invalid ID supplied - * 401: - * $ref: "#/components/responses/UnauthorizedError" - * 404: - * description: Item not found - * 500: - * description: Some server error - */ -router.get( - '/:id', - wrapAsync(async (req, res) => { - const payload = await TaskcategoryDBApi.findBy({ id: req.params.id }); - - res.status(200).send(payload); - }), -); - -router.use('/', require('../helpers').commonErrorHandler); - -module.exports = router; diff --git a/backend/src/services/search.js b/backend/src/services/search.js index 9b6130d..077ceeb 100644 --- a/backend/src/services/search.js +++ b/backend/src/services/search.js @@ -50,8 +50,6 @@ module.exports = class SearchService { tasks: ['title', 'description'], organizations: ['name'], - - taskcategory: ['name'], }; const columnsInt = {}; diff --git a/backend/src/services/taskcategory.js b/backend/src/services/taskcategory.js deleted file mode 100644 index f9b5c76..0000000 --- a/backend/src/services/taskcategory.js +++ /dev/null @@ -1,117 +0,0 @@ -const db = require('../db/models'); -const TaskcategoryDBApi = require('../db/api/taskcategory'); -const processFile = require('../middlewares/upload'); -const ValidationError = require('./notifications/errors/validation'); -const csv = require('csv-parser'); -const axios = require('axios'); -const config = require('../config'); -const stream = require('stream'); - -module.exports = class TaskcategoryService { - static async create(data, currentUser) { - const transaction = await db.sequelize.transaction(); - try { - await TaskcategoryDBApi.create(data, { - currentUser, - transaction, - }); - - await transaction.commit(); - } catch (error) { - await transaction.rollback(); - throw error; - } - } - - static async bulkImport(req, res, sendInvitationEmails = true, host) { - const transaction = await db.sequelize.transaction(); - - try { - await processFile(req, res); - const bufferStream = new stream.PassThrough(); - const results = []; - - await bufferStream.end(Buffer.from(req.file.buffer, 'utf-8')); // convert Buffer to Stream - - await new Promise((resolve, reject) => { - bufferStream - .pipe(csv()) - .on('data', (data) => results.push(data)) - .on('end', async () => { - console.log('CSV results', results); - resolve(); - }) - .on('error', (error) => reject(error)); - }); - - await TaskcategoryDBApi.bulkImport(results, { - transaction, - ignoreDuplicates: true, - validate: true, - currentUser: req.currentUser, - }); - - await transaction.commit(); - } catch (error) { - await transaction.rollback(); - throw error; - } - } - - static async update(data, id, currentUser) { - const transaction = await db.sequelize.transaction(); - try { - let taskcategory = await TaskcategoryDBApi.findBy( - { id }, - { transaction }, - ); - - if (!taskcategory) { - throw new ValidationError('taskcategoryNotFound'); - } - - const updatedTaskcategory = await TaskcategoryDBApi.update(id, data, { - currentUser, - transaction, - }); - - await transaction.commit(); - return updatedTaskcategory; - } catch (error) { - await transaction.rollback(); - throw error; - } - } - - static async deleteByIds(ids, currentUser) { - const transaction = await db.sequelize.transaction(); - - try { - await TaskcategoryDBApi.deleteByIds(ids, { - currentUser, - transaction, - }); - - await transaction.commit(); - } catch (error) { - await transaction.rollback(); - throw error; - } - } - - static async remove(id, currentUser) { - const transaction = await db.sequelize.transaction(); - - try { - await TaskcategoryDBApi.remove(id, { - currentUser, - transaction, - }); - - await transaction.commit(); - } catch (error) { - await transaction.rollback(); - throw error; - } - } -}; diff --git a/frontend/json/runtimeError.json b/frontend/json/runtimeError.json deleted file mode 100644 index 9e26dfe..0000000 --- a/frontend/json/runtimeError.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/frontend/src/components/Taskcategory/CardTaskcategory.tsx b/frontend/src/components/Taskcategory/CardTaskcategory.tsx deleted file mode 100644 index 0bfbb81..0000000 --- a/frontend/src/components/Taskcategory/CardTaskcategory.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import React from 'react'; -import ImageField from '../ImageField'; -import ListActionsPopover from '../ListActionsPopover'; -import { useAppSelector } from '../../stores/hooks'; -import dataFormatter from '../../helpers/dataFormatter'; -import { Pagination } from '../Pagination'; -import { saveFile } from '../../helpers/fileSaver'; -import LoadingSpinner from '../LoadingSpinner'; -import Link from 'next/link'; - -import { hasPermission } from '../../helpers/userPermissions'; - -type Props = { - taskcategory: any[]; - loading: boolean; - onDelete: (id: string) => void; - currentPage: number; - numPages: number; - onPageChange: (page: number) => void; -}; - -const CardTaskcategory = ({ - taskcategory, - loading, - onDelete, - currentPage, - numPages, - onPageChange, -}: Props) => { - const asideScrollbarsStyle = useAppSelector( - (state) => state.style.asideScrollbarsStyle, - ); - const bgColor = useAppSelector((state) => state.style.cardsColor); - const darkMode = useAppSelector((state) => state.style.darkMode); - const corners = useAppSelector((state) => state.style.corners); - const focusRing = useAppSelector((state) => state.style.focusRingColor); - - const currentUser = useAppSelector((state) => state.auth.currentUser); - const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_TASKCATEGORY'); - - return ( -
- {loading && } -
    - {!loading && - taskcategory.map((item, index) => ( -
  • -
    - - {item.name} - - -
    - -
    -
    -
    -
    -
    Name
    -
    -
    {item.name}
    -
    -
    -
    -
  • - ))} - {!loading && taskcategory.length === 0 && ( -
    -

    No data to display

    -
    - )} -
-
- -
-
- ); -}; - -export default CardTaskcategory; diff --git a/frontend/src/components/Taskcategory/ListTaskcategory.tsx b/frontend/src/components/Taskcategory/ListTaskcategory.tsx deleted file mode 100644 index 0fba55a..0000000 --- a/frontend/src/components/Taskcategory/ListTaskcategory.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import React from 'react'; -import CardBox from '../CardBox'; -import ImageField from '../ImageField'; -import dataFormatter from '../../helpers/dataFormatter'; -import { saveFile } from '../../helpers/fileSaver'; -import ListActionsPopover from '../ListActionsPopover'; -import { useAppSelector } from '../../stores/hooks'; -import { Pagination } from '../Pagination'; -import LoadingSpinner from '../LoadingSpinner'; -import Link from 'next/link'; - -import { hasPermission } from '../../helpers/userPermissions'; - -type Props = { - taskcategory: any[]; - loading: boolean; - onDelete: (id: string) => void; - currentPage: number; - numPages: number; - onPageChange: (page: number) => void; -}; - -const ListTaskcategory = ({ - taskcategory, - loading, - onDelete, - currentPage, - numPages, - onPageChange, -}: Props) => { - const currentUser = useAppSelector((state) => state.auth.currentUser); - const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_TASKCATEGORY'); - - const corners = useAppSelector((state) => state.style.corners); - const bgColor = useAppSelector((state) => state.style.cardsColor); - - return ( - <> -
- {loading && } - {!loading && - taskcategory.map((item) => ( - -
- dark:divide-dark-700 overflow-x-auto' - } - > -
-

Name

-

{item.name}

-
- - -
-
- ))} - {!loading && taskcategory.length === 0 && ( -
-

No data to display

-
- )} -
-
- -
- - ); -}; - -export default ListTaskcategory; diff --git a/frontend/src/components/Taskcategory/TableTaskcategory.tsx b/frontend/src/components/Taskcategory/TableTaskcategory.tsx deleted file mode 100644 index 92deef1..0000000 --- a/frontend/src/components/Taskcategory/TableTaskcategory.tsx +++ /dev/null @@ -1,484 +0,0 @@ -import React, { useEffect, useState, useMemo } from 'react'; -import { createPortal } from 'react-dom'; -import { ToastContainer, toast } from 'react-toastify'; -import BaseButton from '../BaseButton'; -import CardBoxModal from '../CardBoxModal'; -import CardBox from '../CardBox'; -import { - fetch, - update, - deleteItem, - setRefetch, - deleteItemsByIds, -} from '../../stores/taskcategory/taskcategorySlice'; -import { useAppDispatch, useAppSelector } from '../../stores/hooks'; -import { useRouter } from 'next/router'; -import { Field, Form, Formik } from 'formik'; -import { DataGrid, GridColDef } from '@mui/x-data-grid'; -import { loadColumns } from './configureTaskcategoryCols'; -import _ from 'lodash'; -import dataFormatter from '../../helpers/dataFormatter'; -import { dataGridStyles } from '../../styles'; - -const perPage = 10; - -const TableSampleTaskcategory = ({ - filterItems, - setFilterItems, - filters, - showGrid, -}) => { - const notify = (type, msg) => toast(msg, { type, position: 'bottom-center' }); - - const dispatch = useAppDispatch(); - const router = useRouter(); - - const pagesList = []; - const [id, setId] = useState(null); - const [currentPage, setCurrentPage] = useState(0); - const [filterRequest, setFilterRequest] = React.useState(''); - const [columns, setColumns] = useState([]); - const [selectedRows, setSelectedRows] = useState([]); - const [sortModel, setSortModel] = useState([ - { - field: '', - sort: 'desc', - }, - ]); - - const { - taskcategory, - loading, - count, - notify: taskcategoryNotify, - refetch, - } = useAppSelector((state) => state.taskcategory); - const { currentUser } = useAppSelector((state) => state.auth); - const focusRing = useAppSelector((state) => state.style.focusRingColor); - const bgColor = useAppSelector((state) => state.style.bgLayoutColor); - const corners = useAppSelector((state) => state.style.corners); - const numPages = - Math.floor(count / perPage) === 0 ? 1 : Math.ceil(count / perPage); - for (let i = 0; i < numPages; i++) { - pagesList.push(i); - } - - const loadData = async (page = currentPage, request = filterRequest) => { - if (page !== currentPage) setCurrentPage(page); - if (request !== filterRequest) setFilterRequest(request); - const { sort, field } = sortModel[0]; - - const query = `?page=${page}&limit=${perPage}${request}&sort=${sort}&field=${field}`; - dispatch(fetch({ limit: perPage, page, query })); - }; - - useEffect(() => { - if (taskcategoryNotify.showNotification) { - notify( - taskcategoryNotify.typeNotification, - taskcategoryNotify.textNotification, - ); - } - }, [taskcategoryNotify.showNotification]); - - useEffect(() => { - if (!currentUser) return; - loadData(); - }, [sortModel, currentUser]); - - useEffect(() => { - if (refetch) { - loadData(0); - dispatch(setRefetch(false)); - } - }, [refetch, dispatch]); - - const [isModalInfoActive, setIsModalInfoActive] = useState(false); - const [isModalTrashActive, setIsModalTrashActive] = useState(false); - - const handleModalAction = () => { - setIsModalInfoActive(false); - setIsModalTrashActive(false); - }; - - const handleDeleteModalAction = (id: string) => { - setId(id); - setIsModalTrashActive(true); - }; - const handleDeleteAction = async () => { - if (id) { - await dispatch(deleteItem(id)); - await loadData(0); - setIsModalTrashActive(false); - } - }; - - const generateFilterRequests = useMemo(() => { - let request = '&'; - filterItems.forEach((item) => { - const isRangeFilter = filters.find( - (filter) => - filter.title === item.fields.selectedField && - (filter.number || filter.date), - ); - - if (isRangeFilter) { - const from = item.fields.filterValueFrom; - const to = item.fields.filterValueTo; - if (from) { - request += `${item.fields.selectedField}Range=${from}&`; - } - if (to) { - request += `${item.fields.selectedField}Range=${to}&`; - } - } else { - const value = item.fields.filterValue; - if (value) { - request += `${item.fields.selectedField}=${value}&`; - } - } - }); - return request; - }, [filterItems, filters]); - - const deleteFilter = (value) => { - const newItems = filterItems.filter((item) => item.id !== value); - - if (newItems.length) { - setFilterItems(newItems); - } else { - loadData(0, ''); - - setFilterItems(newItems); - } - }; - - const handleSubmit = () => { - loadData(0, generateFilterRequests); - }; - - const handleChange = (id) => (e) => { - const value = e.target.value; - const name = e.target.name; - - setFilterItems( - filterItems.map((item) => { - if (item.id !== id) return item; - if (name === 'selectedField') return { id, fields: { [name]: value } }; - - return { id, fields: { ...item.fields, [name]: value } }; - }), - ); - }; - - const handleReset = () => { - setFilterItems([]); - loadData(0, ''); - }; - - const onPageChange = (page: number) => { - loadData(page); - setCurrentPage(page); - }; - - useEffect(() => { - if (!currentUser) return; - - loadColumns(handleDeleteModalAction, `taskcategory`, currentUser).then( - (newCols) => setColumns(newCols), - ); - }, [currentUser]); - - const handleTableSubmit = async (id: string, data) => { - if (!_.isEmpty(data)) { - await dispatch(update({ id, data })) - .unwrap() - .then((res) => res) - .catch((err) => { - throw new Error(err); - }); - } - }; - - const onDeleteRows = async (selectedRows) => { - await dispatch(deleteItemsByIds(selectedRows)); - await loadData(0); - }; - - const controlClasses = - 'w-full py-2 px-2 my-2 rounded dark:placeholder-gray-400 ' + - ` ${bgColor} ${focusRing} ${corners} ` + - 'dark:bg-slate-800 border'; - - const dataGrid = ( -
- `datagrid--row`} - rows={taskcategory ?? []} - columns={columns} - initialState={{ - pagination: { - paginationModel: { - pageSize: 10, - }, - }, - }} - disableRowSelectionOnClick - onProcessRowUpdateError={(params) => { - console.log('Error', params); - }} - processRowUpdate={async (newRow, oldRow) => { - const data = dataFormatter.dataGridEditFormatter(newRow); - - try { - await handleTableSubmit(newRow.id, data); - return newRow; - } catch { - return oldRow; - } - }} - sortingMode={'server'} - checkboxSelection - onRowSelectionModelChange={(ids) => { - setSelectedRows(ids); - }} - onSortModelChange={(params) => { - params.length - ? setSortModel(params) - : setSortModel([{ field: '', sort: 'desc' }]); - }} - rowCount={count} - pageSizeOptions={[10]} - paginationMode={'server'} - loading={loading} - onPaginationModelChange={(params) => { - onPageChange(params.page); - }} - /> -
- ); - - return ( - <> - {filterItems && Array.isArray(filterItems) && filterItems.length ? ( - - null} - > -
- <> - {filterItems && - filterItems.map((filterItem) => { - return ( -
-
-
- Filter -
- - {filters.map((selectOption) => ( - - ))} - -
- {filters.find( - (filter) => - filter.title === filterItem?.fields?.selectedField, - )?.type === 'enum' ? ( -
-
Value
- - - {filters - .find( - (filter) => - filter.title === - filterItem?.fields?.selectedField, - ) - ?.options?.map((option) => ( - - ))} - -
- ) : filters.find( - (filter) => - filter.title === - filterItem?.fields?.selectedField, - )?.number ? ( -
-
-
- From -
- -
-
-
- To -
- -
-
- ) : filters.find( - (filter) => - filter.title === - filterItem?.fields?.selectedField, - )?.date ? ( -
-
-
- From -
- -
-
-
- To -
- -
-
- ) : ( -
-
- Contains -
- -
- )} -
-
- Action -
- { - deleteFilter(filterItem.id); - }} - /> -
-
- ); - })} -
- - -
- -
-
-
- ) : null} - -

Are you sure you want to delete this item?

-
- - {dataGrid} - - {selectedRows.length > 0 && - createPortal( - onDeleteRows(selectedRows)} - />, - document.getElementById('delete-rows-button'), - )} - - - ); -}; - -export default TableSampleTaskcategory; diff --git a/frontend/src/components/Taskcategory/configureTaskcategoryCols.tsx b/frontend/src/components/Taskcategory/configureTaskcategoryCols.tsx deleted file mode 100644 index 59714cb..0000000 --- a/frontend/src/components/Taskcategory/configureTaskcategoryCols.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import React from 'react'; -import BaseIcon from '../BaseIcon'; -import { mdiEye, mdiTrashCan, mdiPencilOutline } from '@mdi/js'; -import axios from 'axios'; -import { - GridActionsCellItem, - GridRowParams, - GridValueGetterParams, -} from '@mui/x-data-grid'; -import ImageField from '../ImageField'; -import { saveFile } from '../../helpers/fileSaver'; -import dataFormatter from '../../helpers/dataFormatter'; -import DataGridMultiSelect from '../DataGridMultiSelect'; -import ListActionsPopover from '../ListActionsPopover'; - -import { hasPermission } from '../../helpers/userPermissions'; - -type Params = (id: string) => void; - -export const loadColumns = async ( - onDelete: Params, - entityName: string, - - user, -) => { - async function callOptionsApi(entityName: string) { - if (!hasPermission(user, 'READ_' + entityName.toUpperCase())) return []; - - try { - const data = await axios(`/${entityName}/autocomplete?limit=100`); - return data.data; - } catch (error) { - console.log(error); - return []; - } - } - - const hasUpdatePermission = hasPermission(user, 'UPDATE_TASKCATEGORY'); - - return [ - { - field: 'name', - headerName: 'Name', - flex: 1, - minWidth: 120, - filterable: false, - headerClassName: 'datagrid--header', - cellClassName: 'datagrid--cell', - - editable: hasUpdatePermission, - }, - - { - field: 'actions', - type: 'actions', - minWidth: 30, - headerClassName: 'datagrid--header', - cellClassName: 'datagrid--cell', - getActions: (params: GridRowParams) => { - return [ - , - ]; - }, - }, - ]; -}; diff --git a/frontend/src/components/WebPageComponents/Footer.tsx b/frontend/src/components/WebPageComponents/Footer.tsx index ab92e86..081158b 100644 --- a/frontend/src/components/WebPageComponents/Footer.tsx +++ b/frontend/src/components/WebPageComponents/Footer.tsx @@ -18,9 +18,9 @@ export default function WebSiteFooter({ const borders = useAppSelector((state) => state.style.borders); const websiteHeder = useAppSelector((state) => state.style.websiteHeder); - const style = FooterStyle.WITH_PAGES; + const style = FooterStyle.WITH_PROJECT_NAME; - const design = FooterDesigns.DEFAULT_DESIGN; + const design = FooterDesigns.DESIGN_DIVERSITY; return (
state.style.websiteHeder); const borders = useAppSelector((state) => state.style.borders); - const style = HeaderStyle.PAGES_RIGHT; + const style = HeaderStyle.PAGES_LEFT; - const design = HeaderDesigns.DEFAULT_DESIGN; + const design = HeaderDesigns.DESIGN_DIVERSITY; return (
{ const [roles, setRoles] = React.useState('Loading...'); const [permissions, setPermissions] = React.useState('Loading...'); const [organizations, setOrganizations] = React.useState('Loading...'); - const [taskcategory, setTaskcategory] = React.useState('Loading...'); const [widgetsRole, setWidgetsRole] = React.useState({ role: { value: '', label: '' }, @@ -50,7 +49,6 @@ const Dashboard = () => { 'roles', 'permissions', 'organizations', - 'taskcategory', ]; const fns = [ setUsers, @@ -60,7 +58,6 @@ const Dashboard = () => { setRoles, setPermissions, setOrganizations, - setTaskcategory, ]; const requests = entities.map((entity, index) => { @@ -392,38 +389,6 @@ const Dashboard = () => {
)} - - {hasPermission(currentUser, 'READ_TASKCATEGORY') && ( - -
-
-
-
- Taskcategory -
-
- {taskcategory} -
-
-
- -
-
-
- - )}
diff --git a/frontend/src/pages/index.tsx b/frontend/src/pages/index.tsx index cee3ad9..ebf398c 100644 --- a/frontend/src/pages/index.tsx +++ b/frontend/src/pages/index.tsx @@ -109,7 +109,7 @@ export default function WebSite() { { - <> -

Taskcategory organizations

- -
- - - - - - - - {organizations.taskcategory_organizations && - Array.isArray(organizations.taskcategory_organizations) && - organizations.taskcategory_organizations.map( - (item: any) => ( - - router.push( - `/taskcategory/taskcategory-view/?id=${item.id}`, - ) - } - > - - - ), - )} - -
Name
{item.name}
-
- {!organizations?.taskcategory_organizations?.length && ( -
No data
- )} -
- - { - const router = useRouter(); - const dispatch = useAppDispatch(); - const initVals = { - organizations: null, - - name: '', - }; - const [initialValues, setInitialValues] = useState(initVals); - - const { taskcategory } = useAppSelector((state) => state.taskcategory); - - const { currentUser } = useAppSelector((state) => state.auth); - - const { taskcategoryId } = router.query; - - useEffect(() => { - dispatch(fetch({ id: taskcategoryId })); - }, [taskcategoryId]); - - useEffect(() => { - if (typeof taskcategory === 'object') { - setInitialValues(taskcategory); - } - }, [taskcategory]); - - useEffect(() => { - if (typeof taskcategory === 'object') { - const newInitialVal = { ...initVals }; - - Object.keys(initVals).forEach( - (el) => (newInitialVal[el] = taskcategory[el]), - ); - - setInitialValues(newInitialVal); - } - }, [taskcategory]); - - const handleSubmit = async (data) => { - await dispatch(update({ id: taskcategoryId, data })); - await router.push('/taskcategory/taskcategory-list'); - }; - - return ( - <> - - {getPageTitle('Edit taskcategory')} - - - - {''} - - - handleSubmit(values)} - > -
- - - - - - - - - - - - - router.push('/taskcategory/taskcategory-list')} - /> - - -
-
-
- - ); -}; - -EditTaskcategory.getLayout = function getLayout(page: ReactElement) { - return ( - - {page} - - ); -}; - -export default EditTaskcategory; diff --git a/frontend/src/pages/taskcategory/taskcategory-edit.tsx b/frontend/src/pages/taskcategory/taskcategory-edit.tsx deleted file mode 100644 index a613ba2..0000000 --- a/frontend/src/pages/taskcategory/taskcategory-edit.tsx +++ /dev/null @@ -1,141 +0,0 @@ -import { mdiChartTimelineVariant, mdiUpload } from '@mdi/js'; -import Head from 'next/head'; -import React, { ReactElement, useEffect, useState } from 'react'; -import DatePicker from 'react-datepicker'; -import 'react-datepicker/dist/react-datepicker.css'; -import dayjs from 'dayjs'; - -import CardBox from '../../components/CardBox'; -import LayoutAuthenticated from '../../layouts/Authenticated'; -import SectionMain from '../../components/SectionMain'; -import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'; -import { getPageTitle } from '../../config'; - -import { Field, Form, Formik } from 'formik'; -import FormField from '../../components/FormField'; -import BaseDivider from '../../components/BaseDivider'; -import BaseButtons from '../../components/BaseButtons'; -import BaseButton from '../../components/BaseButton'; -import FormCheckRadio from '../../components/FormCheckRadio'; -import FormCheckRadioGroup from '../../components/FormCheckRadioGroup'; -import FormFilePicker from '../../components/FormFilePicker'; -import FormImagePicker from '../../components/FormImagePicker'; -import { SelectField } from '../../components/SelectField'; -import { SelectFieldMany } from '../../components/SelectFieldMany'; -import { SwitchField } from '../../components/SwitchField'; -import { RichTextField } from '../../components/RichTextField'; - -import { update, fetch } from '../../stores/taskcategory/taskcategorySlice'; -import { useAppDispatch, useAppSelector } from '../../stores/hooks'; -import { useRouter } from 'next/router'; -import { saveFile } from '../../helpers/fileSaver'; -import dataFormatter from '../../helpers/dataFormatter'; -import ImageField from '../../components/ImageField'; - -import { hasPermission } from '../../helpers/userPermissions'; - -const EditTaskcategoryPage = () => { - const router = useRouter(); - const dispatch = useAppDispatch(); - const initVals = { - organizations: null, - - name: '', - }; - const [initialValues, setInitialValues] = useState(initVals); - - const { taskcategory } = useAppSelector((state) => state.taskcategory); - - const { currentUser } = useAppSelector((state) => state.auth); - - const { id } = router.query; - - useEffect(() => { - dispatch(fetch({ id: id })); - }, [id]); - - useEffect(() => { - if (typeof taskcategory === 'object') { - setInitialValues(taskcategory); - } - }, [taskcategory]); - - useEffect(() => { - if (typeof taskcategory === 'object') { - const newInitialVal = { ...initVals }; - Object.keys(initVals).forEach( - (el) => (newInitialVal[el] = taskcategory[el]), - ); - setInitialValues(newInitialVal); - } - }, [taskcategory]); - - const handleSubmit = async (data) => { - await dispatch(update({ id: id, data })); - await router.push('/taskcategory/taskcategory-list'); - }; - - return ( - <> - - {getPageTitle('Edit taskcategory')} - - - - {''} - - - handleSubmit(values)} - > -
- - - - - - - - - - - - - router.push('/taskcategory/taskcategory-list')} - /> - - -
-
-
- - ); -}; - -EditTaskcategoryPage.getLayout = function getLayout(page: ReactElement) { - return ( - - {page} - - ); -}; - -export default EditTaskcategoryPage; diff --git a/frontend/src/pages/taskcategory/taskcategory-list.tsx b/frontend/src/pages/taskcategory/taskcategory-list.tsx deleted file mode 100644 index 38710a0..0000000 --- a/frontend/src/pages/taskcategory/taskcategory-list.tsx +++ /dev/null @@ -1,165 +0,0 @@ -import { mdiChartTimelineVariant } from '@mdi/js'; -import Head from 'next/head'; -import { uniqueId } from 'lodash'; -import React, { ReactElement, useState } from 'react'; -import CardBox from '../../components/CardBox'; -import LayoutAuthenticated from '../../layouts/Authenticated'; -import SectionMain from '../../components/SectionMain'; -import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'; -import { getPageTitle } from '../../config'; -import TableTaskcategory from '../../components/Taskcategory/TableTaskcategory'; -import BaseButton from '../../components/BaseButton'; -import axios from 'axios'; -import Link from 'next/link'; -import { useAppDispatch, useAppSelector } from '../../stores/hooks'; -import CardBoxModal from '../../components/CardBoxModal'; -import DragDropFilePicker from '../../components/DragDropFilePicker'; -import { - setRefetch, - uploadCsv, -} from '../../stores/taskcategory/taskcategorySlice'; - -import { hasPermission } from '../../helpers/userPermissions'; - -const TaskcategoryTablesPage = () => { - const [filterItems, setFilterItems] = useState([]); - const [csvFile, setCsvFile] = useState(null); - const [isModalActive, setIsModalActive] = useState(false); - const [showTableView, setShowTableView] = useState(false); - - const { currentUser } = useAppSelector((state) => state.auth); - - const dispatch = useAppDispatch(); - - const [filters] = useState([{ label: 'Name', title: 'name' }]); - - const hasCreatePermission = - currentUser && hasPermission(currentUser, 'CREATE_TASKCATEGORY'); - - const addFilter = () => { - const newItem = { - id: uniqueId(), - fields: { - filterValue: '', - filterValueFrom: '', - filterValueTo: '', - selectedField: '', - }, - }; - newItem.fields.selectedField = filters[0].title; - setFilterItems([...filterItems, newItem]); - }; - - const getTaskcategoryCSV = async () => { - const response = await axios({ - url: '/taskcategory?filetype=csv', - method: 'GET', - responseType: 'blob', - }); - const type = response.headers['content-type']; - const blob = new Blob([response.data], { type: type }); - const link = document.createElement('a'); - link.href = window.URL.createObjectURL(blob); - link.download = 'taskcategoryCSV.csv'; - link.click(); - }; - - const onModalConfirm = async () => { - if (!csvFile) return; - await dispatch(uploadCsv(csvFile)); - dispatch(setRefetch(true)); - setCsvFile(null); - setIsModalActive(false); - }; - - const onModalCancel = () => { - setCsvFile(null); - setIsModalActive(false); - }; - - return ( - <> - - {getPageTitle('Taskcategory')} - - - - {''} - - - {hasCreatePermission && ( - - )} - - - - - {hasCreatePermission && ( - setIsModalActive(true)} - /> - )} - -
-
-
-
- - - - -
- - - - - ); -}; - -TaskcategoryTablesPage.getLayout = function getLayout(page: ReactElement) { - return ( - - {page} - - ); -}; - -export default TaskcategoryTablesPage; diff --git a/frontend/src/pages/taskcategory/taskcategory-new.tsx b/frontend/src/pages/taskcategory/taskcategory-new.tsx deleted file mode 100644 index faf0e9a..0000000 --- a/frontend/src/pages/taskcategory/taskcategory-new.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import { - mdiAccount, - mdiChartTimelineVariant, - mdiMail, - mdiUpload, -} from '@mdi/js'; -import Head from 'next/head'; -import React, { ReactElement } from 'react'; -import CardBox from '../../components/CardBox'; -import LayoutAuthenticated from '../../layouts/Authenticated'; -import SectionMain from '../../components/SectionMain'; -import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'; -import { getPageTitle } from '../../config'; - -import { Field, Form, Formik } from 'formik'; -import FormField from '../../components/FormField'; -import BaseDivider from '../../components/BaseDivider'; -import BaseButtons from '../../components/BaseButtons'; -import BaseButton from '../../components/BaseButton'; -import FormCheckRadio from '../../components/FormCheckRadio'; -import FormCheckRadioGroup from '../../components/FormCheckRadioGroup'; -import FormFilePicker from '../../components/FormFilePicker'; -import FormImagePicker from '../../components/FormImagePicker'; -import { SwitchField } from '../../components/SwitchField'; - -import { SelectField } from '../../components/SelectField'; -import { SelectFieldMany } from '../../components/SelectFieldMany'; -import { RichTextField } from '../../components/RichTextField'; - -import { create } from '../../stores/taskcategory/taskcategorySlice'; -import { useAppDispatch } from '../../stores/hooks'; -import { useRouter } from 'next/router'; -import moment from 'moment'; - -const initialValues = { - organizations: '', - - name: '', -}; - -const TaskcategoryNew = () => { - const router = useRouter(); - const dispatch = useAppDispatch(); - - const handleSubmit = async (data) => { - await dispatch(create(data)); - await router.push('/taskcategory/taskcategory-list'); - }; - return ( - <> - - {getPageTitle('New Item')} - - - - {''} - - - handleSubmit(values)} - > -
- - - - - - - - - - - - - router.push('/taskcategory/taskcategory-list')} - /> - - -
-
-
- - ); -}; - -TaskcategoryNew.getLayout = function getLayout(page: ReactElement) { - return ( - - {page} - - ); -}; - -export default TaskcategoryNew; diff --git a/frontend/src/pages/taskcategory/taskcategory-table.tsx b/frontend/src/pages/taskcategory/taskcategory-table.tsx deleted file mode 100644 index 1d306ae..0000000 --- a/frontend/src/pages/taskcategory/taskcategory-table.tsx +++ /dev/null @@ -1,164 +0,0 @@ -import { mdiChartTimelineVariant } from '@mdi/js'; -import Head from 'next/head'; -import { uniqueId } from 'lodash'; -import React, { ReactElement, useState } from 'react'; -import CardBox from '../../components/CardBox'; -import LayoutAuthenticated from '../../layouts/Authenticated'; -import SectionMain from '../../components/SectionMain'; -import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'; -import { getPageTitle } from '../../config'; -import TableTaskcategory from '../../components/Taskcategory/TableTaskcategory'; -import BaseButton from '../../components/BaseButton'; -import axios from 'axios'; -import Link from 'next/link'; -import { useAppDispatch, useAppSelector } from '../../stores/hooks'; -import CardBoxModal from '../../components/CardBoxModal'; -import DragDropFilePicker from '../../components/DragDropFilePicker'; -import { - setRefetch, - uploadCsv, -} from '../../stores/taskcategory/taskcategorySlice'; - -import { hasPermission } from '../../helpers/userPermissions'; - -const TaskcategoryTablesPage = () => { - const [filterItems, setFilterItems] = useState([]); - const [csvFile, setCsvFile] = useState(null); - const [isModalActive, setIsModalActive] = useState(false); - const [showTableView, setShowTableView] = useState(false); - - const { currentUser } = useAppSelector((state) => state.auth); - - const dispatch = useAppDispatch(); - - const [filters] = useState([{ label: 'Name', title: 'name' }]); - - const hasCreatePermission = - currentUser && hasPermission(currentUser, 'CREATE_TASKCATEGORY'); - - const addFilter = () => { - const newItem = { - id: uniqueId(), - fields: { - filterValue: '', - filterValueFrom: '', - filterValueTo: '', - selectedField: '', - }, - }; - newItem.fields.selectedField = filters[0].title; - setFilterItems([...filterItems, newItem]); - }; - - const getTaskcategoryCSV = async () => { - const response = await axios({ - url: '/taskcategory?filetype=csv', - method: 'GET', - responseType: 'blob', - }); - const type = response.headers['content-type']; - const blob = new Blob([response.data], { type: type }); - const link = document.createElement('a'); - link.href = window.URL.createObjectURL(blob); - link.download = 'taskcategoryCSV.csv'; - link.click(); - }; - - const onModalConfirm = async () => { - if (!csvFile) return; - await dispatch(uploadCsv(csvFile)); - dispatch(setRefetch(true)); - setCsvFile(null); - setIsModalActive(false); - }; - - const onModalCancel = () => { - setCsvFile(null); - setIsModalActive(false); - }; - - return ( - <> - - {getPageTitle('Taskcategory')} - - - - {''} - - - {hasCreatePermission && ( - - )} - - - - - {hasCreatePermission && ( - setIsModalActive(true)} - /> - )} - -
-
-
-
- - - -
- - - - - ); -}; - -TaskcategoryTablesPage.getLayout = function getLayout(page: ReactElement) { - return ( - - {page} - - ); -}; - -export default TaskcategoryTablesPage; diff --git a/frontend/src/pages/taskcategory/taskcategory-view.tsx b/frontend/src/pages/taskcategory/taskcategory-view.tsx deleted file mode 100644 index ebbe488..0000000 --- a/frontend/src/pages/taskcategory/taskcategory-view.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import React, { ReactElement, useEffect } from 'react'; -import Head from 'next/head'; -import DatePicker from 'react-datepicker'; -import 'react-datepicker/dist/react-datepicker.css'; -import dayjs from 'dayjs'; -import { useAppDispatch, useAppSelector } from '../../stores/hooks'; -import { useRouter } from 'next/router'; -import { fetch } from '../../stores/taskcategory/taskcategorySlice'; -import { saveFile } from '../../helpers/fileSaver'; -import dataFormatter from '../../helpers/dataFormatter'; -import ImageField from '../../components/ImageField'; -import LayoutAuthenticated from '../../layouts/Authenticated'; -import { getPageTitle } from '../../config'; -import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'; -import SectionMain from '../../components/SectionMain'; -import CardBox from '../../components/CardBox'; -import BaseButton from '../../components/BaseButton'; -import BaseDivider from '../../components/BaseDivider'; -import { mdiChartTimelineVariant } from '@mdi/js'; -import { SwitchField } from '../../components/SwitchField'; -import FormField from '../../components/FormField'; - -import { hasPermission } from '../../helpers/userPermissions'; - -const TaskcategoryView = () => { - const router = useRouter(); - const dispatch = useAppDispatch(); - const { taskcategory } = useAppSelector((state) => state.taskcategory); - - const { currentUser } = useAppSelector((state) => state.auth); - - const { id } = router.query; - - function removeLastCharacter(str) { - console.log(str, `str`); - return str.slice(0, -1); - } - - useEffect(() => { - dispatch(fetch({ id })); - }, [dispatch, id]); - - return ( - <> - - {getPageTitle('View taskcategory')} - - - - - - -
-

organizations

- -

{taskcategory?.organizations?.name ?? 'No data'}

-
- -
-

Name

-

{taskcategory?.name}

-
- - - - router.push('/taskcategory/taskcategory-list')} - /> -
-
- - ); -}; - -TaskcategoryView.getLayout = function getLayout(page: ReactElement) { - return ( - - {page} - - ); -}; - -export default TaskcategoryView; diff --git a/frontend/src/pages/web_pages/services.tsx b/frontend/src/pages/web_pages/services.tsx index f9069b5..ce9af22 100644 --- a/frontend/src/pages/web_pages/services.tsx +++ b/frontend/src/pages/web_pages/services.tsx @@ -100,7 +100,7 @@ export default function WebSite() { { - const { id, query } = data; - const result = await axios.get( - `taskcategory${query || (id ? `/${id}` : '')}`, - ); - return id - ? result.data - : { rows: result.data.rows, count: result.data.count }; - }, -); - -export const deleteItemsByIds = createAsyncThunk( - 'taskcategory/deleteByIds', - async (data: any, { rejectWithValue }) => { - try { - await axios.post('taskcategory/deleteByIds', { data }); - } catch (error) { - if (!error.response) { - throw error; - } - - return rejectWithValue(error.response.data); - } - }, -); - -export const deleteItem = createAsyncThunk( - 'taskcategory/deleteTaskcategory', - async (id: string, { rejectWithValue }) => { - try { - await axios.delete(`taskcategory/${id}`); - } catch (error) { - if (!error.response) { - throw error; - } - - return rejectWithValue(error.response.data); - } - }, -); - -export const create = createAsyncThunk( - 'taskcategory/createTaskcategory', - async (data: any, { rejectWithValue }) => { - try { - const result = await axios.post('taskcategory', { data }); - return result.data; - } catch (error) { - if (!error.response) { - throw error; - } - - return rejectWithValue(error.response.data); - } - }, -); - -export const uploadCsv = createAsyncThunk( - 'taskcategory/uploadCsv', - async (file: File, { rejectWithValue }) => { - try { - const data = new FormData(); - data.append('file', file); - data.append('filename', file.name); - - const result = await axios.post('taskcategory/bulk-import', data, { - headers: { - 'Content-Type': 'multipart/form-data', - }, - }); - - return result.data; - } catch (error) { - if (!error.response) { - throw error; - } - - return rejectWithValue(error.response.data); - } - }, -); - -export const update = createAsyncThunk( - 'taskcategory/updateTaskcategory', - async (payload: any, { rejectWithValue }) => { - try { - const result = await axios.put(`taskcategory/${payload.id}`, { - id: payload.id, - data: payload.data, - }); - return result.data; - } catch (error) { - if (!error.response) { - throw error; - } - - return rejectWithValue(error.response.data); - } - }, -); - -export const taskcategorySlice = createSlice({ - name: 'taskcategory', - initialState, - reducers: { - setRefetch: (state, action: PayloadAction) => { - state.refetch = action.payload; - }, - }, - extraReducers: (builder) => { - builder.addCase(fetch.pending, (state) => { - state.loading = true; - resetNotify(state); - }); - builder.addCase(fetch.rejected, (state, action) => { - state.loading = false; - rejectNotify(state, action); - }); - - builder.addCase(fetch.fulfilled, (state, action) => { - if (action.payload.rows && action.payload.count >= 0) { - state.taskcategory = action.payload.rows; - state.count = action.payload.count; - } else { - state.taskcategory = action.payload; - } - state.loading = false; - }); - - builder.addCase(deleteItemsByIds.pending, (state) => { - state.loading = true; - resetNotify(state); - }); - - builder.addCase(deleteItemsByIds.fulfilled, (state) => { - state.loading = false; - fulfilledNotify(state, 'Taskcategory has been deleted'); - }); - - builder.addCase(deleteItemsByIds.rejected, (state, action) => { - state.loading = false; - rejectNotify(state, action); - }); - - builder.addCase(deleteItem.pending, (state) => { - state.loading = true; - resetNotify(state); - }); - - builder.addCase(deleteItem.fulfilled, (state) => { - state.loading = false; - fulfilledNotify(state, `${'Taskcategory'.slice(0, -1)} has been deleted`); - }); - - builder.addCase(deleteItem.rejected, (state, action) => { - state.loading = false; - rejectNotify(state, action); - }); - - builder.addCase(create.pending, (state) => { - state.loading = true; - resetNotify(state); - }); - builder.addCase(create.rejected, (state, action) => { - state.loading = false; - rejectNotify(state, action); - }); - - builder.addCase(create.fulfilled, (state) => { - state.loading = false; - fulfilledNotify(state, `${'Taskcategory'.slice(0, -1)} has been created`); - }); - - builder.addCase(update.pending, (state) => { - state.loading = true; - resetNotify(state); - }); - builder.addCase(update.fulfilled, (state) => { - state.loading = false; - fulfilledNotify(state, `${'Taskcategory'.slice(0, -1)} has been updated`); - }); - builder.addCase(update.rejected, (state, action) => { - state.loading = false; - rejectNotify(state, action); - }); - - builder.addCase(uploadCsv.pending, (state) => { - state.loading = true; - resetNotify(state); - }); - builder.addCase(uploadCsv.fulfilled, (state) => { - state.loading = false; - fulfilledNotify(state, 'Taskcategory has been uploaded'); - }); - builder.addCase(uploadCsv.rejected, (state, action) => { - state.loading = false; - rejectNotify(state, action); - }); - }, -}); - -// Action creators are generated for each case reducer function -export const { setRefetch } = taskcategorySlice.actions; - -export default taskcategorySlice.reducer;