diff --git a/.gitignore b/.gitignore
index e427ff3..35390a8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
+/backend/node_modules
+/frontend/node_modules
node_modules/
*/node_modules/
-*/build/
+**/node_modules/
+*/build/
\ No newline at end of file
diff --git a/502.html b/502.html
index 84e0dd6..d650847 100644
--- a/502.html
+++ b/502.html
@@ -129,8 +129,8 @@
The application is currently launching. The page will automatically refresh once site is
available.

CREATE DATABASE db_team_projects_hub;`
+ - `postgres=> CREATE DATABASE db_teamflow_manager;`
- Then give that new user privileges to the new database then quit the `psql`.
- - `postgres=> GRANT ALL PRIVILEGES ON DATABASE db_team_projects_hub TO admin;`
+ - `postgres=> GRANT ALL PRIVILEGES ON DATABASE db_teamflow_manager TO admin;`
- `postgres=> \q`
------------
diff --git a/backend/package.json b/backend/package.json
index 9c7733f..6b4568b 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -1,6 +1,6 @@
{
- "name": "teamprojectshub",
- "description": "Team Projects Hub - template backend",
+ "name": "teamflowmanager",
+ "description": "TeamFlow Manager - template backend",
"scripts": {
"start": "npm run db:migrate && npm run db:seed && npm run watch",
"db:migrate": "sequelize-cli db:migrate",
diff --git a/backend/src/ai/LocalAIApi.js b/backend/src/ai/LocalAIApi.js
new file mode 100644
index 0000000..fd571ae
--- /dev/null
+++ b/backend/src/ai/LocalAIApi.js
@@ -0,0 +1,484 @@
+"use strict";
+
+const fs = require("fs");
+const path = require("path");
+const http = require("http");
+const https = require("https");
+const { URL } = require("url");
+
+let CONFIG_CACHE = null;
+
+class LocalAIApi {
+ static createResponse(params, options) {
+ return createResponse(params, options);
+ }
+
+ static request(pathValue, payload, options) {
+ return request(pathValue, payload, options);
+ }
+
+ static fetchStatus(aiRequestId, options) {
+ return fetchStatus(aiRequestId, options);
+ }
+
+ static awaitResponse(aiRequestId, options) {
+ return awaitResponse(aiRequestId, options);
+ }
+
+ static extractText(response) {
+ return extractText(response);
+ }
+
+ static decodeJsonFromResponse(response) {
+ return decodeJsonFromResponse(response);
+ }
+}
+
+async function createResponse(params, options = {}) {
+ const payload = { ...(params || {}) };
+
+ if (!Array.isArray(payload.input) || payload.input.length === 0) {
+ return {
+ success: false,
+ error: "input_missing",
+ message: 'Parameter "input" is required and must be a non-empty array.',
+ };
+ }
+
+ const cfg = config();
+ if (!payload.model) {
+ payload.model = cfg.defaultModel;
+ }
+
+ const initial = await request(options.path, payload, options);
+ if (!initial.success) {
+ return initial;
+ }
+
+ const data = initial.data;
+ if (data && typeof data === "object" && data.ai_request_id) {
+ const pollTimeout = Number(options.poll_timeout ?? 300);
+ const pollInterval = Number(options.poll_interval ?? 5);
+ return await awaitResponse(data.ai_request_id, {
+ interval: pollInterval,
+ timeout: pollTimeout,
+ headers: options.headers,
+ timeout_per_call: options.timeout,
+ verify_tls: options.verify_tls,
+ });
+ }
+
+ return initial;
+}
+
+async function request(pathValue, payload = {}, options = {}) {
+ const cfg = config();
+ const resolvedPath = pathValue || options.path || cfg.responsesPath;
+
+ if (!resolvedPath) {
+ return {
+ success: false,
+ error: "project_id_missing",
+ message: "PROJECT_ID is not defined; cannot resolve AI proxy endpoint.",
+ };
+ }
+
+ if (!cfg.projectUuid) {
+ return {
+ success: false,
+ error: "project_uuid_missing",
+ message: "PROJECT_UUID is not defined; aborting AI request.",
+ };
+ }
+
+ const bodyPayload = { ...(payload || {}) };
+ if (!bodyPayload.project_uuid) {
+ bodyPayload.project_uuid = cfg.projectUuid;
+ }
+
+ const url = buildUrl(resolvedPath, cfg.baseUrl);
+ const timeout = resolveTimeout(options.timeout, cfg.timeout);
+ const verifyTls = resolveVerifyTls(options.verify_tls, cfg.verifyTls);
+
+ const headers = {
+ Accept: "application/json",
+ "Content-Type": "application/json",
+ [cfg.projectHeader]: cfg.projectUuid,
+ };
+ if (Array.isArray(options.headers)) {
+ for (const header of options.headers) {
+ if (typeof header === "string" && header.includes(":")) {
+ const [name, value] = header.split(":", 2);
+ headers[name.trim()] = value.trim();
+ }
+ }
+ }
+
+ const body = JSON.stringify(bodyPayload);
+ return sendRequest(url, "POST", body, headers, timeout, verifyTls);
+}
+
+async function fetchStatus(aiRequestId, options = {}) {
+ const cfg = config();
+ if (!cfg.projectUuid) {
+ return {
+ success: false,
+ error: "project_uuid_missing",
+ message: "PROJECT_UUID is not defined; aborting status check.",
+ };
+ }
+
+ const statusPath = resolveStatusPath(aiRequestId, cfg);
+ const url = buildUrl(statusPath, cfg.baseUrl);
+ const timeout = resolveTimeout(options.timeout, cfg.timeout);
+ const verifyTls = resolveVerifyTls(options.verify_tls, cfg.verifyTls);
+
+ const headers = {
+ Accept: "application/json",
+ [cfg.projectHeader]: cfg.projectUuid,
+ };
+ if (Array.isArray(options.headers)) {
+ for (const header of options.headers) {
+ if (typeof header === "string" && header.includes(":")) {
+ const [name, value] = header.split(":", 2);
+ headers[name.trim()] = value.trim();
+ }
+ }
+ }
+
+ return sendRequest(url, "GET", null, headers, timeout, verifyTls);
+}
+
+async function awaitResponse(aiRequestId, options = {}) {
+ const timeout = Number(options.timeout ?? 300);
+ const interval = Math.max(Number(options.interval ?? 5), 1);
+ const deadline = Date.now() + Math.max(timeout, interval) * 1000;
+
+ while (true) {
+ const statusResp = await fetchStatus(aiRequestId, {
+ headers: options.headers,
+ timeout: options.timeout_per_call,
+ verify_tls: options.verify_tls,
+ });
+
+ if (statusResp.success) {
+ const data = statusResp.data || {};
+ if (data && typeof data === "object") {
+ if (data.status === "success") {
+ return {
+ success: true,
+ status: 200,
+ data: data.response || data,
+ };
+ }
+ if (data.status === "failed") {
+ return {
+ success: false,
+ status: 500,
+ error: String(data.error || "AI request failed"),
+ data,
+ };
+ }
+ }
+ } else {
+ return statusResp;
+ }
+
+ if (Date.now() >= deadline) {
+ return {
+ success: false,
+ error: "timeout",
+ message: "Timed out waiting for AI response.",
+ };
+ }
+
+ await sleep(interval * 1000);
+ }
+}
+
+function extractText(response) {
+ const payload = response && typeof response === "object" ? response.data || response : null;
+ if (!payload || typeof payload !== "object") {
+ return "";
+ }
+
+ if (Array.isArray(payload.output)) {
+ let combined = "";
+ for (const item of payload.output) {
+ if (!item || !Array.isArray(item.content)) {
+ continue;
+ }
+ for (const block of item.content) {
+ if (
+ block &&
+ typeof block === "object" &&
+ block.type === "output_text" &&
+ typeof block.text === "string" &&
+ block.text.length > 0
+ ) {
+ combined += block.text;
+ }
+ }
+ }
+ if (combined) {
+ return combined;
+ }
+ }
+
+ if (
+ payload.choices &&
+ payload.choices[0] &&
+ payload.choices[0].message &&
+ typeof payload.choices[0].message.content === "string"
+ ) {
+ return payload.choices[0].message.content;
+ }
+
+ return "";
+}
+
+function decodeJsonFromResponse(response) {
+ const text = extractText(response);
+ if (!text) {
+ throw new Error("No text found in AI response.");
+ }
+
+ const parsed = parseJson(text);
+ if (parsed.ok && parsed.value && typeof parsed.value === "object") {
+ return parsed.value;
+ }
+
+ const stripped = stripJsonFence(text);
+ if (stripped !== text) {
+ const parsedStripped = parseJson(stripped);
+ if (parsedStripped.ok && parsedStripped.value && typeof parsedStripped.value === "object") {
+ return parsedStripped.value;
+ }
+ throw new Error(`JSON parse failed after stripping fences: ${parsedStripped.error}`);
+ }
+
+ throw new Error(`JSON parse failed: ${parsed.error}`);
+}
+
+function config() {
+ if (CONFIG_CACHE) {
+ return CONFIG_CACHE;
+ }
+
+ ensureEnvLoaded();
+
+ const baseUrl = process.env.AI_PROXY_BASE_URL || "https://flatlogic.com";
+ const projectId = process.env.PROJECT_ID || null;
+ let responsesPath = process.env.AI_RESPONSES_PATH || null;
+ if (!responsesPath && projectId) {
+ responsesPath = `/projects/${projectId}/ai-request`;
+ }
+
+ const timeout = resolveTimeout(process.env.AI_TIMEOUT, 30);
+ const verifyTls = resolveVerifyTls(process.env.AI_VERIFY_TLS, true);
+
+ CONFIG_CACHE = {
+ baseUrl,
+ responsesPath,
+ projectId,
+ projectUuid: process.env.PROJECT_UUID || null,
+ projectHeader: process.env.AI_PROJECT_HEADER || "project-uuid",
+ defaultModel: process.env.AI_DEFAULT_MODEL || "gpt-5-mini",
+ timeout,
+ verifyTls,
+ };
+
+ return CONFIG_CACHE;
+}
+
+function buildUrl(pathValue, baseUrl) {
+ const trimmed = String(pathValue || "").trim();
+ if (trimmed === "") {
+ return baseUrl;
+ }
+ if (trimmed.startsWith("http://") || trimmed.startsWith("https://")) {
+ return trimmed;
+ }
+ if (trimmed.startsWith("/")) {
+ return `${baseUrl}${trimmed}`;
+ }
+ return `${baseUrl}/${trimmed}`;
+}
+
+function resolveStatusPath(aiRequestId, cfg) {
+ const basePath = (cfg.responsesPath || "").replace(/\/+$/, "");
+ if (!basePath) {
+ return `/ai-request/${encodeURIComponent(String(aiRequestId))}/status`;
+ }
+ const normalized = basePath.endsWith("/ai-request") ? basePath : `${basePath}/ai-request`;
+ return `${normalized}/${encodeURIComponent(String(aiRequestId))}/status`;
+}
+
+function sendRequest(urlString, method, body, headers, timeoutSeconds, verifyTls) {
+ return new Promise((resolve) => {
+ let targetUrl;
+ try {
+ targetUrl = new URL(urlString);
+ } catch (err) {
+ resolve({
+ success: false,
+ error: "invalid_url",
+ message: err.message,
+ });
+ return;
+ }
+
+ const isHttps = targetUrl.protocol === "https:";
+ const requestFn = isHttps ? https.request : http.request;
+ const options = {
+ protocol: targetUrl.protocol,
+ hostname: targetUrl.hostname,
+ port: targetUrl.port || (isHttps ? 443 : 80),
+ path: `${targetUrl.pathname}${targetUrl.search}`,
+ method: method.toUpperCase(),
+ headers,
+ timeout: Math.max(Number(timeoutSeconds || 30), 1) * 1000,
+ };
+ if (isHttps) {
+ options.rejectUnauthorized = Boolean(verifyTls);
+ }
+
+ const req = requestFn(options, (res) => {
+ let responseBody = "";
+ res.setEncoding("utf8");
+ res.on("data", (chunk) => {
+ responseBody += chunk;
+ });
+ res.on("end", () => {
+ const status = res.statusCode || 0;
+ const parsed = parseJson(responseBody);
+ const payload = parsed.ok ? parsed.value : responseBody;
+
+ if (status >= 200 && status < 300) {
+ const result = {
+ success: true,
+ status,
+ data: payload,
+ };
+ if (!parsed.ok) {
+ result.json_error = parsed.error;
+ }
+ resolve(result);
+ return;
+ }
+
+ const errorMessage =
+ parsed.ok && payload && typeof payload === "object"
+ ? String(payload.error || payload.message || "AI proxy request failed")
+ : String(responseBody || "AI proxy request failed");
+
+ resolve({
+ success: false,
+ status,
+ error: errorMessage,
+ response: payload,
+ json_error: parsed.ok ? undefined : parsed.error,
+ });
+ });
+ });
+
+ req.on("timeout", () => {
+ req.destroy(new Error("request_timeout"));
+ });
+
+ req.on("error", (err) => {
+ resolve({
+ success: false,
+ error: "request_failed",
+ message: err.message,
+ });
+ });
+
+ if (body) {
+ req.write(body);
+ }
+ req.end();
+ });
+}
+
+function parseJson(value) {
+ if (typeof value !== "string" || value.trim() === "") {
+ return { ok: false, error: "empty_response" };
+ }
+ try {
+ return { ok: true, value: JSON.parse(value) };
+ } catch (err) {
+ return { ok: false, error: err.message };
+ }
+}
+
+function stripJsonFence(text) {
+ const trimmed = text.trim();
+ if (trimmed.startsWith("```json")) {
+ return trimmed.replace(/^```json/, "").replace(/```$/, "").trim();
+ }
+ if (trimmed.startsWith("```")) {
+ return trimmed.replace(/^```/, "").replace(/```$/, "").trim();
+ }
+ return text;
+}
+
+function resolveTimeout(value, fallback) {
+ const parsed = Number.parseInt(String(value ?? fallback), 10);
+ return Number.isNaN(parsed) ? Number(fallback) : parsed;
+}
+
+function resolveVerifyTls(value, fallback) {
+ if (value === undefined || value === null) {
+ return Boolean(fallback);
+ }
+ return String(value).toLowerCase() !== "false" && String(value) !== "0";
+}
+
+function ensureEnvLoaded() {
+ if (process.env.PROJECT_UUID && process.env.PROJECT_ID) {
+ return;
+ }
+
+ const envPath = path.resolve(__dirname, "../../../../.env");
+ if (!fs.existsSync(envPath)) {
+ return;
+ }
+
+ let content;
+ try {
+ content = fs.readFileSync(envPath, "utf8");
+ } catch (err) {
+ throw new Error(`Failed to read executor .env: ${err.message}`);
+ }
+
+ for (const line of content.split(/\r?\n/)) {
+ const trimmed = line.trim();
+ if (!trimmed || trimmed.startsWith("#") || !trimmed.includes("=")) {
+ continue;
+ }
+ const [rawKey, ...rest] = trimmed.split("=");
+ const key = rawKey.trim();
+ if (!key) {
+ continue;
+ }
+ const value = rest.join("=").trim().replace(/^['"]|['"]$/g, "");
+ if (!process.env[key]) {
+ process.env[key] = value;
+ }
+ }
+}
+
+function sleep(ms) {
+ return new Promise((resolve) => setTimeout(resolve, ms));
+}
+
+module.exports = {
+ LocalAIApi,
+ createResponse,
+ request,
+ fetchStatus,
+ awaitResponse,
+ extractText,
+ decodeJsonFromResponse,
+};
diff --git a/backend/src/config.js b/backend/src/config.js
index 79f9d5d..54ebf45 100644
--- a/backend/src/config.js
+++ b/backend/src/config.js
@@ -11,15 +11,15 @@ const config = {
bcrypt: {
saltRounds: 12
},
- admin_pass: "d02fa926",
- user_pass: "b27b3ff8dc07",
+ admin_pass: "156fca4c",
+ user_pass: "94f5514e3457",
admin_email: "admin@flatlogic.com",
providers: {
LOCAL: 'local',
GOOGLE: 'google',
MICROSOFT: 'microsoft'
},
- secret_key: process.env.SECRET_KEY || 'd02fa926-6491-481e-a115-b27b3ff8dc07',
+ secret_key: process.env.SECRET_KEY || '156fca4c-57d0-4fe3-8a0f-94f5514e3457',
remote: '',
port: process.env.NODE_ENV === "production" ? "" : "8080",
hostUI: process.env.NODE_ENV === "production" ? "" : "http://localhost",
@@ -39,7 +39,7 @@ const config = {
},
uploadDir: os.tmpdir(),
email: {
- from: 'Team Projects Hub
',
+ from: 'TeamFlow Manager ',
host: 'email-smtp.us-east-1.amazonaws.com',
port: 587,
auth: {
@@ -60,7 +60,7 @@ const config = {
},
- project_uuid: 'd02fa926-6491-481e-a115-b27b3ff8dc07',
+ project_uuid: '156fca4c-57d0-4fe3-8a0f-94f5514e3457',
flHost: process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'dev_stage' ? 'https://flatlogic.com/projects' : 'http://localhost:3000/projects',
diff --git a/backend/src/db/api/attachments.js b/backend/src/db/api/attachments.js
deleted file mode 100644
index bd706ee..0000000
--- a/backend/src/db/api/attachments.js
+++ /dev/null
@@ -1,490 +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 AttachmentsDBApi {
-
-
-
- static async create(data, options) {
- const currentUser = (options && options.currentUser) || { id: null };
- const transaction = (options && options.transaction) || undefined;
-
- const attachments = await db.attachments.create(
- {
- id: data.id || undefined,
-
- caption: data.caption
- ||
- null
- ,
-
- uploaded_on: data.uploaded_on
- ||
- null
- ,
-
- importHash: data.importHash || null,
- createdById: currentUser.id,
- updatedById: currentUser.id,
- },
- { transaction },
- );
-
-
- await attachments.setTask( data.task || null, {
- transaction,
- });
-
- await attachments.setUploaded_by( data.uploaded_by || null, {
- transaction,
- });
-
-
-
-
-
- await FileDBApi.replaceRelationFiles(
- {
- belongsTo: db.attachments.getTableName(),
- belongsToColumn: 'file',
- belongsToId: attachments.id,
- },
- data.file,
- options,
- );
-
-
- return attachments;
- }
-
-
- 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 attachmentsData = data.map((item, index) => ({
- id: item.id || undefined,
-
- caption: item.caption
- ||
- null
- ,
-
- uploaded_on: item.uploaded_on
- ||
- null
- ,
-
- importHash: item.importHash || null,
- createdById: currentUser.id,
- updatedById: currentUser.id,
- createdAt: new Date(Date.now() + index * 1000),
- }));
-
- // Bulk create items
- const attachments = await db.attachments.bulkCreate(attachmentsData, { transaction });
-
- // For each item created, replace relation files
-
- for (let i = 0; i < attachments.length; i++) {
- await FileDBApi.replaceRelationFiles(
- {
- belongsTo: db.attachments.getTableName(),
- belongsToColumn: 'file',
- belongsToId: attachments[i].id,
- },
- data[i].file,
- options,
- );
- }
-
-
- return attachments;
- }
-
- static async update(id, data, options) {
- const currentUser = (options && options.currentUser) || {id: null};
- const transaction = (options && options.transaction) || undefined;
-
-
- const attachments = await db.attachments.findByPk(id, {}, {transaction});
-
-
-
-
- const updatePayload = {};
-
- if (data.caption !== undefined) updatePayload.caption = data.caption;
-
-
- if (data.uploaded_on !== undefined) updatePayload.uploaded_on = data.uploaded_on;
-
-
- updatePayload.updatedById = currentUser.id;
-
- await attachments.update(updatePayload, {transaction});
-
-
-
- if (data.task !== undefined) {
- await attachments.setTask(
-
- data.task,
-
- { transaction }
- );
- }
-
- if (data.uploaded_by !== undefined) {
- await attachments.setUploaded_by(
-
- data.uploaded_by,
-
- { transaction }
- );
- }
-
-
-
-
-
-
- await FileDBApi.replaceRelationFiles(
- {
- belongsTo: db.attachments.getTableName(),
- belongsToColumn: 'file',
- belongsToId: attachments.id,
- },
- data.file,
- options,
- );
-
-
- return attachments;
- }
-
- static async deleteByIds(ids, options) {
- const currentUser = (options && options.currentUser) || { id: null };
- const transaction = (options && options.transaction) || undefined;
-
- const attachments = await db.attachments.findAll({
- where: {
- id: {
- [Op.in]: ids,
- },
- },
- transaction,
- });
-
- await db.sequelize.transaction(async (transaction) => {
- for (const record of attachments) {
- await record.update(
- {deletedBy: currentUser.id},
- {transaction}
- );
- }
- for (const record of attachments) {
- await record.destroy({transaction});
- }
- });
-
-
- return attachments;
- }
-
- static async remove(id, options) {
- const currentUser = (options && options.currentUser) || {id: null};
- const transaction = (options && options.transaction) || undefined;
-
- const attachments = await db.attachments.findByPk(id, options);
-
- await attachments.update({
- deletedBy: currentUser.id
- }, {
- transaction,
- });
-
- await attachments.destroy({
- transaction
- });
-
- return attachments;
- }
-
- static async findBy(where, options) {
- const transaction = (options && options.transaction) || undefined;
-
- const attachments = await db.attachments.findOne(
- { where },
- { transaction },
- );
-
- if (!attachments) {
- return attachments;
- }
-
- const output = attachments.get({plain: true});
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- output.task = await attachments.getTask({
- transaction
- });
-
-
- output.uploaded_by = await attachments.getUploaded_by({
- transaction
- });
-
-
- output.file = await attachments.getFile({
- transaction
- });
-
-
-
- return output;
- }
-
- static async findAll(
- filter,
- options
- ) {
- const limit = filter.limit || 0;
- let offset = 0;
- let where = {};
- const currentPage = +filter.page;
-
-
-
-
-
- offset = currentPage * limit;
-
- const orderBy = null;
-
- const transaction = (options && options.transaction) || undefined;
-
- let include = [
-
- {
- model: db.tasks,
- as: 'task',
-
- where: filter.task ? {
- [Op.or]: [
- { id: { [Op.in]: filter.task.split('|').map(term => Utils.uuid(term)) } },
- {
- title: {
- [Op.or]: filter.task.split('|').map(term => ({ [Op.iLike]: `%${term}%` }))
- }
- },
- ]
- } : {},
-
- },
-
- {
- model: db.users,
- as: 'uploaded_by',
-
- where: filter.uploaded_by ? {
- [Op.or]: [
- { id: { [Op.in]: filter.uploaded_by.split('|').map(term => Utils.uuid(term)) } },
- {
- firstName: {
- [Op.or]: filter.uploaded_by.split('|').map(term => ({ [Op.iLike]: `%${term}%` }))
- }
- },
- ]
- } : {},
-
- },
-
-
-
- {
- model: db.file,
- as: 'file',
- },
-
- ];
-
- if (filter) {
- if (filter.id) {
- where = {
- ...where,
- ['id']: Utils.uuid(filter.id),
- };
- }
-
-
- if (filter.caption) {
- where = {
- ...where,
- [Op.and]: Utils.ilike(
- 'attachments',
- 'caption',
- filter.caption,
- ),
- };
- }
-
-
-
-
-
-
- if (filter.uploaded_onRange) {
- const [start, end] = filter.uploaded_onRange;
-
- if (start !== undefined && start !== null && start !== '') {
- where = {
- ...where,
- uploaded_on: {
- ...where.uploaded_on,
- [Op.gte]: start,
- },
- };
- }
-
- if (end !== undefined && end !== null && end !== '') {
- where = {
- ...where,
- uploaded_on: {
- ...where.uploaded_on,
- [Op.lte]: end,
- },
- };
- }
- }
-
-
- if (filter.active !== undefined) {
- where = {
- ...where,
- active: filter.active === true || filter.active === 'true'
- };
- }
-
-
-
-
-
-
-
-
-
-
- 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,
- },
- };
- }
- }
- }
-
-
-
-
- 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.attachments.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, ) {
- let where = {};
-
-
-
- if (query) {
- where = {
- [Op.or]: [
- { ['id']: Utils.uuid(query) },
- Utils.ilike(
- 'attachments',
- 'caption',
- query,
- ),
- ],
- };
- }
-
- const records = await db.attachments.findAll({
- attributes: [ 'id', 'caption' ],
- where,
- limit: limit ? Number(limit) : undefined,
- offset: offset ? Number(offset) : undefined,
- orderBy: [['caption', 'ASC']],
- });
-
- return records.map((record) => ({
- id: record.id,
- label: record.caption,
- }));
- }
-
-
-};
-
diff --git a/backend/src/db/api/comments.js b/backend/src/db/api/comments.js
deleted file mode 100644
index 761ea47..0000000
--- a/backend/src/db/api/comments.js
+++ /dev/null
@@ -1,448 +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 CommentsDBApi {
-
-
-
- static async create(data, options) {
- const currentUser = (options && options.currentUser) || { id: null };
- const transaction = (options && options.transaction) || undefined;
-
- const comments = await db.comments.create(
- {
- id: data.id || undefined,
-
- content: data.content
- ||
- null
- ,
-
- created_on: data.created_on
- ||
- null
- ,
-
- importHash: data.importHash || null,
- createdById: currentUser.id,
- updatedById: currentUser.id,
- },
- { transaction },
- );
-
-
- await comments.setTask( data.task || null, {
- transaction,
- });
-
- await comments.setAuthor( data.author || null, {
- transaction,
- });
-
-
-
-
-
-
- return comments;
- }
-
-
- 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 commentsData = data.map((item, index) => ({
- id: item.id || undefined,
-
- content: item.content
- ||
- null
- ,
-
- created_on: item.created_on
- ||
- null
- ,
-
- importHash: item.importHash || null,
- createdById: currentUser.id,
- updatedById: currentUser.id,
- createdAt: new Date(Date.now() + index * 1000),
- }));
-
- // Bulk create items
- const comments = await db.comments.bulkCreate(commentsData, { transaction });
-
- // For each item created, replace relation files
-
-
- return comments;
- }
-
- static async update(id, data, options) {
- const currentUser = (options && options.currentUser) || {id: null};
- const transaction = (options && options.transaction) || undefined;
-
-
- const comments = await db.comments.findByPk(id, {}, {transaction});
-
-
-
-
- const updatePayload = {};
-
- if (data.content !== undefined) updatePayload.content = data.content;
-
-
- if (data.created_on !== undefined) updatePayload.created_on = data.created_on;
-
-
- updatePayload.updatedById = currentUser.id;
-
- await comments.update(updatePayload, {transaction});
-
-
-
- if (data.task !== undefined) {
- await comments.setTask(
-
- data.task,
-
- { transaction }
- );
- }
-
- if (data.author !== undefined) {
- await comments.setAuthor(
-
- data.author,
-
- { transaction }
- );
- }
-
-
-
-
-
-
-
- return comments;
- }
-
- static async deleteByIds(ids, options) {
- const currentUser = (options && options.currentUser) || { id: null };
- const transaction = (options && options.transaction) || undefined;
-
- const comments = await db.comments.findAll({
- where: {
- id: {
- [Op.in]: ids,
- },
- },
- transaction,
- });
-
- await db.sequelize.transaction(async (transaction) => {
- for (const record of comments) {
- await record.update(
- {deletedBy: currentUser.id},
- {transaction}
- );
- }
- for (const record of comments) {
- await record.destroy({transaction});
- }
- });
-
-
- return comments;
- }
-
- static async remove(id, options) {
- const currentUser = (options && options.currentUser) || {id: null};
- const transaction = (options && options.transaction) || undefined;
-
- const comments = await db.comments.findByPk(id, options);
-
- await comments.update({
- deletedBy: currentUser.id
- }, {
- transaction,
- });
-
- await comments.destroy({
- transaction
- });
-
- return comments;
- }
-
- static async findBy(where, options) {
- const transaction = (options && options.transaction) || undefined;
-
- const comments = await db.comments.findOne(
- { where },
- { transaction },
- );
-
- if (!comments) {
- return comments;
- }
-
- const output = comments.get({plain: true});
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- output.task = await comments.getTask({
- transaction
- });
-
-
- output.author = await comments.getAuthor({
- transaction
- });
-
-
-
- return output;
- }
-
- static async findAll(
- filter,
- options
- ) {
- const limit = filter.limit || 0;
- let offset = 0;
- let where = {};
- const currentPage = +filter.page;
-
-
-
-
-
- offset = currentPage * limit;
-
- const orderBy = null;
-
- const transaction = (options && options.transaction) || undefined;
-
- let include = [
-
- {
- model: db.tasks,
- as: 'task',
-
- where: filter.task ? {
- [Op.or]: [
- { id: { [Op.in]: filter.task.split('|').map(term => Utils.uuid(term)) } },
- {
- title: {
- [Op.or]: filter.task.split('|').map(term => ({ [Op.iLike]: `%${term}%` }))
- }
- },
- ]
- } : {},
-
- },
-
- {
- model: db.users,
- as: 'author',
-
- where: filter.author ? {
- [Op.or]: [
- { id: { [Op.in]: filter.author.split('|').map(term => Utils.uuid(term)) } },
- {
- firstName: {
- [Op.or]: filter.author.split('|').map(term => ({ [Op.iLike]: `%${term}%` }))
- }
- },
- ]
- } : {},
-
- },
-
-
-
- ];
-
- if (filter) {
- if (filter.id) {
- where = {
- ...where,
- ['id']: Utils.uuid(filter.id),
- };
- }
-
-
- if (filter.content) {
- where = {
- ...where,
- [Op.and]: Utils.ilike(
- 'comments',
- 'content',
- filter.content,
- ),
- };
- }
-
-
-
-
-
-
- if (filter.created_onRange) {
- const [start, end] = filter.created_onRange;
-
- if (start !== undefined && start !== null && start !== '') {
- where = {
- ...where,
- created_on: {
- ...where.created_on,
- [Op.gte]: start,
- },
- };
- }
-
- if (end !== undefined && end !== null && end !== '') {
- where = {
- ...where,
- created_on: {
- ...where.created_on,
- [Op.lte]: end,
- },
- };
- }
- }
-
-
- if (filter.active !== undefined) {
- where = {
- ...where,
- active: filter.active === true || filter.active === 'true'
- };
- }
-
-
-
-
-
-
-
-
-
-
- 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,
- },
- };
- }
- }
- }
-
-
-
-
- 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.comments.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, ) {
- let where = {};
-
-
-
- if (query) {
- where = {
- [Op.or]: [
- { ['id']: Utils.uuid(query) },
- Utils.ilike(
- 'comments',
- 'content',
- query,
- ),
- ],
- };
- }
-
- const records = await db.comments.findAll({
- attributes: [ 'id', 'content' ],
- where,
- limit: limit ? Number(limit) : undefined,
- offset: offset ? Number(offset) : undefined,
- orderBy: [['content', 'ASC']],
- });
-
- return records.map((record) => ({
- id: record.id,
- label: record.content,
- }));
- }
-
-
-};
-
diff --git a/backend/src/db/api/notifications.js b/backend/src/db/api/notifications.js
deleted file mode 100644
index 5a5fe28..0000000
--- a/backend/src/db/api/notifications.js
+++ /dev/null
@@ -1,470 +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 NotificationsDBApi {
-
-
-
- static async create(data, options) {
- const currentUser = (options && options.currentUser) || { id: null };
- const transaction = (options && options.transaction) || undefined;
-
- const notifications = await db.notifications.create(
- {
- id: data.id || undefined,
-
- message: data.message
- ||
- null
- ,
-
- read: data.read
- ||
- false
-
- ,
-
- sent_at: data.sent_at
- ||
- null
- ,
-
- importHash: data.importHash || null,
- createdById: currentUser.id,
- updatedById: currentUser.id,
- },
- { transaction },
- );
-
-
- await notifications.setRecipient( data.recipient || null, {
- transaction,
- });
-
- await notifications.setRelated_task( data.related_task || null, {
- transaction,
- });
-
-
-
-
-
-
- return notifications;
- }
-
-
- 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 notificationsData = data.map((item, index) => ({
- id: item.id || undefined,
-
- message: item.message
- ||
- null
- ,
-
- read: item.read
- ||
- false
-
- ,
-
- sent_at: item.sent_at
- ||
- null
- ,
-
- importHash: item.importHash || null,
- createdById: currentUser.id,
- updatedById: currentUser.id,
- createdAt: new Date(Date.now() + index * 1000),
- }));
-
- // Bulk create items
- const notifications = await db.notifications.bulkCreate(notificationsData, { transaction });
-
- // For each item created, replace relation files
-
-
- return notifications;
- }
-
- static async update(id, data, options) {
- const currentUser = (options && options.currentUser) || {id: null};
- const transaction = (options && options.transaction) || undefined;
-
-
- const notifications = await db.notifications.findByPk(id, {}, {transaction});
-
-
-
-
- const updatePayload = {};
-
- if (data.message !== undefined) updatePayload.message = data.message;
-
-
- if (data.read !== undefined) updatePayload.read = data.read;
-
-
- if (data.sent_at !== undefined) updatePayload.sent_at = data.sent_at;
-
-
- updatePayload.updatedById = currentUser.id;
-
- await notifications.update(updatePayload, {transaction});
-
-
-
- if (data.recipient !== undefined) {
- await notifications.setRecipient(
-
- data.recipient,
-
- { transaction }
- );
- }
-
- if (data.related_task !== undefined) {
- await notifications.setRelated_task(
-
- data.related_task,
-
- { transaction }
- );
- }
-
-
-
-
-
-
-
- return notifications;
- }
-
- static async deleteByIds(ids, options) {
- const currentUser = (options && options.currentUser) || { id: null };
- const transaction = (options && options.transaction) || undefined;
-
- const notifications = await db.notifications.findAll({
- where: {
- id: {
- [Op.in]: ids,
- },
- },
- transaction,
- });
-
- await db.sequelize.transaction(async (transaction) => {
- for (const record of notifications) {
- await record.update(
- {deletedBy: currentUser.id},
- {transaction}
- );
- }
- for (const record of notifications) {
- await record.destroy({transaction});
- }
- });
-
-
- return notifications;
- }
-
- static async remove(id, options) {
- const currentUser = (options && options.currentUser) || {id: null};
- const transaction = (options && options.transaction) || undefined;
-
- const notifications = await db.notifications.findByPk(id, options);
-
- await notifications.update({
- deletedBy: currentUser.id
- }, {
- transaction,
- });
-
- await notifications.destroy({
- transaction
- });
-
- return notifications;
- }
-
- static async findBy(where, options) {
- const transaction = (options && options.transaction) || undefined;
-
- const notifications = await db.notifications.findOne(
- { where },
- { transaction },
- );
-
- if (!notifications) {
- return notifications;
- }
-
- const output = notifications.get({plain: true});
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- output.recipient = await notifications.getRecipient({
- transaction
- });
-
-
- output.related_task = await notifications.getRelated_task({
- transaction
- });
-
-
-
- return output;
- }
-
- static async findAll(
- filter,
- options
- ) {
- const limit = filter.limit || 0;
- let offset = 0;
- let where = {};
- const currentPage = +filter.page;
-
-
-
-
-
- offset = currentPage * limit;
-
- const orderBy = null;
-
- const transaction = (options && options.transaction) || undefined;
-
- let include = [
-
- {
- model: db.users,
- as: 'recipient',
-
- where: filter.recipient ? {
- [Op.or]: [
- { id: { [Op.in]: filter.recipient.split('|').map(term => Utils.uuid(term)) } },
- {
- firstName: {
- [Op.or]: filter.recipient.split('|').map(term => ({ [Op.iLike]: `%${term}%` }))
- }
- },
- ]
- } : {},
-
- },
-
- {
- model: db.tasks,
- as: 'related_task',
-
- where: filter.related_task ? {
- [Op.or]: [
- { id: { [Op.in]: filter.related_task.split('|').map(term => Utils.uuid(term)) } },
- {
- title: {
- [Op.or]: filter.related_task.split('|').map(term => ({ [Op.iLike]: `%${term}%` }))
- }
- },
- ]
- } : {},
-
- },
-
-
-
- ];
-
- if (filter) {
- if (filter.id) {
- where = {
- ...where,
- ['id']: Utils.uuid(filter.id),
- };
- }
-
-
- if (filter.message) {
- where = {
- ...where,
- [Op.and]: Utils.ilike(
- 'notifications',
- 'message',
- filter.message,
- ),
- };
- }
-
-
-
-
-
-
- if (filter.sent_atRange) {
- const [start, end] = filter.sent_atRange;
-
- if (start !== undefined && start !== null && start !== '') {
- where = {
- ...where,
- sent_at: {
- ...where.sent_at,
- [Op.gte]: start,
- },
- };
- }
-
- if (end !== undefined && end !== null && end !== '') {
- where = {
- ...where,
- sent_at: {
- ...where.sent_at,
- [Op.lte]: end,
- },
- };
- }
- }
-
-
- if (filter.active !== undefined) {
- where = {
- ...where,
- active: filter.active === true || filter.active === 'true'
- };
- }
-
-
- if (filter.read) {
- where = {
- ...where,
- read: filter.read,
- };
- }
-
-
-
-
-
-
-
-
-
- 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,
- },
- };
- }
- }
- }
-
-
-
-
- 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.notifications.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, ) {
- let where = {};
-
-
-
- if (query) {
- where = {
- [Op.or]: [
- { ['id']: Utils.uuid(query) },
- Utils.ilike(
- 'notifications',
- 'message',
- query,
- ),
- ],
- };
- }
-
- const records = await db.notifications.findAll({
- attributes: [ 'id', 'message' ],
- where,
- limit: limit ? Number(limit) : undefined,
- offset: offset ? Number(offset) : undefined,
- orderBy: [['message', 'ASC']],
- });
-
- return records.map((record) => ({
- id: record.id,
- label: record.message,
- }));
- }
-
-
-};
-
diff --git a/backend/src/db/api/permissions.js b/backend/src/db/api/permissions.js
index 813685b..daceb98 100644
--- a/backend/src/db/api/permissions.js
+++ b/backend/src/db/api/permissions.js
@@ -172,10 +172,6 @@ module.exports = class PermissionsDBApi {
-
-
-
-
return output;
}
diff --git a/backend/src/db/api/projects.js b/backend/src/db/api/projects.js
index 5764cd7..bb9eaa4 100644
--- a/backend/src/db/api/projects.js
+++ b/backend/src/db/api/projects.js
@@ -31,6 +31,11 @@ module.exports = class ProjectsDBApi {
null
,
+ status: data.status
+ ||
+ null
+ ,
+
start_date: data.start_date
||
null
@@ -41,18 +46,8 @@ module.exports = class ProjectsDBApi {
null
,
- status: data.status
- ||
- null
- ,
-
budget: data.budget
||
- null
- ,
-
- progress: data.progress
- ||
null
,
@@ -76,6 +71,16 @@ module.exports = class ProjectsDBApi {
+ await FileDBApi.replaceRelationFiles(
+ {
+ belongsTo: db.projects.getTableName(),
+ belongsToColumn: 'attachments',
+ belongsToId: projects.id,
+ },
+ data.attachments,
+ options,
+ );
+
return projects;
}
@@ -97,6 +102,11 @@ module.exports = class ProjectsDBApi {
description: item.description
||
null
+ ,
+
+ status: item.status
+ ||
+ null
,
start_date: item.start_date
@@ -107,21 +117,11 @@ module.exports = class ProjectsDBApi {
end_date: item.end_date
||
null
- ,
-
- status: item.status
- ||
- null
,
budget: item.budget
||
null
- ,
-
- progress: item.progress
- ||
- null
,
importHash: item.importHash || null,
@@ -135,6 +135,18 @@ module.exports = class ProjectsDBApi {
// For each item created, replace relation files
+ for (let i = 0; i < projects.length; i++) {
+ await FileDBApi.replaceRelationFiles(
+ {
+ belongsTo: db.projects.getTableName(),
+ belongsToColumn: 'attachments',
+ belongsToId: projects[i].id,
+ },
+ data[i].attachments,
+ options,
+ );
+ }
+
return projects;
}
@@ -157,21 +169,18 @@ module.exports = class ProjectsDBApi {
if (data.description !== undefined) updatePayload.description = data.description;
+ if (data.status !== undefined) updatePayload.status = data.status;
+
+
if (data.start_date !== undefined) updatePayload.start_date = data.start_date;
if (data.end_date !== undefined) updatePayload.end_date = data.end_date;
- if (data.status !== undefined) updatePayload.status = data.status;
-
-
if (data.budget !== undefined) updatePayload.budget = data.budget;
- if (data.progress !== undefined) updatePayload.progress = data.progress;
-
-
updatePayload.updatedById = currentUser.id;
await projects.update(updatePayload, {transaction});
@@ -201,6 +210,16 @@ module.exports = class ProjectsDBApi {
+ await FileDBApi.replaceRelationFiles(
+ {
+ belongsTo: db.projects.getTableName(),
+ belongsToColumn: 'attachments',
+ belongsToId: projects.id,
+ },
+ data.attachments,
+ options,
+ );
+
return projects;
}
@@ -280,14 +299,6 @@ module.exports = class ProjectsDBApi {
-
-
- output.reports_project = await projects.getReports_project({
- transaction
- });
-
-
-
output.owner = await projects.getOwner({
transaction
});
@@ -298,6 +309,11 @@ module.exports = class ProjectsDBApi {
});
+ output.attachments = await projects.getAttachments({
+ transaction
+ });
+
+
return output;
}
@@ -359,6 +375,11 @@ module.exports = class ProjectsDBApi {
+ {
+ model: db.file,
+ as: 'attachments',
+ },
+
];
if (filter) {
@@ -487,30 +508,6 @@ module.exports = class ProjectsDBApi {
}
}
- if (filter.progressRange) {
- const [start, end] = filter.progressRange;
-
- if (start !== undefined && start !== null && start !== '') {
- where = {
- ...where,
- progress: {
- ...where.progress,
- [Op.gte]: start,
- },
- };
- }
-
- if (end !== undefined && end !== null && end !== '') {
- where = {
- ...where,
- progress: {
- ...where.progress,
- [Op.lte]: end,
- },
- };
- }
- }
-
if (filter.active !== undefined) {
where = {
diff --git a/backend/src/db/api/reports.js b/backend/src/db/api/reports.js
deleted file mode 100644
index 487e751..0000000
--- a/backend/src/db/api/reports.js
+++ /dev/null
@@ -1,514 +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 ReportsDBApi {
-
-
-
- static async create(data, options) {
- const currentUser = (options && options.currentUser) || { id: null };
- const transaction = (options && options.transaction) || undefined;
-
- const reports = await db.reports.create(
- {
- id: data.id || undefined,
-
- title: data.title
- ||
- null
- ,
-
- created_on: data.created_on
- ||
- null
- ,
-
- summary: data.summary
- ||
- null
- ,
-
- importHash: data.importHash || null,
- createdById: currentUser.id,
- updatedById: currentUser.id,
- },
- { transaction },
- );
-
-
- await reports.setProject( data.project || null, {
- transaction,
- });
-
- await reports.setGenerated_by( data.generated_by || null, {
- transaction,
- });
-
-
-
-
-
- await FileDBApi.replaceRelationFiles(
- {
- belongsTo: db.reports.getTableName(),
- belongsToColumn: 'content_file',
- belongsToId: reports.id,
- },
- data.content_file,
- options,
- );
-
-
- return reports;
- }
-
-
- 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 reportsData = data.map((item, index) => ({
- id: item.id || undefined,
-
- title: item.title
- ||
- null
- ,
-
- created_on: item.created_on
- ||
- null
- ,
-
- summary: item.summary
- ||
- null
- ,
-
- importHash: item.importHash || null,
- createdById: currentUser.id,
- updatedById: currentUser.id,
- createdAt: new Date(Date.now() + index * 1000),
- }));
-
- // Bulk create items
- const reports = await db.reports.bulkCreate(reportsData, { transaction });
-
- // For each item created, replace relation files
-
- for (let i = 0; i < reports.length; i++) {
- await FileDBApi.replaceRelationFiles(
- {
- belongsTo: db.reports.getTableName(),
- belongsToColumn: 'content_file',
- belongsToId: reports[i].id,
- },
- data[i].content_file,
- options,
- );
- }
-
-
- return reports;
- }
-
- static async update(id, data, options) {
- const currentUser = (options && options.currentUser) || {id: null};
- const transaction = (options && options.transaction) || undefined;
-
-
- const reports = await db.reports.findByPk(id, {}, {transaction});
-
-
-
-
- const updatePayload = {};
-
- if (data.title !== undefined) updatePayload.title = data.title;
-
-
- if (data.created_on !== undefined) updatePayload.created_on = data.created_on;
-
-
- if (data.summary !== undefined) updatePayload.summary = data.summary;
-
-
- updatePayload.updatedById = currentUser.id;
-
- await reports.update(updatePayload, {transaction});
-
-
-
- if (data.project !== undefined) {
- await reports.setProject(
-
- data.project,
-
- { transaction }
- );
- }
-
- if (data.generated_by !== undefined) {
- await reports.setGenerated_by(
-
- data.generated_by,
-
- { transaction }
- );
- }
-
-
-
-
-
-
- await FileDBApi.replaceRelationFiles(
- {
- belongsTo: db.reports.getTableName(),
- belongsToColumn: 'content_file',
- belongsToId: reports.id,
- },
- data.content_file,
- options,
- );
-
-
- return reports;
- }
-
- static async deleteByIds(ids, options) {
- const currentUser = (options && options.currentUser) || { id: null };
- const transaction = (options && options.transaction) || undefined;
-
- const reports = await db.reports.findAll({
- where: {
- id: {
- [Op.in]: ids,
- },
- },
- transaction,
- });
-
- await db.sequelize.transaction(async (transaction) => {
- for (const record of reports) {
- await record.update(
- {deletedBy: currentUser.id},
- {transaction}
- );
- }
- for (const record of reports) {
- await record.destroy({transaction});
- }
- });
-
-
- return reports;
- }
-
- static async remove(id, options) {
- const currentUser = (options && options.currentUser) || {id: null};
- const transaction = (options && options.transaction) || undefined;
-
- const reports = await db.reports.findByPk(id, options);
-
- await reports.update({
- deletedBy: currentUser.id
- }, {
- transaction,
- });
-
- await reports.destroy({
- transaction
- });
-
- return reports;
- }
-
- static async findBy(where, options) {
- const transaction = (options && options.transaction) || undefined;
-
- const reports = await db.reports.findOne(
- { where },
- { transaction },
- );
-
- if (!reports) {
- return reports;
- }
-
- const output = reports.get({plain: true});
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- output.project = await reports.getProject({
- transaction
- });
-
-
- output.generated_by = await reports.getGenerated_by({
- transaction
- });
-
-
- output.content_file = await reports.getContent_file({
- transaction
- });
-
-
-
- return output;
- }
-
- static async findAll(
- filter,
- options
- ) {
- const limit = filter.limit || 0;
- let offset = 0;
- let where = {};
- const currentPage = +filter.page;
-
-
-
-
-
- offset = currentPage * limit;
-
- const orderBy = null;
-
- const transaction = (options && options.transaction) || undefined;
-
- let include = [
-
- {
- model: db.projects,
- as: 'project',
-
- where: filter.project ? {
- [Op.or]: [
- { id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
- {
- name: {
- [Op.or]: filter.project.split('|').map(term => ({ [Op.iLike]: `%${term}%` }))
- }
- },
- ]
- } : {},
-
- },
-
- {
- model: db.users,
- as: 'generated_by',
-
- where: filter.generated_by ? {
- [Op.or]: [
- { id: { [Op.in]: filter.generated_by.split('|').map(term => Utils.uuid(term)) } },
- {
- firstName: {
- [Op.or]: filter.generated_by.split('|').map(term => ({ [Op.iLike]: `%${term}%` }))
- }
- },
- ]
- } : {},
-
- },
-
-
-
- {
- model: db.file,
- as: 'content_file',
- },
-
- ];
-
- if (filter) {
- if (filter.id) {
- where = {
- ...where,
- ['id']: Utils.uuid(filter.id),
- };
- }
-
-
- if (filter.title) {
- where = {
- ...where,
- [Op.and]: Utils.ilike(
- 'reports',
- 'title',
- filter.title,
- ),
- };
- }
-
- if (filter.summary) {
- where = {
- ...where,
- [Op.and]: Utils.ilike(
- 'reports',
- 'summary',
- filter.summary,
- ),
- };
- }
-
-
-
-
-
-
- if (filter.created_onRange) {
- const [start, end] = filter.created_onRange;
-
- if (start !== undefined && start !== null && start !== '') {
- where = {
- ...where,
- created_on: {
- ...where.created_on,
- [Op.gte]: start,
- },
- };
- }
-
- if (end !== undefined && end !== null && end !== '') {
- where = {
- ...where,
- created_on: {
- ...where.created_on,
- [Op.lte]: end,
- },
- };
- }
- }
-
-
- if (filter.active !== undefined) {
- where = {
- ...where,
- active: filter.active === true || filter.active === 'true'
- };
- }
-
-
-
-
-
-
-
-
-
-
- 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,
- },
- };
- }
- }
- }
-
-
-
-
- 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.reports.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, ) {
- let where = {};
-
-
-
- if (query) {
- where = {
- [Op.or]: [
- { ['id']: Utils.uuid(query) },
- Utils.ilike(
- 'reports',
- 'title',
- query,
- ),
- ],
- };
- }
-
- const records = await db.reports.findAll({
- attributes: [ 'id', 'title' ],
- where,
- limit: limit ? Number(limit) : undefined,
- offset: offset ? Number(offset) : undefined,
- orderBy: [['title', 'ASC']],
- });
-
- return records.map((record) => ({
- id: record.id,
- label: record.title,
- }));
- }
-
-
-};
-
diff --git a/backend/src/db/api/roles.js b/backend/src/db/api/roles.js
index d20e68d..4d11d0a 100644
--- a/backend/src/db/api/roles.js
+++ b/backend/src/db/api/roles.js
@@ -197,10 +197,6 @@ module.exports = class RolesDBApi {
-
-
-
-
output.permissions = await roles.getPermissions({
transaction
});
diff --git a/backend/src/db/api/tasks.js b/backend/src/db/api/tasks.js
index d1d5131..6d99211 100644
--- a/backend/src/db/api/tasks.js
+++ b/backend/src/db/api/tasks.js
@@ -41,21 +41,26 @@ module.exports = class TasksDBApi {
null
,
- due_date: data.due_date
- ||
- null
- ,
-
start_date: data.start_date
||
null
,
+ due_date: data.due_date
+ ||
+ null
+ ,
+
estimated_hours: data.estimated_hours
||
null
,
+ spent_hours: data.spent_hours
+ ||
+ null
+ ,
+
completed: data.completed
||
false
@@ -70,6 +75,10 @@ module.exports = class TasksDBApi {
);
+ await tasks.setProject( data.project || null, {
+ transaction,
+ });
+
await tasks.setAssignee( data.assignee || null, {
transaction,
});
@@ -78,14 +87,20 @@ module.exports = class TasksDBApi {
transaction,
});
- await tasks.setProject( data.project || null, {
- transaction,
- });
-
+ await FileDBApi.replaceRelationFiles(
+ {
+ belongsTo: db.tasks.getTableName(),
+ belongsToColumn: 'attachments',
+ belongsToId: tasks.id,
+ },
+ data.attachments,
+ options,
+ );
+
return tasks;
}
@@ -117,21 +132,26 @@ module.exports = class TasksDBApi {
priority: item.priority
||
null
- ,
-
- due_date: item.due_date
- ||
- null
,
start_date: item.start_date
||
null
+ ,
+
+ due_date: item.due_date
+ ||
+ null
,
estimated_hours: item.estimated_hours
||
null
+ ,
+
+ spent_hours: item.spent_hours
+ ||
+ null
,
completed: item.completed
@@ -151,6 +171,18 @@ module.exports = class TasksDBApi {
// For each item created, replace relation files
+ for (let i = 0; i < tasks.length; i++) {
+ await FileDBApi.replaceRelationFiles(
+ {
+ belongsTo: db.tasks.getTableName(),
+ belongsToColumn: 'attachments',
+ belongsToId: tasks[i].id,
+ },
+ data[i].attachments,
+ options,
+ );
+ }
+
return tasks;
}
@@ -179,15 +211,18 @@ module.exports = class TasksDBApi {
if (data.priority !== undefined) updatePayload.priority = data.priority;
- if (data.due_date !== undefined) updatePayload.due_date = data.due_date;
-
-
if (data.start_date !== undefined) updatePayload.start_date = data.start_date;
+ if (data.due_date !== undefined) updatePayload.due_date = data.due_date;
+
+
if (data.estimated_hours !== undefined) updatePayload.estimated_hours = data.estimated_hours;
+ if (data.spent_hours !== undefined) updatePayload.spent_hours = data.spent_hours;
+
+
if (data.completed !== undefined) updatePayload.completed = data.completed;
@@ -197,6 +232,15 @@ module.exports = class TasksDBApi {
+ if (data.project !== undefined) {
+ await tasks.setProject(
+
+ data.project,
+
+ { transaction }
+ );
+ }
+
if (data.assignee !== undefined) {
await tasks.setAssignee(
@@ -215,20 +259,21 @@ module.exports = class TasksDBApi {
);
}
- if (data.project !== undefined) {
- await tasks.setProject(
-
- data.project,
-
- { transaction }
- );
- }
-
+ await FileDBApi.replaceRelationFiles(
+ {
+ belongsTo: db.tasks.getTableName(),
+ belongsToColumn: 'attachments',
+ belongsToId: tasks.id,
+ },
+ data.attachments,
+ options,
+ );
+
return tasks;
}
@@ -303,23 +348,12 @@ module.exports = class TasksDBApi {
- output.comments_task = await tasks.getComments_task({
+
+ output.project = await tasks.getProject({
transaction
});
- output.attachments_task = await tasks.getAttachments_task({
- transaction
- });
-
-
- output.notifications_related_task = await tasks.getNotifications_related_task({
- transaction
- });
-
-
-
-
output.assignee = await tasks.getAssignee({
transaction
});
@@ -330,7 +364,7 @@ module.exports = class TasksDBApi {
});
- output.project = await tasks.getProject({
+ output.attachments = await tasks.getAttachments({
transaction
});
@@ -360,6 +394,23 @@ module.exports = class TasksDBApi {
let include = [
+ {
+ model: db.projects,
+ as: 'project',
+
+ where: filter.project ? {
+ [Op.or]: [
+ { id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
+ {
+ name: {
+ [Op.or]: filter.project.split('|').map(term => ({ [Op.iLike]: `%${term}%` }))
+ }
+ },
+ ]
+ } : {},
+
+ },
+
{
model: db.users,
as: 'assignee',
@@ -394,25 +445,13 @@ module.exports = class TasksDBApi {
},
+
+
{
- model: db.projects,
- as: 'project',
-
- where: filter.project ? {
- [Op.or]: [
- { id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
- {
- name: {
- [Op.or]: filter.project.split('|').map(term => ({ [Op.iLike]: `%${term}%` }))
- }
- },
- ]
- } : {},
-
+ model: db.file,
+ as: 'attachments',
},
-
-
];
if (filter) {
@@ -451,30 +490,6 @@ module.exports = class TasksDBApi {
- if (filter.due_dateRange) {
- const [start, end] = filter.due_dateRange;
-
- if (start !== undefined && start !== null && start !== '') {
- where = {
- ...where,
- due_date: {
- ...where.due_date,
- [Op.gte]: start,
- },
- };
- }
-
- if (end !== undefined && end !== null && end !== '') {
- where = {
- ...where,
- due_date: {
- ...where.due_date,
- [Op.lte]: end,
- },
- };
- }
- }
-
if (filter.start_dateRange) {
const [start, end] = filter.start_dateRange;
@@ -499,6 +514,30 @@ module.exports = class TasksDBApi {
}
}
+ if (filter.due_dateRange) {
+ const [start, end] = filter.due_dateRange;
+
+ if (start !== undefined && start !== null && start !== '') {
+ where = {
+ ...where,
+ due_date: {
+ ...where.due_date,
+ [Op.gte]: start,
+ },
+ };
+ }
+
+ if (end !== undefined && end !== null && end !== '') {
+ where = {
+ ...where,
+ due_date: {
+ ...where.due_date,
+ [Op.lte]: end,
+ },
+ };
+ }
+ }
+
if (filter.estimated_hoursRange) {
const [start, end] = filter.estimated_hoursRange;
@@ -523,6 +562,30 @@ module.exports = class TasksDBApi {
}
}
+ if (filter.spent_hoursRange) {
+ const [start, end] = filter.spent_hoursRange;
+
+ if (start !== undefined && start !== null && start !== '') {
+ where = {
+ ...where,
+ spent_hours: {
+ ...where.spent_hours,
+ [Op.gte]: start,
+ },
+ };
+ }
+
+ if (end !== undefined && end !== null && end !== '') {
+ where = {
+ ...where,
+ spent_hours: {
+ ...where.spent_hours,
+ [Op.lte]: end,
+ },
+ };
+ }
+ }
+
if (filter.active !== undefined) {
where = {
diff --git a/backend/src/db/api/team_members.js b/backend/src/db/api/team_memberships.js
similarity index 72%
rename from backend/src/db/api/team_members.js
rename to backend/src/db/api/team_memberships.js
index bd7d74e..2c6f765 100644
--- a/backend/src/db/api/team_members.js
+++ b/backend/src/db/api/team_memberships.js
@@ -9,7 +9,7 @@ const Utils = require('../utils');
const Sequelize = db.Sequelize;
const Op = Sequelize.Op;
-module.exports = class Team_membersDBApi {
+module.exports = class Team_membershipsDBApi {
@@ -17,22 +17,17 @@ module.exports = class Team_membersDBApi {
const currentUser = (options && options.currentUser) || { id: null };
const transaction = (options && options.transaction) || undefined;
- const team_members = await db.team_members.create(
+ const team_memberships = await db.team_memberships.create(
{
id: data.id || undefined,
+ member_label: data.member_label
+ ||
+ null
+ ,
+
role: data.role
||
- null
- ,
-
- joined_on: data.joined_on
- ||
- null
- ,
-
- display_label: data.display_label
- ||
null
,
@@ -44,11 +39,11 @@ module.exports = class Team_membersDBApi {
);
- await team_members.setTeam( data.team || null, {
+ await team_memberships.setTeam( data.team || null, {
transaction,
});
- await team_members.setUser( data.user || null, {
+ await team_memberships.setUser( data.user || null, {
transaction,
});
@@ -57,7 +52,7 @@ module.exports = class Team_membersDBApi {
- return team_members;
+ return team_memberships;
}
@@ -66,22 +61,17 @@ module.exports = class Team_membersDBApi {
const transaction = (options && options.transaction) || undefined;
// Prepare data - wrapping individual data transformations in a map() method
- const team_membersData = data.map((item, index) => ({
+ const team_membershipsData = data.map((item, index) => ({
id: item.id || undefined,
+ member_label: item.member_label
+ ||
+ null
+ ,
+
role: item.role
||
null
- ,
-
- joined_on: item.joined_on
- ||
- null
- ,
-
- display_label: item.display_label
- ||
- null
,
importHash: item.importHash || null,
@@ -91,12 +81,12 @@ module.exports = class Team_membersDBApi {
}));
// Bulk create items
- const team_members = await db.team_members.bulkCreate(team_membersData, { transaction });
+ const team_memberships = await db.team_memberships.bulkCreate(team_membershipsData, { transaction });
// For each item created, replace relation files
- return team_members;
+ return team_memberships;
}
static async update(id, data, options) {
@@ -104,30 +94,27 @@ module.exports = class Team_membersDBApi {
const transaction = (options && options.transaction) || undefined;
- const team_members = await db.team_members.findByPk(id, {}, {transaction});
+ const team_memberships = await db.team_memberships.findByPk(id, {}, {transaction});
const updatePayload = {};
+ if (data.member_label !== undefined) updatePayload.member_label = data.member_label;
+
+
if (data.role !== undefined) updatePayload.role = data.role;
- if (data.joined_on !== undefined) updatePayload.joined_on = data.joined_on;
-
-
- if (data.display_label !== undefined) updatePayload.display_label = data.display_label;
-
-
updatePayload.updatedById = currentUser.id;
- await team_members.update(updatePayload, {transaction});
+ await team_memberships.update(updatePayload, {transaction});
if (data.team !== undefined) {
- await team_members.setTeam(
+ await team_memberships.setTeam(
data.team,
@@ -136,7 +123,7 @@ module.exports = class Team_membersDBApi {
}
if (data.user !== undefined) {
- await team_members.setUser(
+ await team_memberships.setUser(
data.user,
@@ -150,14 +137,14 @@ module.exports = class Team_membersDBApi {
- return team_members;
+ return team_memberships;
}
static async deleteByIds(ids, options) {
const currentUser = (options && options.currentUser) || { id: null };
const transaction = (options && options.transaction) || undefined;
- const team_members = await db.team_members.findAll({
+ const team_memberships = await db.team_memberships.findAll({
where: {
id: {
[Op.in]: ids,
@@ -167,53 +154,53 @@ module.exports = class Team_membersDBApi {
});
await db.sequelize.transaction(async (transaction) => {
- for (const record of team_members) {
+ for (const record of team_memberships) {
await record.update(
{deletedBy: currentUser.id},
{transaction}
);
}
- for (const record of team_members) {
+ for (const record of team_memberships) {
await record.destroy({transaction});
}
});
- return team_members;
+ return team_memberships;
}
static async remove(id, options) {
const currentUser = (options && options.currentUser) || {id: null};
const transaction = (options && options.transaction) || undefined;
- const team_members = await db.team_members.findByPk(id, options);
+ const team_memberships = await db.team_memberships.findByPk(id, options);
- await team_members.update({
+ await team_memberships.update({
deletedBy: currentUser.id
}, {
transaction,
});
- await team_members.destroy({
+ await team_memberships.destroy({
transaction
});
- return team_members;
+ return team_memberships;
}
static async findBy(where, options) {
const transaction = (options && options.transaction) || undefined;
- const team_members = await db.team_members.findOne(
+ const team_memberships = await db.team_memberships.findOne(
{ where },
{ transaction },
);
- if (!team_members) {
- return team_members;
+ if (!team_memberships) {
+ return team_memberships;
}
- const output = team_members.get({plain: true});
+ const output = team_memberships.get({plain: true});
@@ -224,16 +211,12 @@ module.exports = class Team_membersDBApi {
-
-
-
-
- output.team = await team_members.getTeam({
+ output.team = await team_memberships.getTeam({
transaction
});
- output.user = await team_members.getUser({
+ output.user = await team_memberships.getUser({
transaction
});
@@ -310,13 +293,13 @@ module.exports = class Team_membersDBApi {
}
- if (filter.display_label) {
+ if (filter.member_label) {
where = {
...where,
[Op.and]: Utils.ilike(
- 'team_members',
- 'display_label',
- filter.display_label,
+ 'team_memberships',
+ 'member_label',
+ filter.member_label,
),
};
}
@@ -326,30 +309,6 @@ module.exports = class Team_membersDBApi {
- if (filter.joined_onRange) {
- const [start, end] = filter.joined_onRange;
-
- if (start !== undefined && start !== null && start !== '') {
- where = {
- ...where,
- joined_on: {
- ...where.joined_on,
- [Op.gte]: start,
- },
- };
- }
-
- if (end !== undefined && end !== null && end !== '') {
- where = {
- ...where,
- joined_on: {
- ...where.joined_on,
- [Op.lte]: end,
- },
- };
- }
- }
-
if (filter.active !== undefined) {
where = {
@@ -419,7 +378,7 @@ module.exports = class Team_membersDBApi {
}
try {
- const { rows, count } = await db.team_members.findAndCountAll(queryOptions);
+ const { rows, count } = await db.team_memberships.findAndCountAll(queryOptions);
return {
rows: options?.countOnly ? [] : rows,
@@ -441,25 +400,25 @@ module.exports = class Team_membersDBApi {
[Op.or]: [
{ ['id']: Utils.uuid(query) },
Utils.ilike(
- 'team_members',
- 'display_label',
+ 'team_memberships',
+ 'member_label',
query,
),
],
};
}
- const records = await db.team_members.findAll({
- attributes: [ 'id', 'display_label' ],
+ const records = await db.team_memberships.findAll({
+ attributes: [ 'id', 'member_label' ],
where,
limit: limit ? Number(limit) : undefined,
offset: offset ? Number(offset) : undefined,
- orderBy: [['display_label', 'ASC']],
+ orderBy: [['member_label', 'ASC']],
});
return records.map((record) => ({
id: record.id,
- label: record.display_label,
+ label: record.member_label,
}));
}
diff --git a/backend/src/db/api/teams.js b/backend/src/db/api/teams.js
index 995cfb9..6306911 100644
--- a/backend/src/db/api/teams.js
+++ b/backend/src/db/api/teams.js
@@ -28,16 +28,6 @@ module.exports = class TeamsDBApi {
description: data.description
||
- null
- ,
-
- visibility: data.visibility
- ||
- null
- ,
-
- members_count: data.members_count
- ||
null
,
@@ -49,24 +39,10 @@ module.exports = class TeamsDBApi {
);
- await teams.setOwner( data.owner || null, {
- transaction,
- });
-
- await FileDBApi.replaceRelationFiles(
- {
- belongsTo: db.teams.getTableName(),
- belongsToColumn: 'avatar',
- belongsToId: teams.id,
- },
- data.avatar,
- options,
- );
-
return teams;
}
@@ -88,16 +64,6 @@ module.exports = class TeamsDBApi {
description: item.description
||
null
- ,
-
- visibility: item.visibility
- ||
- null
- ,
-
- members_count: item.members_count
- ||
- null
,
importHash: item.importHash || null,
@@ -111,18 +77,6 @@ module.exports = class TeamsDBApi {
// For each item created, replace relation files
- for (let i = 0; i < teams.length; i++) {
- await FileDBApi.replaceRelationFiles(
- {
- belongsTo: db.teams.getTableName(),
- belongsToColumn: 'avatar',
- belongsToId: teams[i].id,
- },
- data[i].avatar,
- options,
- );
- }
-
return teams;
}
@@ -145,42 +99,17 @@ module.exports = class TeamsDBApi {
if (data.description !== undefined) updatePayload.description = data.description;
- if (data.visibility !== undefined) updatePayload.visibility = data.visibility;
-
-
- if (data.members_count !== undefined) updatePayload.members_count = data.members_count;
-
-
updatePayload.updatedById = currentUser.id;
await teams.update(updatePayload, {transaction});
- if (data.owner !== undefined) {
- await teams.setOwner(
-
- data.owner,
-
- { transaction }
- );
- }
-
- await FileDBApi.replaceRelationFiles(
- {
- belongsTo: db.teams.getTableName(),
- belongsToColumn: 'avatar',
- belongsToId: teams.id,
- },
- data.avatar,
- options,
- );
-
return teams;
}
@@ -252,7 +181,7 @@ module.exports = class TeamsDBApi {
- output.team_members_team = await teams.getTeam_members_team({
+ output.team_memberships_team = await teams.getTeam_memberships_team({
transaction
});
@@ -264,20 +193,6 @@ module.exports = class TeamsDBApi {
-
-
-
-
- output.avatar = await teams.getAvatar({
- transaction
- });
-
-
- output.owner = await teams.getOwner({
- transaction
- });
-
-
return output;
}
@@ -303,30 +218,8 @@ module.exports = class TeamsDBApi {
let include = [
- {
- model: db.users,
- as: 'owner',
-
- where: filter.owner ? {
- [Op.or]: [
- { id: { [Op.in]: filter.owner.split('|').map(term => Utils.uuid(term)) } },
- {
- firstName: {
- [Op.or]: filter.owner.split('|').map(term => ({ [Op.iLike]: `%${term}%` }))
- }
- },
- ]
- } : {},
-
- },
-
- {
- model: db.file,
- as: 'avatar',
- },
-
];
if (filter) {
@@ -365,30 +258,6 @@ module.exports = class TeamsDBApi {
- if (filter.members_countRange) {
- const [start, end] = filter.members_countRange;
-
- if (start !== undefined && start !== null && start !== '') {
- where = {
- ...where,
- members_count: {
- ...where.members_count,
- [Op.gte]: start,
- },
- };
- }
-
- if (end !== undefined && end !== null && end !== '') {
- where = {
- ...where,
- members_count: {
- ...where.members_count,
- [Op.lte]: end,
- },
- };
- }
- }
-
if (filter.active !== undefined) {
where = {
@@ -398,17 +267,8 @@ module.exports = class TeamsDBApi {
}
- if (filter.visibility) {
- where = {
- ...where,
- visibility: filter.visibility,
- };
- }
-
-
-
if (filter.createdAtRange) {
diff --git a/backend/src/db/api/users.js b/backend/src/db/api/users.js
index d3ee52e..4bed437 100644
--- a/backend/src/db/api/users.js
+++ b/backend/src/db/api/users.js
@@ -403,12 +403,8 @@ module.exports = class UsersDBApi {
- output.teams_owner = await users.getTeams_owner({
- transaction
- });
-
- output.team_members_user = await users.getTeam_members_user({
+ output.team_memberships_user = await users.getTeam_memberships_user({
transaction
});
@@ -427,26 +423,6 @@ module.exports = class UsersDBApi {
});
- output.comments_author = await users.getComments_author({
- transaction
- });
-
-
- output.attachments_uploaded_by = await users.getAttachments_uploaded_by({
- transaction
- });
-
-
- output.notifications_recipient = await users.getNotifications_recipient({
- transaction
- });
-
-
- output.reports_generated_by = await users.getReports_generated_by({
- transaction
- });
-
-
output.avatar = await users.getAvatar({
transaction
diff --git a/backend/src/db/db.config.js b/backend/src/db/db.config.js
index 4c88153..7c7dc83 100644
--- a/backend/src/db/db.config.js
+++ b/backend/src/db/db.config.js
@@ -15,7 +15,7 @@ module.exports = {
username: 'postgres',
dialect: 'postgres',
password: '',
- database: 'db_team_projects_hub',
+ database: 'db_teamflow_manager',
host: process.env.DB_HOST || 'localhost',
logging: console.log,
seederStorage: 'sequelize',
diff --git a/backend/src/db/migrations/1767609012299.js b/backend/src/db/migrations/1767710423367.js
similarity index 63%
rename from backend/src/db/migrations/1767609012299.js
rename to backend/src/db/migrations/1767710423367.js
index 0e0f4f0..a0d0508 100644
--- a/backend/src/db/migrations/1767609012299.js
+++ b/backend/src/db/migrations/1767710423367.js
@@ -140,7 +140,7 @@ module.exports = {
- await queryInterface.createTable('team_members', {
+ await queryInterface.createTable('team_memberships', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
@@ -236,134 +236,6 @@ module.exports = {
- await queryInterface.createTable('comments', {
- 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.createTable('attachments', {
- 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.createTable('notifications', {
- 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.createTable('reports', {
- 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(
'users',
@@ -653,29 +525,10 @@ module.exports = {
await queryInterface.addColumn(
- 'teams',
- 'visibility',
+ 'team_memberships',
+ 'member_label',
{
- type: Sequelize.DataTypes.ENUM,
-
-
- values: ['Private','Public'],
-
-
- },
- { transaction }
- );
-
-
-
-
-
-
- await queryInterface.addColumn(
- 'teams',
- 'members_count',
- {
- type: Sequelize.DataTypes.INTEGER,
+ type: Sequelize.DataTypes.TEXT,
@@ -687,27 +540,7 @@ module.exports = {
await queryInterface.addColumn(
- 'teams',
- 'ownerId',
- {
- type: Sequelize.DataTypes.UUID,
-
-
-
- references: {
- model: 'users',
- key: 'id',
- },
-
- },
- { transaction }
- );
-
-
-
-
- await queryInterface.addColumn(
- 'team_members',
+ 'team_memberships',
'teamId',
{
type: Sequelize.DataTypes.UUID,
@@ -727,7 +560,7 @@ module.exports = {
await queryInterface.addColumn(
- 'team_members',
+ 'team_memberships',
'userId',
{
type: Sequelize.DataTypes.UUID,
@@ -747,7 +580,7 @@ module.exports = {
await queryInterface.addColumn(
- 'team_members',
+ 'team_memberships',
'role',
{
type: Sequelize.DataTypes.ENUM,
@@ -763,36 +596,6 @@ module.exports = {
- await queryInterface.addColumn(
- 'team_members',
- 'joined_on',
- {
- type: Sequelize.DataTypes.DATE,
-
-
-
- },
- { transaction }
- );
-
-
-
-
- await queryInterface.addColumn(
- 'team_members',
- 'display_label',
- {
- type: Sequelize.DataTypes.TEXT,
-
-
-
- },
- { transaction }
- );
-
-
-
-
await queryInterface.addColumn(
'projects',
'name',
@@ -823,53 +626,6 @@ module.exports = {
- await queryInterface.addColumn(
- 'projects',
- 'start_date',
- {
- type: Sequelize.DataTypes.DATE,
-
-
-
- },
- { transaction }
- );
-
-
-
-
- await queryInterface.addColumn(
- 'projects',
- 'end_date',
- {
- type: Sequelize.DataTypes.DATE,
-
-
-
- },
- { transaction }
- );
-
-
-
-
- await queryInterface.addColumn(
- 'projects',
- 'status',
- {
- type: Sequelize.DataTypes.ENUM,
-
-
- values: ['Planned','Active','OnHold','Completed','Archived'],
-
-
- },
- { transaction }
- );
-
-
-
-
await queryInterface.addColumn(
'projects',
'ownerId',
@@ -912,9 +668,26 @@ module.exports = {
await queryInterface.addColumn(
'projects',
- 'budget',
+ 'status',
{
- type: Sequelize.DataTypes.DECIMAL,
+ type: Sequelize.DataTypes.ENUM,
+
+
+ values: ['Draft','Active','OnHold','Completed','Cancelled'],
+
+
+ },
+ { transaction }
+ );
+
+
+
+
+ await queryInterface.addColumn(
+ 'projects',
+ 'start_date',
+ {
+ type: Sequelize.DataTypes.DATE,
@@ -927,9 +700,9 @@ module.exports = {
await queryInterface.addColumn(
'projects',
- 'progress',
+ 'end_date',
{
- type: Sequelize.DataTypes.INTEGER,
+ type: Sequelize.DataTypes.DATE,
@@ -940,6 +713,23 @@ module.exports = {
+ await queryInterface.addColumn(
+ 'projects',
+ 'budget',
+ {
+ type: Sequelize.DataTypes.DECIMAL,
+
+
+
+ },
+ { transaction }
+ );
+
+
+
+
+
+
await queryInterface.addColumn(
'tasks',
'title',
@@ -972,30 +762,16 @@ module.exports = {
await queryInterface.addColumn(
'tasks',
- 'status',
+ 'projectId',
{
- type: Sequelize.DataTypes.ENUM,
+ type: Sequelize.DataTypes.UUID,
- values: ['Backlog','ToDo','InProgress','InReview','Done','Blocked'],
-
-
- },
- { transaction }
- );
-
-
-
-
- await queryInterface.addColumn(
- 'tasks',
- 'priority',
- {
- type: Sequelize.DataTypes.ENUM,
-
-
- values: ['Low','Medium','High','Critical'],
+ references: {
+ model: 'projects',
+ key: 'id',
+ },
},
{ transaction }
@@ -1046,16 +822,13 @@ module.exports = {
await queryInterface.addColumn(
'tasks',
- 'projectId',
+ 'status',
{
- type: Sequelize.DataTypes.UUID,
+ type: Sequelize.DataTypes.ENUM,
+ values: ['ToDo','InProgress','InReview','Blocked','Done'],
- references: {
- model: 'projects',
- key: 'id',
- },
},
{ transaction }
@@ -1066,7 +839,24 @@ module.exports = {
await queryInterface.addColumn(
'tasks',
- 'due_date',
+ 'priority',
+ {
+ type: Sequelize.DataTypes.ENUM,
+
+
+ values: ['Low','Medium','High','Critical'],
+
+
+ },
+ { transaction }
+ );
+
+
+
+
+ await queryInterface.addColumn(
+ 'tasks',
+ 'start_date',
{
type: Sequelize.DataTypes.DATE,
@@ -1081,7 +871,7 @@ module.exports = {
await queryInterface.addColumn(
'tasks',
- 'start_date',
+ 'due_date',
{
type: Sequelize.DataTypes.DATE,
@@ -1109,6 +899,23 @@ module.exports = {
+ await queryInterface.addColumn(
+ 'tasks',
+ 'spent_hours',
+ {
+ type: Sequelize.DataTypes.DECIMAL,
+
+
+
+ },
+ { transaction }
+ );
+
+
+
+
+
+
await queryInterface.addColumn(
'tasks',
'completed',
@@ -1125,323 +932,6 @@ module.exports = {
);
-
-
- await queryInterface.addColumn(
- 'comments',
- 'taskId',
- {
- type: Sequelize.DataTypes.UUID,
-
-
-
- references: {
- model: 'tasks',
- key: 'id',
- },
-
- },
- { transaction }
- );
-
-
-
-
- await queryInterface.addColumn(
- 'comments',
- 'authorId',
- {
- type: Sequelize.DataTypes.UUID,
-
-
-
- references: {
- model: 'users',
- key: 'id',
- },
-
- },
- { transaction }
- );
-
-
-
-
- await queryInterface.addColumn(
- 'comments',
- 'content',
- {
- type: Sequelize.DataTypes.TEXT,
-
-
-
- },
- { transaction }
- );
-
-
-
-
- await queryInterface.addColumn(
- 'comments',
- 'created_on',
- {
- type: Sequelize.DataTypes.DATE,
-
-
-
- },
- { transaction }
- );
-
-
-
-
- await queryInterface.addColumn(
- 'attachments',
- 'taskId',
- {
- type: Sequelize.DataTypes.UUID,
-
-
-
- references: {
- model: 'tasks',
- key: 'id',
- },
-
- },
- { transaction }
- );
-
-
-
-
- await queryInterface.addColumn(
- 'attachments',
- 'uploaded_byId',
- {
- type: Sequelize.DataTypes.UUID,
-
-
-
- references: {
- model: 'users',
- key: 'id',
- },
-
- },
- { transaction }
- );
-
-
-
-
-
-
- await queryInterface.addColumn(
- 'attachments',
- 'caption',
- {
- type: Sequelize.DataTypes.TEXT,
-
-
-
- },
- { transaction }
- );
-
-
-
-
- await queryInterface.addColumn(
- 'attachments',
- 'uploaded_on',
- {
- type: Sequelize.DataTypes.DATE,
-
-
-
- },
- { transaction }
- );
-
-
-
-
- await queryInterface.addColumn(
- 'notifications',
- 'recipientId',
- {
- type: Sequelize.DataTypes.UUID,
-
-
-
- references: {
- model: 'users',
- key: 'id',
- },
-
- },
- { transaction }
- );
-
-
-
-
- await queryInterface.addColumn(
- 'notifications',
- 'message',
- {
- type: Sequelize.DataTypes.TEXT,
-
-
-
- },
- { transaction }
- );
-
-
-
-
- await queryInterface.addColumn(
- 'notifications',
- 'related_taskId',
- {
- type: Sequelize.DataTypes.UUID,
-
-
-
- references: {
- model: 'tasks',
- key: 'id',
- },
-
- },
- { transaction }
- );
-
-
-
-
- await queryInterface.addColumn(
- 'notifications',
- 'read',
- {
- type: Sequelize.DataTypes.BOOLEAN,
-
- defaultValue: false,
- allowNull: false,
-
-
-
- },
- { transaction }
- );
-
-
-
-
- await queryInterface.addColumn(
- 'notifications',
- 'sent_at',
- {
- type: Sequelize.DataTypes.DATE,
-
-
-
- },
- { transaction }
- );
-
-
-
-
- await queryInterface.addColumn(
- 'reports',
- 'title',
- {
- type: Sequelize.DataTypes.TEXT,
-
-
-
- },
- { transaction }
- );
-
-
-
-
- await queryInterface.addColumn(
- 'reports',
- 'projectId',
- {
- type: Sequelize.DataTypes.UUID,
-
-
-
- references: {
- model: 'projects',
- key: 'id',
- },
-
- },
- { transaction }
- );
-
-
-
-
- await queryInterface.addColumn(
- 'reports',
- 'generated_byId',
- {
- type: Sequelize.DataTypes.UUID,
-
-
-
- references: {
- model: 'users',
- key: 'id',
- },
-
- },
- { transaction }
- );
-
-
-
-
- await queryInterface.addColumn(
- 'reports',
- 'created_on',
- {
- type: Sequelize.DataTypes.DATE,
-
-
-
- },
- { transaction }
- );
-
-
-
-
-
-
- await queryInterface.addColumn(
- 'reports',
- 'summary',
- {
- type: Sequelize.DataTypes.TEXT,
-
-
-
- },
- { transaction }
- );
-
-
await transaction.commit();
@@ -1464,8 +954,8 @@ module.exports = {
await queryInterface.removeColumn(
- 'reports',
- 'summary',
+ 'tasks',
+ 'completed',
{ transaction }
);
@@ -1473,147 +963,9 @@ module.exports = {
- await queryInterface.removeColumn(
- 'reports',
- 'created_on',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'reports',
- 'generated_byId',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'reports',
- 'projectId',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'reports',
- 'title',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'notifications',
- 'sent_at',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'notifications',
- 'read',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'notifications',
- 'related_taskId',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'notifications',
- 'message',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'notifications',
- 'recipientId',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'attachments',
- 'uploaded_on',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'attachments',
- 'caption',
- { transaction }
- );
-
-
-
-
-
- await queryInterface.removeColumn(
- 'attachments',
- 'uploaded_byId',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'attachments',
- 'taskId',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'comments',
- 'created_on',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'comments',
- 'content',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'comments',
- 'authorId',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'comments',
- 'taskId',
- { transaction }
- );
-
-
-
await queryInterface.removeColumn(
'tasks',
- 'completed',
+ 'spent_hours',
{ transaction }
);
@@ -1627,14 +979,6 @@ module.exports = {
- await queryInterface.removeColumn(
- 'tasks',
- 'start_date',
- { transaction }
- );
-
-
-
await queryInterface.removeColumn(
'tasks',
'due_date',
@@ -1645,23 +989,7 @@ module.exports = {
await queryInterface.removeColumn(
'tasks',
- 'projectId',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'tasks',
- 'reporterId',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'tasks',
- 'assigneeId',
+ 'start_date',
{ transaction }
);
@@ -1683,6 +1011,30 @@ module.exports = {
+ await queryInterface.removeColumn(
+ 'tasks',
+ 'reporterId',
+ { transaction }
+ );
+
+
+
+ await queryInterface.removeColumn(
+ 'tasks',
+ 'assigneeId',
+ { transaction }
+ );
+
+
+
+ await queryInterface.removeColumn(
+ 'tasks',
+ 'projectId',
+ { transaction }
+ );
+
+
+
await queryInterface.removeColumn(
'tasks',
'description',
@@ -1699,12 +1051,6 @@ module.exports = {
- await queryInterface.removeColumn(
- 'projects',
- 'progress',
- { transaction }
- );
-
await queryInterface.removeColumn(
@@ -1715,30 +1061,6 @@ module.exports = {
- await queryInterface.removeColumn(
- 'projects',
- 'teamId',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'projects',
- 'ownerId',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'projects',
- 'status',
- { transaction }
- );
-
-
-
await queryInterface.removeColumn(
'projects',
'end_date',
@@ -1755,6 +1077,30 @@ module.exports = {
+ await queryInterface.removeColumn(
+ 'projects',
+ 'status',
+ { transaction }
+ );
+
+
+
+ await queryInterface.removeColumn(
+ 'projects',
+ 'teamId',
+ { transaction }
+ );
+
+
+
+ await queryInterface.removeColumn(
+ 'projects',
+ 'ownerId',
+ { transaction }
+ );
+
+
+
await queryInterface.removeColumn(
'projects',
'description',
@@ -1772,23 +1118,7 @@ module.exports = {
await queryInterface.removeColumn(
- 'team_members',
- 'display_label',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'team_members',
- 'joined_on',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'team_members',
+ 'team_memberships',
'role',
{ transaction }
);
@@ -1796,7 +1126,7 @@ module.exports = {
await queryInterface.removeColumn(
- 'team_members',
+ 'team_memberships',
'userId',
{ transaction }
);
@@ -1804,7 +1134,7 @@ module.exports = {
await queryInterface.removeColumn(
- 'team_members',
+ 'team_memberships',
'teamId',
{ transaction }
);
@@ -1812,26 +1142,8 @@ module.exports = {
await queryInterface.removeColumn(
- 'teams',
- 'ownerId',
- { transaction }
- );
-
-
-
- await queryInterface.removeColumn(
- 'teams',
- 'members_count',
- { transaction }
- );
-
-
-
-
-
- await queryInterface.removeColumn(
- 'teams',
- 'visibility',
+ 'team_memberships',
+ 'member_label',
{ transaction }
);
@@ -1987,22 +1299,6 @@ module.exports = {
- await queryInterface.dropTable('reports', { transaction });
-
-
-
- await queryInterface.dropTable('notifications', { transaction });
-
-
-
- await queryInterface.dropTable('attachments', { transaction });
-
-
-
- await queryInterface.dropTable('comments', { transaction });
-
-
-
await queryInterface.dropTable('tasks', { transaction });
@@ -2011,7 +1307,7 @@ module.exports = {
- await queryInterface.dropTable('team_members', { transaction });
+ await queryInterface.dropTable('team_memberships', { transaction });
diff --git a/backend/src/db/models/attachments.js b/backend/src/db/models/attachments.js
deleted file mode 100644
index 2558d8e..0000000
--- a/backend/src/db/models/attachments.js
+++ /dev/null
@@ -1,109 +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 attachments = sequelize.define(
- 'attachments',
- {
- id: {
- type: DataTypes.UUID,
- defaultValue: DataTypes.UUIDV4,
- primaryKey: true,
- },
-
-caption: {
- type: DataTypes.TEXT,
-
-
-
- },
-
-uploaded_on: {
- type: DataTypes.DATE,
-
-
-
- },
-
- importHash: {
- type: DataTypes.STRING(255),
- allowNull: true,
- unique: true,
- },
- },
- {
- timestamps: true,
- paranoid: true,
- freezeTableName: true,
- },
- );
-
- attachments.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.attachments.belongsTo(db.tasks, {
- as: 'task',
- foreignKey: {
- name: 'taskId',
- },
- constraints: false,
- });
-
- db.attachments.belongsTo(db.users, {
- as: 'uploaded_by',
- foreignKey: {
- name: 'uploaded_byId',
- },
- constraints: false,
- });
-
-
-
- db.attachments.hasMany(db.file, {
- as: 'file',
- foreignKey: 'belongsToId',
- constraints: false,
- scope: {
- belongsTo: db.attachments.getTableName(),
- belongsToColumn: 'file',
- },
- });
-
-
- db.attachments.belongsTo(db.users, {
- as: 'createdBy',
- });
-
- db.attachments.belongsTo(db.users, {
- as: 'updatedBy',
- });
- };
-
-
-
- return attachments;
-};
-
-
diff --git a/backend/src/db/models/comments.js b/backend/src/db/models/comments.js
deleted file mode 100644
index f76258d..0000000
--- a/backend/src/db/models/comments.js
+++ /dev/null
@@ -1,99 +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 comments = sequelize.define(
- 'comments',
- {
- id: {
- type: DataTypes.UUID,
- defaultValue: DataTypes.UUIDV4,
- primaryKey: true,
- },
-
-content: {
- type: DataTypes.TEXT,
-
-
-
- },
-
-created_on: {
- type: DataTypes.DATE,
-
-
-
- },
-
- importHash: {
- type: DataTypes.STRING(255),
- allowNull: true,
- unique: true,
- },
- },
- {
- timestamps: true,
- paranoid: true,
- freezeTableName: true,
- },
- );
-
- comments.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.comments.belongsTo(db.tasks, {
- as: 'task',
- foreignKey: {
- name: 'taskId',
- },
- constraints: false,
- });
-
- db.comments.belongsTo(db.users, {
- as: 'author',
- foreignKey: {
- name: 'authorId',
- },
- constraints: false,
- });
-
-
-
-
- db.comments.belongsTo(db.users, {
- as: 'createdBy',
- });
-
- db.comments.belongsTo(db.users, {
- as: 'updatedBy',
- });
- };
-
-
-
- return comments;
-};
-
-
diff --git a/backend/src/db/models/notifications.js b/backend/src/db/models/notifications.js
deleted file mode 100644
index 09a9be9..0000000
--- a/backend/src/db/models/notifications.js
+++ /dev/null
@@ -1,109 +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 notifications = sequelize.define(
- 'notifications',
- {
- id: {
- type: DataTypes.UUID,
- defaultValue: DataTypes.UUIDV4,
- primaryKey: true,
- },
-
-message: {
- type: DataTypes.TEXT,
-
-
-
- },
-
-read: {
- type: DataTypes.BOOLEAN,
-
- allowNull: false,
- defaultValue: false,
-
-
-
- },
-
-sent_at: {
- type: DataTypes.DATE,
-
-
-
- },
-
- importHash: {
- type: DataTypes.STRING(255),
- allowNull: true,
- unique: true,
- },
- },
- {
- timestamps: true,
- paranoid: true,
- freezeTableName: true,
- },
- );
-
- notifications.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.notifications.belongsTo(db.users, {
- as: 'recipient',
- foreignKey: {
- name: 'recipientId',
- },
- constraints: false,
- });
-
- db.notifications.belongsTo(db.tasks, {
- as: 'related_task',
- foreignKey: {
- name: 'related_taskId',
- },
- constraints: false,
- });
-
-
-
-
- db.notifications.belongsTo(db.users, {
- as: 'createdBy',
- });
-
- db.notifications.belongsTo(db.users, {
- as: 'updatedBy',
- });
- };
-
-
-
- return notifications;
-};
-
-
diff --git a/backend/src/db/models/permissions.js b/backend/src/db/models/permissions.js
index 53431d8..c6a1206 100644
--- a/backend/src/db/models/permissions.js
+++ b/backend/src/db/models/permissions.js
@@ -48,10 +48,6 @@ name: {
-
-
-
-
//end loop
diff --git a/backend/src/db/models/projects.js b/backend/src/db/models/projects.js
index 58f5c57..14c265c 100644
--- a/backend/src/db/models/projects.js
+++ b/backend/src/db/models/projects.js
@@ -28,6 +28,31 @@ description: {
},
+status: {
+ type: DataTypes.ENUM,
+
+
+
+ values: [
+
+"Draft",
+
+
+"Active",
+
+
+"OnHold",
+
+
+"Completed",
+
+
+"Cancelled"
+
+ ],
+
+ },
+
start_date: {
type: DataTypes.DATE,
@@ -42,43 +67,11 @@ end_date: {
},
-status: {
- type: DataTypes.ENUM,
-
-
-
- values: [
-
-"Planned",
-
-
-"Active",
-
-
-"OnHold",
-
-
-"Completed",
-
-
-"Archived"
-
- ],
-
- },
-
budget: {
type: DataTypes.DECIMAL,
- },
-
-progress: {
- type: DataTypes.INTEGER,
-
-
-
},
importHash: {
@@ -116,18 +109,6 @@ progress: {
-
-
- db.projects.hasMany(db.reports, {
- as: 'reports_project',
- foreignKey: {
- name: 'projectId',
- },
- constraints: false,
- });
-
-
-
//end loop
@@ -150,6 +131,16 @@ progress: {
+ db.projects.hasMany(db.file, {
+ as: 'attachments',
+ foreignKey: 'belongsToId',
+ constraints: false,
+ scope: {
+ belongsTo: db.projects.getTableName(),
+ belongsToColumn: 'attachments',
+ },
+ });
+
db.projects.belongsTo(db.users, {
as: 'createdBy',
diff --git a/backend/src/db/models/reports.js b/backend/src/db/models/reports.js
deleted file mode 100644
index ada3c95..0000000
--- a/backend/src/db/models/reports.js
+++ /dev/null
@@ -1,116 +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 reports = sequelize.define(
- 'reports',
- {
- id: {
- type: DataTypes.UUID,
- defaultValue: DataTypes.UUIDV4,
- primaryKey: true,
- },
-
-title: {
- type: DataTypes.TEXT,
-
-
-
- },
-
-created_on: {
- type: DataTypes.DATE,
-
-
-
- },
-
-summary: {
- type: DataTypes.TEXT,
-
-
-
- },
-
- importHash: {
- type: DataTypes.STRING(255),
- allowNull: true,
- unique: true,
- },
- },
- {
- timestamps: true,
- paranoid: true,
- freezeTableName: true,
- },
- );
-
- reports.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.reports.belongsTo(db.projects, {
- as: 'project',
- foreignKey: {
- name: 'projectId',
- },
- constraints: false,
- });
-
- db.reports.belongsTo(db.users, {
- as: 'generated_by',
- foreignKey: {
- name: 'generated_byId',
- },
- constraints: false,
- });
-
-
-
- db.reports.hasMany(db.file, {
- as: 'content_file',
- foreignKey: 'belongsToId',
- constraints: false,
- scope: {
- belongsTo: db.reports.getTableName(),
- belongsToColumn: 'content_file',
- },
- });
-
-
- db.reports.belongsTo(db.users, {
- as: 'createdBy',
- });
-
- db.reports.belongsTo(db.users, {
- as: 'updatedBy',
- });
- };
-
-
-
- return reports;
-};
-
-
diff --git a/backend/src/db/models/roles.js b/backend/src/db/models/roles.js
index 696cb39..e26c222 100644
--- a/backend/src/db/models/roles.js
+++ b/backend/src/db/models/roles.js
@@ -81,10 +81,6 @@ role_customization: {
-
-
-
-
//end loop
diff --git a/backend/src/db/models/tasks.js b/backend/src/db/models/tasks.js
index e33e1b1..737a6e7 100644
--- a/backend/src/db/models/tasks.js
+++ b/backend/src/db/models/tasks.js
@@ -35,9 +35,6 @@ status: {
values: [
-"Backlog",
-
-
"ToDo",
@@ -47,10 +44,10 @@ status: {
"InReview",
-"Done",
+"Blocked",
-"Blocked"
+"Done"
],
@@ -78,18 +75,18 @@ priority: {
},
-due_date: {
- type: DataTypes.DATE,
-
-
-
- },
-
start_date: {
type: DataTypes.DATE,
+ },
+
+due_date: {
+ type: DataTypes.DATE,
+
+
+
},
estimated_hours: {
@@ -97,6 +94,13 @@ estimated_hours: {
+ },
+
+spent_hours: {
+ type: DataTypes.DECIMAL,
+
+
+
},
completed: {
@@ -135,39 +139,19 @@ completed: {
- db.tasks.hasMany(db.comments, {
- as: 'comments_task',
- foreignKey: {
- name: 'taskId',
- },
- constraints: false,
- });
-
-
- db.tasks.hasMany(db.attachments, {
- as: 'attachments_task',
- foreignKey: {
- name: 'taskId',
- },
- constraints: false,
- });
-
-
- db.tasks.hasMany(db.notifications, {
- as: 'notifications_related_task',
- foreignKey: {
- name: 'related_taskId',
- },
- constraints: false,
- });
-
-
-
//end loop
+ db.tasks.belongsTo(db.projects, {
+ as: 'project',
+ foreignKey: {
+ name: 'projectId',
+ },
+ constraints: false,
+ });
+
db.tasks.belongsTo(db.users, {
as: 'assignee',
foreignKey: {
@@ -184,17 +168,19 @@ completed: {
constraints: false,
});
- db.tasks.belongsTo(db.projects, {
- as: 'project',
- foreignKey: {
- name: 'projectId',
- },
+
+
+ db.tasks.hasMany(db.file, {
+ as: 'attachments',
+ foreignKey: 'belongsToId',
constraints: false,
+ scope: {
+ belongsTo: db.tasks.getTableName(),
+ belongsToColumn: 'attachments',
+ },
});
-
-
db.tasks.belongsTo(db.users, {
as: 'createdBy',
});
diff --git a/backend/src/db/models/team_members.js b/backend/src/db/models/team_memberships.js
similarity index 75%
rename from backend/src/db/models/team_members.js
rename to backend/src/db/models/team_memberships.js
index f8d9536..d3f6ed5 100644
--- a/backend/src/db/models/team_members.js
+++ b/backend/src/db/models/team_memberships.js
@@ -5,8 +5,8 @@ const bcrypt = require('bcrypt');
const moment = require('moment');
module.exports = function(sequelize, DataTypes) {
- const team_members = sequelize.define(
- 'team_members',
+ const team_memberships = sequelize.define(
+ 'team_memberships',
{
id: {
type: DataTypes.UUID,
@@ -14,6 +14,13 @@ module.exports = function(sequelize, DataTypes) {
primaryKey: true,
},
+member_label: {
+ type: DataTypes.TEXT,
+
+
+
+ },
+
role: {
type: DataTypes.ENUM,
@@ -30,20 +37,6 @@ role: {
},
-joined_on: {
- type: DataTypes.DATE,
-
-
-
- },
-
-display_label: {
- type: DataTypes.TEXT,
-
-
-
- },
-
importHash: {
type: DataTypes.STRING(255),
allowNull: true,
@@ -57,7 +50,7 @@ display_label: {
},
);
- team_members.associate = (db) => {
+ team_memberships.associate = (db) => {
/// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity
@@ -71,15 +64,11 @@ display_label: {
-
-
-
-
//end loop
- db.team_members.belongsTo(db.teams, {
+ db.team_memberships.belongsTo(db.teams, {
as: 'team',
foreignKey: {
name: 'teamId',
@@ -87,7 +76,7 @@ display_label: {
constraints: false,
});
- db.team_members.belongsTo(db.users, {
+ db.team_memberships.belongsTo(db.users, {
as: 'user',
foreignKey: {
name: 'userId',
@@ -98,18 +87,18 @@ display_label: {
- db.team_members.belongsTo(db.users, {
+ db.team_memberships.belongsTo(db.users, {
as: 'createdBy',
});
- db.team_members.belongsTo(db.users, {
+ db.team_memberships.belongsTo(db.users, {
as: 'updatedBy',
});
};
- return team_members;
+ return team_memberships;
};
diff --git a/backend/src/db/models/teams.js b/backend/src/db/models/teams.js
index d78b0f3..8158ba5 100644
--- a/backend/src/db/models/teams.js
+++ b/backend/src/db/models/teams.js
@@ -26,29 +26,6 @@ description: {
- },
-
-visibility: {
- type: DataTypes.ENUM,
-
-
-
- values: [
-
-"Private",
-
-
-"Public"
-
- ],
-
- },
-
-members_count: {
- type: DataTypes.INTEGER,
-
-
-
},
importHash: {
@@ -74,8 +51,8 @@ members_count: {
- db.teams.hasMany(db.team_members, {
- as: 'team_members_team',
+ db.teams.hasMany(db.team_memberships, {
+ as: 'team_memberships_team',
foreignKey: {
name: 'teamId',
},
@@ -94,35 +71,13 @@ members_count: {
-
-
-
-
//end loop
- db.teams.belongsTo(db.users, {
- as: 'owner',
- foreignKey: {
- name: 'ownerId',
- },
- constraints: false,
- });
- db.teams.hasMany(db.file, {
- as: 'avatar',
- foreignKey: 'belongsToId',
- constraints: false,
- scope: {
- belongsTo: db.teams.getTableName(),
- belongsToColumn: 'avatar',
- },
- });
-
-
db.teams.belongsTo(db.users, {
as: 'createdBy',
});
diff --git a/backend/src/db/models/users.js b/backend/src/db/models/users.js
index 2ba107d..9a8f480 100644
--- a/backend/src/db/models/users.js
+++ b/backend/src/db/models/users.js
@@ -144,17 +144,9 @@ provider: {
- db.users.hasMany(db.teams, {
- as: 'teams_owner',
- foreignKey: {
- name: 'ownerId',
- },
- constraints: false,
- });
-
- db.users.hasMany(db.team_members, {
- as: 'team_members_user',
+ db.users.hasMany(db.team_memberships, {
+ as: 'team_memberships_user',
foreignKey: {
name: 'userId',
},
@@ -188,42 +180,6 @@ provider: {
});
- db.users.hasMany(db.comments, {
- as: 'comments_author',
- foreignKey: {
- name: 'authorId',
- },
- constraints: false,
- });
-
-
- db.users.hasMany(db.attachments, {
- as: 'attachments_uploaded_by',
- foreignKey: {
- name: 'uploaded_byId',
- },
- constraints: false,
- });
-
-
- db.users.hasMany(db.notifications, {
- as: 'notifications_recipient',
- foreignKey: {
- name: 'recipientId',
- },
- constraints: false,
- });
-
-
- db.users.hasMany(db.reports, {
- as: 'reports_generated_by',
- foreignKey: {
- name: 'generated_byId',
- },
- constraints: false,
- });
-
-
//end loop
diff --git a/backend/src/db/seeders/20200430130760-user-roles.js b/backend/src/db/seeders/20200430130760-user-roles.js
index 3e0a439..fae87b8 100644
--- a/backend/src/db/seeders/20200430130760-user-roles.js
+++ b/backend/src/db/seeders/20200430130760-user-roles.js
@@ -33,11 +33,11 @@ module.exports = {
- { id: getId("ProjectOwner"), name: "Project Owner", createdAt, updatedAt },
+ { id: getId("PlatformLead"), name: "Platform Lead", createdAt, updatedAt },
- { id: getId("ProjectManager"), name: "Project Manager", createdAt, updatedAt },
+ { id: getId("ProjectLead"), name: "Project Lead", createdAt, updatedAt },
- { id: getId("TeamLead"), name: "Team Lead", createdAt, updatedAt },
+ { id: getId("TeamManager"), name: "Team Manager", createdAt, updatedAt },
{ id: getId("Contributor"), name: "Contributor", createdAt, updatedAt },
@@ -61,7 +61,7 @@ module.exports = {
}
const entities = [
- "users","roles","permissions","teams","team_members","projects","tasks","comments","attachments","notifications","reports",,
+ "users","roles","permissions","teams","team_memberships","projects","tasks",,
];
await queryInterface.bulkInsert("permissions", entities.flatMap(createPermissions));
await queryInterface.bulkInsert("permissions", [{ id: getId(`READ_API_DOCS`), createdAt, updatedAt, name: `READ_API_DOCS` }]);
@@ -90,19 +90,19 @@ await queryInterface.bulkInsert("rolesPermissionsPermissions", [
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('CREATE_USERS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('CREATE_USERS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('READ_USERS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('READ_USERS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('UPDATE_USERS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('UPDATE_USERS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('DELETE_USERS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('DELETE_USERS') },
@@ -113,12 +113,16 @@ await queryInterface.bulkInsert("rolesPermissionsPermissions", [
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('READ_USERS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("ProjectLead"), permissionId: getId('READ_USERS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("ProjectLead"), permissionId: getId('UPDATE_USERS') },
+
+ { createdAt, updatedAt, roles_permissionsId: getId("ProjectLead"), permissionId: getId('DELETE_USERS') },
+
@@ -128,10 +132,12 @@ await queryInterface.bulkInsert("rolesPermissionsPermissions", [
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('READ_USERS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("TeamManager"), permissionId: getId('READ_USERS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("TeamManager"), permissionId: getId('UPDATE_USERS') },
+
@@ -183,40 +189,19 @@ await queryInterface.bulkInsert("rolesPermissionsPermissions", [
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('CREATE_TEAMS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('CREATE_TEAMS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('READ_TEAMS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('READ_TEAMS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('UPDATE_TEAMS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('UPDATE_TEAMS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('DELETE_TEAMS') },
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('CREATE_TEAMS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('READ_TEAMS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('UPDATE_TEAMS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('DELETE_TEAMS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('DELETE_TEAMS') },
@@ -227,11 +212,34 @@ await queryInterface.bulkInsert("rolesPermissionsPermissions", [
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('READ_TEAMS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("ProjectLead"), permissionId: getId('READ_TEAMS') },
+
+
+
+ { createdAt, updatedAt, roles_permissionsId: getId("ProjectLead"), permissionId: getId('UPDATE_TEAMS') },
+
+
+
+
+
+
+ { createdAt, updatedAt, roles_permissionsId: getId("TeamManager"), permissionId: getId('CREATE_TEAMS') },
+
+
+
+ { createdAt, updatedAt, roles_permissionsId: getId("TeamManager"), permissionId: getId('READ_TEAMS') },
+
+
+
+ { createdAt, updatedAt, roles_permissionsId: getId("TeamManager"), permissionId: getId('UPDATE_TEAMS') },
+
+
+
+ { createdAt, updatedAt, roles_permissionsId: getId("TeamManager"), permissionId: getId('DELETE_TEAMS') },
@@ -280,61 +288,19 @@ await queryInterface.bulkInsert("rolesPermissionsPermissions", [
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('CREATE_TEAM_MEMBERS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('CREATE_TEAM_MEMBERSHIPS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('READ_TEAM_MEMBERS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('READ_TEAM_MEMBERSHIPS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('UPDATE_TEAM_MEMBERS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('UPDATE_TEAM_MEMBERSHIPS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('DELETE_TEAM_MEMBERS') },
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('CREATE_TEAM_MEMBERS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('READ_TEAM_MEMBERS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('UPDATE_TEAM_MEMBERS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('DELETE_TEAM_MEMBERS') },
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('CREATE_TEAM_MEMBERS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('READ_TEAM_MEMBERS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('UPDATE_TEAM_MEMBERS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('DELETE_TEAM_MEMBERS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('DELETE_TEAM_MEMBERSHIPS') },
@@ -345,7 +311,45 @@ await queryInterface.bulkInsert("rolesPermissionsPermissions", [
- { createdAt, updatedAt, roles_permissionsId: getId("Contributor"), permissionId: getId('READ_TEAM_MEMBERS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("ProjectLead"), permissionId: getId('READ_TEAM_MEMBERSHIPS') },
+
+
+
+ { createdAt, updatedAt, roles_permissionsId: getId("ProjectLead"), permissionId: getId('UPDATE_TEAM_MEMBERSHIPS') },
+
+
+
+
+
+
+
+
+
+
+ { createdAt, updatedAt, roles_permissionsId: getId("TeamManager"), permissionId: getId('CREATE_TEAM_MEMBERSHIPS') },
+
+
+
+ { createdAt, updatedAt, roles_permissionsId: getId("TeamManager"), permissionId: getId('READ_TEAM_MEMBERSHIPS') },
+
+
+
+ { createdAt, updatedAt, roles_permissionsId: getId("TeamManager"), permissionId: getId('UPDATE_TEAM_MEMBERSHIPS') },
+
+
+
+ { createdAt, updatedAt, roles_permissionsId: getId("TeamManager"), permissionId: getId('DELETE_TEAM_MEMBERSHIPS') },
+
+
+
+
+
+
+
+
+
+
+ { createdAt, updatedAt, roles_permissionsId: getId("Contributor"), permissionId: getId('READ_TEAM_MEMBERSHIPS') },
@@ -360,7 +364,7 @@ await queryInterface.bulkInsert("rolesPermissionsPermissions", [
- { createdAt, updatedAt, roles_permissionsId: getId("Viewer"), permissionId: getId('READ_TEAM_MEMBERS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("Viewer"), permissionId: getId('READ_TEAM_MEMBERSHIPS') },
@@ -383,19 +387,19 @@ await queryInterface.bulkInsert("rolesPermissionsPermissions", [
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('CREATE_PROJECTS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('CREATE_PROJECTS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('READ_PROJECTS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('READ_PROJECTS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('UPDATE_PROJECTS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('UPDATE_PROJECTS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('DELETE_PROJECTS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('DELETE_PROJECTS') },
@@ -404,19 +408,19 @@ await queryInterface.bulkInsert("rolesPermissionsPermissions", [
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('CREATE_PROJECTS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("ProjectLead"), permissionId: getId('CREATE_PROJECTS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('READ_PROJECTS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("ProjectLead"), permissionId: getId('READ_PROJECTS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('UPDATE_PROJECTS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("ProjectLead"), permissionId: getId('UPDATE_PROJECTS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('DELETE_PROJECTS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("ProjectLead"), permissionId: getId('DELETE_PROJECTS') },
@@ -425,15 +429,13 @@ await queryInterface.bulkInsert("rolesPermissionsPermissions", [
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('CREATE_PROJECTS') },
+
+
+ { createdAt, updatedAt, roles_permissionsId: getId("TeamManager"), permissionId: getId('READ_PROJECTS') },
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('READ_PROJECTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('UPDATE_PROJECTS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("TeamManager"), permissionId: getId('UPDATE_PROJECTS') },
@@ -484,19 +486,19 @@ await queryInterface.bulkInsert("rolesPermissionsPermissions", [
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('CREATE_TASKS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('CREATE_TASKS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('READ_TASKS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('READ_TASKS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('UPDATE_TASKS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('UPDATE_TASKS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('DELETE_TASKS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('DELETE_TASKS') },
@@ -505,19 +507,19 @@ await queryInterface.bulkInsert("rolesPermissionsPermissions", [
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('CREATE_TASKS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("ProjectLead"), permissionId: getId('CREATE_TASKS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('READ_TASKS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("ProjectLead"), permissionId: getId('READ_TASKS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('UPDATE_TASKS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("ProjectLead"), permissionId: getId('UPDATE_TASKS') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('DELETE_TASKS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("ProjectLead"), permissionId: getId('DELETE_TASKS') },
@@ -526,19 +528,19 @@ await queryInterface.bulkInsert("rolesPermissionsPermissions", [
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('CREATE_TASKS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("TeamManager"), permissionId: getId('CREATE_TASKS') },
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('READ_TASKS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("TeamManager"), permissionId: getId('READ_TASKS') },
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('UPDATE_TASKS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("TeamManager"), permissionId: getId('UPDATE_TASKS') },
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('DELETE_TASKS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("TeamManager"), permissionId: getId('DELETE_TASKS') },
@@ -581,436 +583,16 @@ await queryInterface.bulkInsert("rolesPermissionsPermissions", [
-
-
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('CREATE_COMMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('READ_COMMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('UPDATE_COMMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('DELETE_COMMENTS') },
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('CREATE_COMMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('READ_COMMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('UPDATE_COMMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('DELETE_COMMENTS') },
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('CREATE_COMMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('READ_COMMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('UPDATE_COMMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('DELETE_COMMENTS') },
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("Contributor"), permissionId: getId('CREATE_COMMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("Contributor"), permissionId: getId('READ_COMMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("Contributor"), permissionId: getId('UPDATE_COMMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("Contributor"), permissionId: getId('DELETE_COMMENTS') },
-
-
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("Viewer"), permissionId: getId('READ_COMMENTS') },
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('CREATE_ATTACHMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('READ_ATTACHMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('UPDATE_ATTACHMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('DELETE_ATTACHMENTS') },
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('CREATE_ATTACHMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('READ_ATTACHMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('UPDATE_ATTACHMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('DELETE_ATTACHMENTS') },
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('CREATE_ATTACHMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('READ_ATTACHMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('UPDATE_ATTACHMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('DELETE_ATTACHMENTS') },
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("Contributor"), permissionId: getId('CREATE_ATTACHMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("Contributor"), permissionId: getId('READ_ATTACHMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("Contributor"), permissionId: getId('UPDATE_ATTACHMENTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("Contributor"), permissionId: getId('DELETE_ATTACHMENTS') },
-
-
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("Viewer"), permissionId: getId('READ_ATTACHMENTS') },
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('CREATE_NOTIFICATIONS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('READ_NOTIFICATIONS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('UPDATE_NOTIFICATIONS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('DELETE_NOTIFICATIONS') },
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('CREATE_NOTIFICATIONS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('READ_NOTIFICATIONS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('UPDATE_NOTIFICATIONS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('DELETE_NOTIFICATIONS') },
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('CREATE_NOTIFICATIONS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('READ_NOTIFICATIONS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('UPDATE_NOTIFICATIONS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('DELETE_NOTIFICATIONS') },
-
-
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("Contributor"), permissionId: getId('READ_NOTIFICATIONS') },
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("Viewer"), permissionId: getId('READ_NOTIFICATIONS') },
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('CREATE_REPORTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('READ_REPORTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('UPDATE_REPORTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('DELETE_REPORTS') },
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('CREATE_REPORTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('READ_REPORTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('UPDATE_REPORTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('DELETE_REPORTS') },
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('CREATE_REPORTS') },
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('READ_REPORTS') },
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("Contributor"), permissionId: getId('READ_REPORTS') },
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("Viewer"), permissionId: getId('READ_REPORTS') },
-
-
-
-
-
-
-
-
-
-
-
-
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectOwner"), permissionId: getId('CREATE_SEARCH') },
+ { createdAt, updatedAt, roles_permissionsId: getId("PlatformLead"), permissionId: getId('CREATE_SEARCH') },
- { createdAt, updatedAt, roles_permissionsId: getId("ProjectManager"), permissionId: getId('CREATE_SEARCH') },
+ { createdAt, updatedAt, roles_permissionsId: getId("ProjectLead"), permissionId: getId('CREATE_SEARCH') },
- { createdAt, updatedAt, roles_permissionsId: getId("TeamLead"), permissionId: getId('CREATE_SEARCH') },
+ { createdAt, updatedAt, roles_permissionsId: getId("TeamManager"), permissionId: getId('CREATE_SEARCH') },
{ createdAt, updatedAt, roles_permissionsId: getId("Contributor"), permissionId: getId('CREATE_SEARCH') },
@@ -1039,10 +621,10 @@ await queryInterface.bulkInsert("rolesPermissionsPermissions", [
{ createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('UPDATE_TEAMS') },
{ createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('DELETE_TEAMS') },
- { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('CREATE_TEAM_MEMBERS') },
- { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('READ_TEAM_MEMBERS') },
- { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('UPDATE_TEAM_MEMBERS') },
- { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('DELETE_TEAM_MEMBERS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('CREATE_TEAM_MEMBERSHIPS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('READ_TEAM_MEMBERSHIPS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('UPDATE_TEAM_MEMBERSHIPS') },
+ { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('DELETE_TEAM_MEMBERSHIPS') },
{ createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('CREATE_PROJECTS') },
{ createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('READ_PROJECTS') },
@@ -1054,26 +636,6 @@ await queryInterface.bulkInsert("rolesPermissionsPermissions", [
{ createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('UPDATE_TASKS') },
{ createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('DELETE_TASKS') },
- { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('CREATE_COMMENTS') },
- { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('READ_COMMENTS') },
- { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('UPDATE_COMMENTS') },
- { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('DELETE_COMMENTS') },
-
- { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('CREATE_ATTACHMENTS') },
- { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('READ_ATTACHMENTS') },
- { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('UPDATE_ATTACHMENTS') },
- { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('DELETE_ATTACHMENTS') },
-
- { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('CREATE_NOTIFICATIONS') },
- { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('READ_NOTIFICATIONS') },
- { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('UPDATE_NOTIFICATIONS') },
- { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('DELETE_NOTIFICATIONS') },
-
- { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('CREATE_REPORTS') },
- { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('READ_REPORTS') },
- { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('UPDATE_REPORTS') },
- { createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('DELETE_REPORTS') },
-
{ createdAt, updatedAt, roles_permissionsId: getId("Administrator"), permissionId: getId('READ_API_DOCS') },
@@ -1089,8 +651,8 @@ await queryInterface.bulkInsert("rolesPermissionsPermissions", [
- await queryInterface.sequelize.query(`UPDATE "users" SET "app_roleId"='${getId("ProjectOwner")}' WHERE "email"='client@hello.com'`);
- await queryInterface.sequelize.query(`UPDATE "users" SET "app_roleId"='${getId("ProjectManager")}' WHERE "email"='john@doe.com'`);
+ await queryInterface.sequelize.query(`UPDATE "users" SET "app_roleId"='${getId("PlatformLead")}' WHERE "email"='client@hello.com'`);
+ await queryInterface.sequelize.query(`UPDATE "users" SET "app_roleId"='${getId("ProjectLead")}' WHERE "email"='john@doe.com'`);
diff --git a/backend/src/db/seeders/20231127130745-sample-data.js b/backend/src/db/seeders/20231127130745-sample-data.js
index 5ad3028..69fb926 100644
--- a/backend/src/db/seeders/20231127130745-sample-data.js
+++ b/backend/src/db/seeders/20231127130745-sample-data.js
@@ -30,20 +30,12 @@ const Users = db.users;
const Teams = db.teams;
-const TeamMembers = db.team_members;
+const TeamMemberships = db.team_memberships;
const Projects = db.projects;
const Tasks = db.tasks;
-const Comments = db.comments;
-
-const Attachments = db.attachments;
-
-const Notifications = db.notifications;
-
-const Reports = db.reports;
-
@@ -57,42 +49,14 @@ const TeamsData = [
- "name": "Core Team",
+ "name": "Core Platform",
- "description": "Cross functional core team handling product strategy and delivery",
-
-
-
-
-
-
- "visibility": "Private",
-
-
-
-
-
-
- // type code here for "images" field
-
-
-
-
-
-
- "members_count": 5,
-
-
-
-
-
-
- // type code here for "relation_one" field
+ "description": "Platform services and shared infrastructure",
@@ -110,35 +74,7 @@ const TeamsData = [
- "description": "Mobile engineers building native apps",
-
-
-
-
-
-
- "visibility": "Public",
-
-
-
-
-
-
- // type code here for "images" field
-
-
-
-
-
-
- "members_count": 3,
-
-
-
-
-
-
- // type code here for "relation_one" field
+ "description": "Native mobile applications and releases",
@@ -149,42 +85,50 @@ const TeamsData = [
- "name": "Design Team",
+ "name": "Design Studio",
- "description": "Designers focused on UX and UI",
+ "description": "Product design, UX research, and visual system",
+
+
+
+ },
+
+ {
+
+
+
+
+ "name": "Data Science",
- "visibility": "Public",
+ "description": "Analytics, ML models, and reporting",
+
+
+
+ },
+
+ {
+
+
+
+
+ "name": "Customer Success",
- // type code here for "images" field
-
-
-
-
-
-
- "members_count": 2,
-
-
-
-
-
-
- // type code here for "relation_one" field
+ "description": "Onboarding, support, and customer feedback",
@@ -194,13 +138,20 @@ const TeamsData = [
-const TeamMembersData = [
+const TeamMembershipsData = [
{
+ "member_label": "Alice - Platform Lead",
+
+
+
+
+
+
// type code here for "relation_one" field
@@ -219,20 +170,6 @@ const TeamMembersData = [
-
-
-
- "joined_on": new Date('2025-06-01T09:00:00Z'),
-
-
-
-
-
-
- "display_label": "Alice Johnson - Core Team",
-
-
-
},
{
@@ -240,6 +177,13 @@ const TeamMembersData = [
+ "member_label": "Ben - Frontend",
+
+
+
+
+
+
// type code here for "relation_one" field
@@ -258,17 +202,35 @@ const TeamMembersData = [
+ },
+
+ {
+
- "joined_on": new Date('2025-06-15T10:30:00Z'),
+ "member_label": "Carmen - Design Lead",
- "display_label": "Bob Smith - Core Team",
+ // type code here for "relation_one" field
+
+
+
+
+
+
+ // type code here for "relation_one" field
+
+
+
+
+
+
+ "role": "Member",
@@ -279,6 +241,13 @@ const TeamMembersData = [
+ "member_label": "Daniel - Data Engineer",
+
+
+
+
+
+
// type code here for "relation_one" field
@@ -297,17 +266,35 @@ const TeamMembersData = [
+ },
+
+ {
+
- "joined_on": new Date('2025-05-20T12:00:00Z'),
+ "member_label": "Eve - Customer Success",
- "display_label": "Carol Nguyen - Design Team",
+ // type code here for "relation_one" field
+
+
+
+
+
+
+ // type code here for "relation_one" field
+
+
+
+
+
+
+ "role": "Admin",
@@ -331,21 +318,155 @@ const ProjectsData = [
- "description": "Modernize the public website with updated branding and improved performance",
+ "description": "Refresh marketing site and improve conversion funnels",
- "start_date": new Date('2025-09-01T09:00:00Z'),
+ // type code here for "relation_one" field
- "end_date": new Date('2026-02-28T17:00:00Z'),
+ // type code here for "relation_one" field
+
+
+
+
+
+
+ "status": "OnHold",
+
+
+
+
+
+
+ "start_date": new Date('2025-01-06T09:00:00Z'),
+
+
+
+
+
+
+ "end_date": new Date('2025-03-15T17:00:00Z'),
+
+
+
+
+
+
+ "budget": 45000,
+
+
+
+
+
+
+ // type code here for "files" field
+
+
+
+ },
+
+ {
+
+
+
+
+ "name": "Mobile App Launch",
+
+
+
+
+
+
+ "description": "Launch iOS and Android native apps for public release",
+
+
+
+
+
+
+ // type code here for "relation_one" field
+
+
+
+
+
+
+ // type code here for "relation_one" field
+
+
+
+
+
+
+ "status": "Cancelled",
+
+
+
+
+
+
+ "start_date": new Date('2025-02-01T09:00:00Z'),
+
+
+
+
+
+
+ "end_date": new Date('2025-06-30T17:00:00Z'),
+
+
+
+
+
+
+ "budget": 120000,
+
+
+
+
+
+
+ // type code here for "files" field
+
+
+
+ },
+
+ {
+
+
+
+
+ "name": "Analytics Pipeline",
+
+
+
+
+
+
+ "description": "Implement ETL and reporting for key metrics",
+
+
+
+
+
+
+ // type code here for "relation_one" field
+
+
+
+
+
+
+ // type code here for "relation_one" field
@@ -359,28 +480,28 @@ const ProjectsData = [
- // type code here for "relation_one" field
+ "start_date": new Date('2025-01-20T10:00:00Z'),
- // type code here for "relation_one" field
+ "end_date": new Date('2025-04-01T17:00:00Z'),
- "budget": 25000.0,
+ "budget": 60000,
- "progress": 45,
+ // type code here for "files" field
@@ -391,35 +512,14 @@ const ProjectsData = [
- "name": "Mobile App V2",
+ "name": "Support Portal",
- "description": "Second major version of the mobile app with offline support",
-
-
-
-
-
-
- "start_date": new Date('2025-08-15T09:00:00Z'),
-
-
-
-
-
-
- "end_date": new Date('2026-04-30T17:00:00Z'),
-
-
-
-
-
-
- "status": "Planned",
+ "description": "Customer self service portal and knowledge base",
@@ -440,14 +540,35 @@ const ProjectsData = [
- "budget": 40000.0,
+ "status": "OnHold",
- "progress": 10,
+ "start_date": new Date('2024-11-15T09:00:00Z'),
+
+
+
+
+
+
+ "end_date": new Date('2025-05-01T17:00:00Z'),
+
+
+
+
+
+
+ "budget": 25000,
+
+
+
+
+
+
+ // type code here for "files" field
@@ -458,35 +579,14 @@ const ProjectsData = [
- "name": "Design System",
+ "name": "Marketing Campaign Q2",
- "description": "Create a shared design system and component library",
-
-
-
-
-
-
- "start_date": new Date('2025-07-01T09:00:00Z'),
-
-
-
-
-
-
- "end_date": new Date('2025-12-31T17:00:00Z'),
-
-
-
-
-
-
- "status": "Completed",
+ "description": "Quarterly campaign to boost user acquisition",
@@ -507,14 +607,35 @@ const ProjectsData = [
- "budget": 15000.0,
+ "status": "Draft",
- "progress": 60,
+ "start_date": new Date('2025-04-01T09:00:00Z'),
+
+
+
+
+
+
+ "end_date": new Date('2025-06-30T17:00:00Z'),
+
+
+
+
+
+
+ "budget": 30000,
+
+
+
+
+
+
+ // type code here for "files" field
@@ -531,14 +652,35 @@ const TasksData = [
- "title": "Landing Page Mockups",
+ "title": "Create homepage wireframes",
- "description": "Create high fidelity mockups for the new landing page",
+ "description": "Produce initial wireframes for the new homepage",
+
+
+
+
+
+
+ // type code here for "relation_one" field
+
+
+
+
+
+
+ // type code here for "relation_one" field
+
+
+
+
+
+
+ // type code here for "relation_one" field
@@ -552,49 +694,42 @@ const TasksData = [
- "priority": "High",
+ "priority": "Critical",
- // type code here for "relation_one" field
+ "start_date": new Date('2025-01-07T09:00:00Z'),
- // type code here for "relation_one" field
+ "due_date": new Date('2025-01-20T17:00:00Z'),
- // type code here for "relation_one" field
+ "estimated_hours": 40,
- "due_date": new Date('2026-01-15T17:00:00Z'),
+ "spent_hours": 12,
- "start_date": new Date('2025-12-01T09:00:00Z'),
-
-
-
-
-
-
- "estimated_hours": 40.0,
+ // type code here for "files" field
@@ -612,28 +747,14 @@ const TasksData = [
- "title": "Implement Auth API",
+ "title": "Implement auth endpoints",
- "description": "Develop authentication endpoints and token management",
-
-
-
-
-
-
- "status": "ToDo",
-
-
-
-
-
-
- "priority": "High",
+ "description": "Add token based authentication and refresh flow",
@@ -661,21 +782,49 @@ const TasksData = [
- "due_date": new Date('2026-02-01T17:00:00Z'),
+ "status": "InProgress",
- "start_date": new Date('2025-11-20T09:00:00Z'),
+ "priority": "Low",
- "estimated_hours": 80.0,
+ "start_date": new Date('2025-02-10T09:00:00Z'),
+
+
+
+
+
+
+ "due_date": new Date('2025-02-24T17:00:00Z'),
+
+
+
+
+
+
+ "estimated_hours": 32,
+
+
+
+
+
+
+ "spent_hours": 0,
+
+
+
+
+
+
+ // type code here for "files" field
@@ -693,14 +842,35 @@ const TasksData = [
- "title": "Mobile Offline Sync",
+ "title": "Schedule ETL backfill",
- "description": "Design and implement offline data synchronization for mobile",
+ "description": "Plan and run backfill for historical metrics",
+
+
+
+
+
+
+ // type code here for "relation_one" field
+
+
+
+
+
+
+ // type code here for "relation_one" field
+
+
+
+
+
+
+ // type code here for "relation_one" field
@@ -714,49 +884,42 @@ const TasksData = [
- "priority": "High",
+ "priority": "Medium",
- // type code here for "relation_one" field
+ "start_date": new Date('2025-01-25T09:00:00Z'),
- // type code here for "relation_one" field
+ "due_date": new Date('2025-02-10T17:00:00Z'),
- // type code here for "relation_one" field
+ "estimated_hours": 24,
- "due_date": new Date('2026-03-15T17:00:00Z'),
+ "spent_hours": 6,
- "start_date": new Date('2026-01-10T09:00:00Z'),
-
-
-
-
-
-
- "estimated_hours": 120.0,
+ // type code here for "files" field
@@ -769,49 +932,25 @@ const TasksData = [
},
-];
-
-
-
-const CommentsData = [
-
{
- // type code here for "relation_one" field
+ "title": "Draft support knowledge base",
- // type code here for "relation_one" field
+ "description": "Create initial articles for top customer issues",
- "content": "Initial mockups uploaded for review",
-
-
-
-
-
-
- "created_on": new Date('2025-12-05T10:20:00Z'),
-
-
-
- },
-
- {
-
-
-
-
// type code here for "relation_one" field
@@ -826,24 +965,6 @@ const CommentsData = [
- "content": "Auth endpoints draft PR is ready for review",
-
-
-
-
-
-
- "created_on": new Date('2025-11-25T15:40:00Z'),
-
-
-
- },
-
- {
-
-
-
-
// type code here for "relation_one" field
@@ -851,45 +972,42 @@ const CommentsData = [
- // type code here for "relation_one" field
+ "status": "Blocked",
- "content": "Component library includes button and form primitives",
+ "priority": "Critical",
- "created_on": new Date('2025-10-12T09:30:00Z'),
-
-
-
- },
-
-];
-
-
-
-const AttachmentsData = [
-
- {
-
-
-
-
- // type code here for "relation_one" field
+ "start_date": new Date('2024-12-01T09:00:00Z'),
- // type code here for "relation_one" field
+ "due_date": new Date('2025-01-15T17:00:00Z'),
+
+
+
+
+
+
+ "estimated_hours": 16,
+
+
+
+
+
+
+ "spent_hours": 16,
@@ -903,14 +1021,7 @@ const AttachmentsData = [
- "caption": "Landing page mockups v1",
-
-
-
-
-
-
- "uploaded_on": new Date('2025-12-05T10:25:00Z'),
+ "completed": true,
@@ -921,6 +1032,20 @@ const AttachmentsData = [
+ "title": "Prepare Q2 campaign assets",
+
+
+
+
+
+
+ "description": "Design banners and messaging for campaign channels",
+
+
+
+
+
+
// type code here for "relation_one" field
@@ -935,6 +1060,55 @@ const AttachmentsData = [
+ // type code here for "relation_one" field
+
+
+
+
+
+
+ "status": "InProgress",
+
+
+
+
+
+
+ "priority": "High",
+
+
+
+
+
+
+ "start_date": new Date('2025-03-15T09:00:00Z'),
+
+
+
+
+
+
+ "due_date": new Date('2025-04-15T17:00:00Z'),
+
+
+
+
+
+
+ "estimated_hours": 48,
+
+
+
+
+
+
+ "spent_hours": 0,
+
+
+
+
+
+
// type code here for "files" field
@@ -942,320 +1116,7 @@ const AttachmentsData = [
- "caption": "Auth API specification",
-
-
-
-
-
-
- "uploaded_on": new Date('2025-11-20T14:00:00Z'),
-
-
-
- },
-
- {
-
-
-
-
- // type code here for "relation_one" field
-
-
-
-
-
-
- // type code here for "relation_one" field
-
-
-
-
-
-
- // type code here for "files" field
-
-
-
-
-
-
- "caption": "Component demo recording",
-
-
-
-
-
-
- "uploaded_on": new Date('2025-10-15T11:10:00Z'),
-
-
-
- },
-
-];
-
-
-
-const NotificationsData = [
-
- {
-
-
-
-
- // type code here for "relation_one" field
-
-
-
-
-
-
- "message": "New review requested for Landing Page Mockups",
-
-
-
-
-
-
- // type code here for "relation_one" field
-
-
-
-
-
-
- "read": true,
-
-
-
-
-
-
- "sent_at": new Date('2025-12-05T10:30:00Z'),
-
-
-
- },
-
- {
-
-
-
-
- // type code here for "relation_one" field
-
-
-
-
-
-
- "message": "Please review the Auth API draft",
-
-
-
-
-
-
- // type code here for "relation_one" field
-
-
-
-
-
-
- "read": false,
-
-
-
-
-
-
- "sent_at": new Date('2025-11-25T15:45:00Z'),
-
-
-
- },
-
- {
-
-
-
-
- // type code here for "relation_one" field
-
-
-
-
-
-
- "message": "E2E tests are blocked in staging",
-
-
-
-
-
-
- // type code here for "relation_one" field
-
-
-
-
-
-
- "read": true,
-
-
-
-
-
-
- "sent_at": new Date('2026-01-03T08:05:00Z'),
-
-
-
- },
-
-];
-
-
-
-const ReportsData = [
-
- {
-
-
-
-
- "title": "Website Redesign Q4 Progress",
-
-
-
-
-
-
- // type code here for "relation_one" field
-
-
-
-
-
-
- // type code here for "relation_one" field
-
-
-
-
-
-
- "created_on": new Date('2026-01-01T12:00:00Z'),
-
-
-
-
-
-
- // type code here for "files" field
-
-
-
-
-
-
- "summary": "Progress update covering design and implementation milestones",
-
-
-
- },
-
- {
-
-
-
-
- "title": "Mobile App V2 Roadmap",
-
-
-
-
-
-
- // type code here for "relation_one" field
-
-
-
-
-
-
- // type code here for "relation_one" field
-
-
-
-
-
-
- "created_on": new Date('2025-10-01T08:30:00Z'),
-
-
-
-
-
-
- // type code here for "files" field
-
-
-
-
-
-
- "summary": "Roadmap and major deliverables for mobile version two",
-
-
-
- },
-
- {
-
-
-
-
- "title": "Design System Audit",
-
-
-
-
-
-
- // type code here for "relation_one" field
-
-
-
-
-
-
- // type code here for "relation_one" field
-
-
-
-
-
-
- "created_on": new Date('2025-12-01T11:45:00Z'),
-
-
-
-
-
-
- // type code here for "files" field
-
-
-
-
-
-
- "summary": "Audit of current components and recommended improvements",
+ "completed": false,
@@ -1311,168 +1172,167 @@ const ReportsData = [
-
-
-
-
-
-
-
-
- async function associateTeamWithOwner() {
-
- const relatedOwner0 = await Users.findOne({
- offset: Math.floor(Math.random() * (await Users.count())),
- });
- const Team0 = await Teams.findOne({
- order: [['id', 'ASC']],
- offset: 0
- });
- if (Team0?.setOwner)
- {
- await
- Team0.
- setOwner(relatedOwner0);
- }
-
- const relatedOwner1 = await Users.findOne({
- offset: Math.floor(Math.random() * (await Users.count())),
- });
- const Team1 = await Teams.findOne({
- order: [['id', 'ASC']],
- offset: 1
- });
- if (Team1?.setOwner)
- {
- await
- Team1.
- setOwner(relatedOwner1);
- }
-
- const relatedOwner2 = await Users.findOne({
- offset: Math.floor(Math.random() * (await Users.count())),
- });
- const Team2 = await Teams.findOne({
- order: [['id', 'ASC']],
- offset: 2
- });
- if (Team2?.setOwner)
- {
- await
- Team2.
- setOwner(relatedOwner2);
- }
-
- }
-
-
+
+
- async function associateTeamMemberWithTeam() {
+ async function associateTeamMembershipWithTeam() {
const relatedTeam0 = await Teams.findOne({
offset: Math.floor(Math.random() * (await Teams.count())),
});
- const TeamMember0 = await TeamMembers.findOne({
+ const TeamMembership0 = await TeamMemberships.findOne({
order: [['id', 'ASC']],
offset: 0
});
- if (TeamMember0?.setTeam)
+ if (TeamMembership0?.setTeam)
{
await
- TeamMember0.
+ TeamMembership0.
setTeam(relatedTeam0);
}
const relatedTeam1 = await Teams.findOne({
offset: Math.floor(Math.random() * (await Teams.count())),
});
- const TeamMember1 = await TeamMembers.findOne({
+ const TeamMembership1 = await TeamMemberships.findOne({
order: [['id', 'ASC']],
offset: 1
});
- if (TeamMember1?.setTeam)
+ if (TeamMembership1?.setTeam)
{
await
- TeamMember1.
+ TeamMembership1.
setTeam(relatedTeam1);
}
const relatedTeam2 = await Teams.findOne({
offset: Math.floor(Math.random() * (await Teams.count())),
});
- const TeamMember2 = await TeamMembers.findOne({
+ const TeamMembership2 = await TeamMemberships.findOne({
order: [['id', 'ASC']],
offset: 2
});
- if (TeamMember2?.setTeam)
+ if (TeamMembership2?.setTeam)
{
await
- TeamMember2.
+ TeamMembership2.
setTeam(relatedTeam2);
}
+ const relatedTeam3 = await Teams.findOne({
+ offset: Math.floor(Math.random() * (await Teams.count())),
+ });
+ const TeamMembership3 = await TeamMemberships.findOne({
+ order: [['id', 'ASC']],
+ offset: 3
+ });
+ if (TeamMembership3?.setTeam)
+ {
+ await
+ TeamMembership3.
+ setTeam(relatedTeam3);
+ }
+
+ const relatedTeam4 = await Teams.findOne({
+ offset: Math.floor(Math.random() * (await Teams.count())),
+ });
+ const TeamMembership4 = await TeamMemberships.findOne({
+ order: [['id', 'ASC']],
+ offset: 4
+ });
+ if (TeamMembership4?.setTeam)
+ {
+ await
+ TeamMembership4.
+ setTeam(relatedTeam4);
+ }
+
}
- async function associateTeamMemberWithUser() {
+ async function associateTeamMembershipWithUser() {
const relatedUser0 = await Users.findOne({
offset: Math.floor(Math.random() * (await Users.count())),
});
- const TeamMember0 = await TeamMembers.findOne({
+ const TeamMembership0 = await TeamMemberships.findOne({
order: [['id', 'ASC']],
offset: 0
});
- if (TeamMember0?.setUser)
+ if (TeamMembership0?.setUser)
{
await
- TeamMember0.
+ TeamMembership0.
setUser(relatedUser0);
}
const relatedUser1 = await Users.findOne({
offset: Math.floor(Math.random() * (await Users.count())),
});
- const TeamMember1 = await TeamMembers.findOne({
+ const TeamMembership1 = await TeamMemberships.findOne({
order: [['id', 'ASC']],
offset: 1
});
- if (TeamMember1?.setUser)
+ if (TeamMembership1?.setUser)
{
await
- TeamMember1.
+ TeamMembership1.
setUser(relatedUser1);
}
const relatedUser2 = await Users.findOne({
offset: Math.floor(Math.random() * (await Users.count())),
});
- const TeamMember2 = await TeamMembers.findOne({
+ const TeamMembership2 = await TeamMemberships.findOne({
order: [['id', 'ASC']],
offset: 2
});
- if (TeamMember2?.setUser)
+ if (TeamMembership2?.setUser)
{
await
- TeamMember2.
+ TeamMembership2.
setUser(relatedUser2);
}
+ const relatedUser3 = await Users.findOne({
+ offset: Math.floor(Math.random() * (await Users.count())),
+ });
+ const TeamMembership3 = await TeamMemberships.findOne({
+ order: [['id', 'ASC']],
+ offset: 3
+ });
+ if (TeamMembership3?.setUser)
+ {
+ await
+ TeamMembership3.
+ setUser(relatedUser3);
+ }
+
+ const relatedUser4 = await Users.findOne({
+ offset: Math.floor(Math.random() * (await Users.count())),
+ });
+ const TeamMembership4 = await TeamMemberships.findOne({
+ order: [['id', 'ASC']],
+ offset: 4
+ });
+ if (TeamMembership4?.setUser)
+ {
+ await
+ TeamMembership4.
+ setUser(relatedUser4);
+ }
+
}
-
-
-
-
@@ -1480,12 +1340,6 @@ const ReportsData = [
-
-
-
-
-
-
@@ -1534,6 +1388,34 @@ const ReportsData = [
setOwner(relatedOwner2);
}
+ const relatedOwner3 = await Users.findOne({
+ offset: Math.floor(Math.random() * (await Users.count())),
+ });
+ const Project3 = await Projects.findOne({
+ order: [['id', 'ASC']],
+ offset: 3
+ });
+ if (Project3?.setOwner)
+ {
+ await
+ Project3.
+ setOwner(relatedOwner3);
+ }
+
+ const relatedOwner4 = await Users.findOne({
+ offset: Math.floor(Math.random() * (await Users.count())),
+ });
+ const Project4 = await Projects.findOne({
+ order: [['id', 'ASC']],
+ offset: 4
+ });
+ if (Project4?.setOwner)
+ {
+ await
+ Project4.
+ setOwner(relatedOwner4);
+ }
+
}
@@ -1583,6 +1465,34 @@ const ReportsData = [
setTeam(relatedTeam2);
}
+ const relatedTeam3 = await Teams.findOne({
+ offset: Math.floor(Math.random() * (await Teams.count())),
+ });
+ const Project3 = await Projects.findOne({
+ order: [['id', 'ASC']],
+ offset: 3
+ });
+ if (Project3?.setTeam)
+ {
+ await
+ Project3.
+ setTeam(relatedTeam3);
+ }
+
+ const relatedTeam4 = await Teams.findOne({
+ offset: Math.floor(Math.random() * (await Teams.count())),
+ });
+ const Project4 = await Projects.findOne({
+ order: [['id', 'ASC']],
+ offset: 4
+ });
+ if (Project4?.setTeam)
+ {
+ await
+ Project4.
+ setTeam(relatedTeam4);
+ }
+
}
@@ -1590,6 +1500,12 @@ const ReportsData = [
+
+
+
+
+
+
@@ -1599,7 +1515,80 @@ const ReportsData = [
-
+
+ async function associateTaskWithProject() {
+
+ const relatedProject0 = await Projects.findOne({
+ offset: Math.floor(Math.random() * (await Projects.count())),
+ });
+ const Task0 = await Tasks.findOne({
+ order: [['id', 'ASC']],
+ offset: 0
+ });
+ if (Task0?.setProject)
+ {
+ await
+ Task0.
+ setProject(relatedProject0);
+ }
+
+ const relatedProject1 = await Projects.findOne({
+ offset: Math.floor(Math.random() * (await Projects.count())),
+ });
+ const Task1 = await Tasks.findOne({
+ order: [['id', 'ASC']],
+ offset: 1
+ });
+ if (Task1?.setProject)
+ {
+ await
+ Task1.
+ setProject(relatedProject1);
+ }
+
+ const relatedProject2 = await Projects.findOne({
+ offset: Math.floor(Math.random() * (await Projects.count())),
+ });
+ const Task2 = await Tasks.findOne({
+ order: [['id', 'ASC']],
+ offset: 2
+ });
+ if (Task2?.setProject)
+ {
+ await
+ Task2.
+ setProject(relatedProject2);
+ }
+
+ const relatedProject3 = await Projects.findOne({
+ offset: Math.floor(Math.random() * (await Projects.count())),
+ });
+ const Task3 = await Tasks.findOne({
+ order: [['id', 'ASC']],
+ offset: 3
+ });
+ if (Task3?.setProject)
+ {
+ await
+ Task3.
+ setProject(relatedProject3);
+ }
+
+ const relatedProject4 = await Projects.findOne({
+ offset: Math.floor(Math.random() * (await Projects.count())),
+ });
+ const Task4 = await Tasks.findOne({
+ order: [['id', 'ASC']],
+ offset: 4
+ });
+ if (Task4?.setProject)
+ {
+ await
+ Task4.
+ setProject(relatedProject4);
+ }
+
+ }
@@ -1648,6 +1637,34 @@ const ReportsData = [
setAssignee(relatedAssignee2);
}
+ const relatedAssignee3 = await Users.findOne({
+ offset: Math.floor(Math.random() * (await Users.count())),
+ });
+ const Task3 = await Tasks.findOne({
+ order: [['id', 'ASC']],
+ offset: 3
+ });
+ if (Task3?.setAssignee)
+ {
+ await
+ Task3.
+ setAssignee(relatedAssignee3);
+ }
+
+ const relatedAssignee4 = await Users.findOne({
+ offset: Math.floor(Math.random() * (await Users.count())),
+ });
+ const Task4 = await Tasks.findOne({
+ order: [['id', 'ASC']],
+ offset: 4
+ });
+ if (Task4?.setAssignee)
+ {
+ await
+ Task4.
+ setAssignee(relatedAssignee4);
+ }
+
}
@@ -1697,53 +1714,32 @@ const ReportsData = [
setReporter(relatedReporter2);
}
- }
-
-
-
-
- async function associateTaskWithProject() {
-
- const relatedProject0 = await Projects.findOne({
- offset: Math.floor(Math.random() * (await Projects.count())),
+ const relatedReporter3 = await Users.findOne({
+ offset: Math.floor(Math.random() * (await Users.count())),
});
- const Task0 = await Tasks.findOne({
+ const Task3 = await Tasks.findOne({
order: [['id', 'ASC']],
- offset: 0
+ offset: 3
});
- if (Task0?.setProject)
+ if (Task3?.setReporter)
{
await
- Task0.
- setProject(relatedProject0);
+ Task3.
+ setReporter(relatedReporter3);
}
- const relatedProject1 = await Projects.findOne({
- offset: Math.floor(Math.random() * (await Projects.count())),
+ const relatedReporter4 = await Users.findOne({
+ offset: Math.floor(Math.random() * (await Users.count())),
});
- const Task1 = await Tasks.findOne({
+ const Task4 = await Tasks.findOne({
order: [['id', 'ASC']],
- offset: 1
+ offset: 4
});
- if (Task1?.setProject)
+ if (Task4?.setReporter)
{
await
- Task1.
- setProject(relatedProject1);
- }
-
- const relatedProject2 = await Projects.findOne({
- offset: Math.floor(Math.random() * (await Projects.count())),
- });
- const Task2 = await Tasks.findOne({
- order: [['id', 'ASC']],
- offset: 2
- });
- if (Task2?.setProject)
- {
- await
- Task2.
- setProject(relatedProject2);
+ Task4.
+ setReporter(relatedReporter4);
}
}
@@ -1757,430 +1753,6 @@ const ReportsData = [
-
-
-
-
-
-
- async function associateCommentWithTask() {
-
- const relatedTask0 = await Tasks.findOne({
- offset: Math.floor(Math.random() * (await Tasks.count())),
- });
- const Comment0 = await Comments.findOne({
- order: [['id', 'ASC']],
- offset: 0
- });
- if (Comment0?.setTask)
- {
- await
- Comment0.
- setTask(relatedTask0);
- }
-
- const relatedTask1 = await Tasks.findOne({
- offset: Math.floor(Math.random() * (await Tasks.count())),
- });
- const Comment1 = await Comments.findOne({
- order: [['id', 'ASC']],
- offset: 1
- });
- if (Comment1?.setTask)
- {
- await
- Comment1.
- setTask(relatedTask1);
- }
-
- const relatedTask2 = await Tasks.findOne({
- offset: Math.floor(Math.random() * (await Tasks.count())),
- });
- const Comment2 = await Comments.findOne({
- order: [['id', 'ASC']],
- offset: 2
- });
- if (Comment2?.setTask)
- {
- await
- Comment2.
- setTask(relatedTask2);
- }
-
- }
-
-
-
-
- async function associateCommentWithAuthor() {
-
- const relatedAuthor0 = await Users.findOne({
- offset: Math.floor(Math.random() * (await Users.count())),
- });
- const Comment0 = await Comments.findOne({
- order: [['id', 'ASC']],
- offset: 0
- });
- if (Comment0?.setAuthor)
- {
- await
- Comment0.
- setAuthor(relatedAuthor0);
- }
-
- const relatedAuthor1 = await Users.findOne({
- offset: Math.floor(Math.random() * (await Users.count())),
- });
- const Comment1 = await Comments.findOne({
- order: [['id', 'ASC']],
- offset: 1
- });
- if (Comment1?.setAuthor)
- {
- await
- Comment1.
- setAuthor(relatedAuthor1);
- }
-
- const relatedAuthor2 = await Users.findOne({
- offset: Math.floor(Math.random() * (await Users.count())),
- });
- const Comment2 = await Comments.findOne({
- order: [['id', 'ASC']],
- offset: 2
- });
- if (Comment2?.setAuthor)
- {
- await
- Comment2.
- setAuthor(relatedAuthor2);
- }
-
- }
-
-
-
-
-
-
-
-
-
-
-
-
- async function associateAttachmentWithTask() {
-
- const relatedTask0 = await Tasks.findOne({
- offset: Math.floor(Math.random() * (await Tasks.count())),
- });
- const Attachment0 = await Attachments.findOne({
- order: [['id', 'ASC']],
- offset: 0
- });
- if (Attachment0?.setTask)
- {
- await
- Attachment0.
- setTask(relatedTask0);
- }
-
- const relatedTask1 = await Tasks.findOne({
- offset: Math.floor(Math.random() * (await Tasks.count())),
- });
- const Attachment1 = await Attachments.findOne({
- order: [['id', 'ASC']],
- offset: 1
- });
- if (Attachment1?.setTask)
- {
- await
- Attachment1.
- setTask(relatedTask1);
- }
-
- const relatedTask2 = await Tasks.findOne({
- offset: Math.floor(Math.random() * (await Tasks.count())),
- });
- const Attachment2 = await Attachments.findOne({
- order: [['id', 'ASC']],
- offset: 2
- });
- if (Attachment2?.setTask)
- {
- await
- Attachment2.
- setTask(relatedTask2);
- }
-
- }
-
-
-
-
- async function associateAttachmentWithUploaded_by() {
-
- const relatedUploaded_by0 = await Users.findOne({
- offset: Math.floor(Math.random() * (await Users.count())),
- });
- const Attachment0 = await Attachments.findOne({
- order: [['id', 'ASC']],
- offset: 0
- });
- if (Attachment0?.setUploaded_by)
- {
- await
- Attachment0.
- setUploaded_by(relatedUploaded_by0);
- }
-
- const relatedUploaded_by1 = await Users.findOne({
- offset: Math.floor(Math.random() * (await Users.count())),
- });
- const Attachment1 = await Attachments.findOne({
- order: [['id', 'ASC']],
- offset: 1
- });
- if (Attachment1?.setUploaded_by)
- {
- await
- Attachment1.
- setUploaded_by(relatedUploaded_by1);
- }
-
- const relatedUploaded_by2 = await Users.findOne({
- offset: Math.floor(Math.random() * (await Users.count())),
- });
- const Attachment2 = await Attachments.findOne({
- order: [['id', 'ASC']],
- offset: 2
- });
- if (Attachment2?.setUploaded_by)
- {
- await
- Attachment2.
- setUploaded_by(relatedUploaded_by2);
- }
-
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- async function associateNotificationWithRecipient() {
-
- const relatedRecipient0 = await Users.findOne({
- offset: Math.floor(Math.random() * (await Users.count())),
- });
- const Notification0 = await Notifications.findOne({
- order: [['id', 'ASC']],
- offset: 0
- });
- if (Notification0?.setRecipient)
- {
- await
- Notification0.
- setRecipient(relatedRecipient0);
- }
-
- const relatedRecipient1 = await Users.findOne({
- offset: Math.floor(Math.random() * (await Users.count())),
- });
- const Notification1 = await Notifications.findOne({
- order: [['id', 'ASC']],
- offset: 1
- });
- if (Notification1?.setRecipient)
- {
- await
- Notification1.
- setRecipient(relatedRecipient1);
- }
-
- const relatedRecipient2 = await Users.findOne({
- offset: Math.floor(Math.random() * (await Users.count())),
- });
- const Notification2 = await Notifications.findOne({
- order: [['id', 'ASC']],
- offset: 2
- });
- if (Notification2?.setRecipient)
- {
- await
- Notification2.
- setRecipient(relatedRecipient2);
- }
-
- }
-
-
-
-
-
-
- async function associateNotificationWithRelated_task() {
-
- const relatedRelated_task0 = await Tasks.findOne({
- offset: Math.floor(Math.random() * (await Tasks.count())),
- });
- const Notification0 = await Notifications.findOne({
- order: [['id', 'ASC']],
- offset: 0
- });
- if (Notification0?.setRelated_task)
- {
- await
- Notification0.
- setRelated_task(relatedRelated_task0);
- }
-
- const relatedRelated_task1 = await Tasks.findOne({
- offset: Math.floor(Math.random() * (await Tasks.count())),
- });
- const Notification1 = await Notifications.findOne({
- order: [['id', 'ASC']],
- offset: 1
- });
- if (Notification1?.setRelated_task)
- {
- await
- Notification1.
- setRelated_task(relatedRelated_task1);
- }
-
- const relatedRelated_task2 = await Tasks.findOne({
- offset: Math.floor(Math.random() * (await Tasks.count())),
- });
- const Notification2 = await Notifications.findOne({
- order: [['id', 'ASC']],
- offset: 2
- });
- if (Notification2?.setRelated_task)
- {
- await
- Notification2.
- setRelated_task(relatedRelated_task2);
- }
-
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- async function associateReportWithProject() {
-
- const relatedProject0 = await Projects.findOne({
- offset: Math.floor(Math.random() * (await Projects.count())),
- });
- const Report0 = await Reports.findOne({
- order: [['id', 'ASC']],
- offset: 0
- });
- if (Report0?.setProject)
- {
- await
- Report0.
- setProject(relatedProject0);
- }
-
- const relatedProject1 = await Projects.findOne({
- offset: Math.floor(Math.random() * (await Projects.count())),
- });
- const Report1 = await Reports.findOne({
- order: [['id', 'ASC']],
- offset: 1
- });
- if (Report1?.setProject)
- {
- await
- Report1.
- setProject(relatedProject1);
- }
-
- const relatedProject2 = await Projects.findOne({
- offset: Math.floor(Math.random() * (await Projects.count())),
- });
- const Report2 = await Reports.findOne({
- order: [['id', 'ASC']],
- offset: 2
- });
- if (Report2?.setProject)
- {
- await
- Report2.
- setProject(relatedProject2);
- }
-
- }
-
-
-
-
- async function associateReportWithGenerated_by() {
-
- const relatedGenerated_by0 = await Users.findOne({
- offset: Math.floor(Math.random() * (await Users.count())),
- });
- const Report0 = await Reports.findOne({
- order: [['id', 'ASC']],
- offset: 0
- });
- if (Report0?.setGenerated_by)
- {
- await
- Report0.
- setGenerated_by(relatedGenerated_by0);
- }
-
- const relatedGenerated_by1 = await Users.findOne({
- offset: Math.floor(Math.random() * (await Users.count())),
- });
- const Report1 = await Reports.findOne({
- order: [['id', 'ASC']],
- offset: 1
- });
- if (Report1?.setGenerated_by)
- {
- await
- Report1.
- setGenerated_by(relatedGenerated_by1);
- }
-
- const relatedGenerated_by2 = await Users.findOne({
- offset: Math.floor(Math.random() * (await Users.count())),
- });
- const Report2 = await Reports.findOne({
- order: [['id', 'ASC']],
- offset: 2
- });
- if (Report2?.setGenerated_by)
- {
- await
- Report2.
- setGenerated_by(relatedGenerated_by2);
- }
-
- }
@@ -2205,7 +1777,7 @@ module.exports = {
- await TeamMembers.bulkCreate(TeamMembersData);
+ await TeamMemberships.bulkCreate(TeamMembershipsData);
@@ -2218,26 +1790,6 @@ module.exports = {
await Tasks.bulkCreate(TasksData);
-
-
- await Comments.bulkCreate(CommentsData);
-
-
-
-
- await Attachments.bulkCreate(AttachmentsData);
-
-
-
-
- await Notifications.bulkCreate(NotificationsData);
-
-
-
-
- await Reports.bulkCreate(ReportsData);
-
-
await Promise.all([
@@ -2283,44 +1835,25 @@ module.exports = {
-
-
-
-
-
-
-
-
- await associateTeamWithOwner(),
-
-
-
-
-
-
-
- await associateTeamMemberWithTeam(),
-
-
-
-
- await associateTeamMemberWithUser(),
-
-
-
-
-
-
-
-
+
+ await associateTeamMembershipWithTeam(),
+
+
+ await associateTeamMembershipWithUser(),
+
+
+
+
+
+
@@ -2340,6 +1873,12 @@ module.exports = {
+
+
+
+
+
+
@@ -2348,7 +1887,8 @@ module.exports = {
-
+
+ await associateTaskWithProject(),
@@ -2362,9 +1902,6 @@ module.exports = {
-
- await associateTaskWithProject(),
-
@@ -2374,76 +1911,6 @@ module.exports = {
-
-
-
-
-
- await associateCommentWithTask(),
-
-
-
-
- await associateCommentWithAuthor(),
-
-
-
-
-
-
-
-
-
-
-
- await associateAttachmentWithTask(),
-
-
-
-
- await associateAttachmentWithUploaded_by(),
-
-
-
-
-
-
-
-
-
-
-
-
-
- await associateNotificationWithRecipient(),
-
-
-
-
-
-
- await associateNotificationWithRelated_task(),
-
-
-
-
-
-
-
-
-
-
-
-
-
- await associateReportWithProject(),
-
-
-
-
- await associateReportWithGenerated_by(),
-
-
@@ -2465,7 +1932,7 @@ module.exports = {
await queryInterface.bulkDelete('teams', null, {});
- await queryInterface.bulkDelete('team_members', null, {});
+ await queryInterface.bulkDelete('team_memberships', null, {});
await queryInterface.bulkDelete('projects', null, {});
@@ -2473,18 +1940,6 @@ module.exports = {
await queryInterface.bulkDelete('tasks', null, {});
-
- await queryInterface.bulkDelete('comments', null, {});
-
-
- await queryInterface.bulkDelete('attachments', null, {});
-
-
- await queryInterface.bulkDelete('notifications', null, {});
-
-
- await queryInterface.bulkDelete('reports', null, {});
-
},
};
\ No newline at end of file
diff --git a/backend/src/index.js b/backend/src/index.js
index 6c7d842..11701d3 100644
--- a/backend/src/index.js
+++ b/backend/src/index.js
@@ -16,12 +16,10 @@ const fileRoutes = require('./routes/file');
const searchRoutes = require('./routes/search');
const pexelsRoutes = require('./routes/pexels');
-
const openaiRoutes = require('./routes/openai');
-
const usersRoutes = require('./routes/users');
const rolesRoutes = require('./routes/roles');
@@ -30,20 +28,12 @@ const permissionsRoutes = require('./routes/permissions');
const teamsRoutes = require('./routes/teams');
-const team_membersRoutes = require('./routes/team_members');
+const team_membershipsRoutes = require('./routes/team_memberships');
const projectsRoutes = require('./routes/projects');
const tasksRoutes = require('./routes/tasks');
-const commentsRoutes = require('./routes/comments');
-
-const attachmentsRoutes = require('./routes/attachments');
-
-const notificationsRoutes = require('./routes/notifications');
-
-const reportsRoutes = require('./routes/reports');
-
const getBaseUrl = (url) => {
if (!url) return '';
@@ -55,8 +45,8 @@ const options = {
openapi: "3.0.0",
info: {
version: "1.0.0",
- title: "Team Projects Hub",
- description: "Team Projects Hub Online REST API for Testing and Prototyping application. You can perform all major operations with your entities - create, delete and etc.",
+ title: "TeamFlow Manager",
+ description: "TeamFlow Manager Online REST API for Testing and Prototyping application. You can perform all major operations with your entities - create, delete and etc.",
},
servers: [
{
@@ -110,27 +100,22 @@ app.use('/api/permissions', passport.authenticate('jwt', {session: false}), perm
app.use('/api/teams', passport.authenticate('jwt', {session: false}), teamsRoutes);
-app.use('/api/team_members', passport.authenticate('jwt', {session: false}), team_membersRoutes);
+app.use('/api/team_memberships', passport.authenticate('jwt', {session: false}), team_membershipsRoutes);
app.use('/api/projects', passport.authenticate('jwt', {session: false}), projectsRoutes);
app.use('/api/tasks', passport.authenticate('jwt', {session: false}), tasksRoutes);
-app.use('/api/comments', passport.authenticate('jwt', {session: false}), commentsRoutes);
-
-app.use('/api/attachments', passport.authenticate('jwt', {session: false}), attachmentsRoutes);
-
-app.use('/api/notifications', passport.authenticate('jwt', {session: false}), notificationsRoutes);
-
-app.use('/api/reports', passport.authenticate('jwt', {session: false}), reportsRoutes);
-
-
app.use(
'/api/openai',
passport.authenticate('jwt', { session: false }),
openaiRoutes,
);
-
+app.use(
+ '/api/ai',
+ passport.authenticate('jwt', { session: false }),
+ openaiRoutes,
+);
app.use(
'/api/search',
diff --git a/backend/src/routes/attachments.js b/backend/src/routes/attachments.js
deleted file mode 100644
index 0b4d720..0000000
--- a/backend/src/routes/attachments.js
+++ /dev/null
@@ -1,426 +0,0 @@
-
-const express = require('express');
-
-const AttachmentsService = require('../services/attachments');
-const AttachmentsDBApi = require('../db/api/attachments');
-const wrapAsync = require('../helpers').wrapAsync;
-
-
-const router = express.Router();
-
-const { parse } = require('json2csv');
-
-
-const {
- checkCrudPermissions,
-} = require('../middlewares/check-permissions');
-
-router.use(checkCrudPermissions('attachments'));
-
-
-/**
- * @swagger
- * components:
- * schemas:
- * Attachments:
- * type: object
- * properties:
-
-
-
-
- */
-
-/**
- * @swagger
- * tags:
- * name: Attachments
- * description: The Attachments managing API
- */
-
-/**
-* @swagger
-* /api/attachments:
-* post:
-* security:
-* - bearerAuth: []
-* tags: [Attachments]
-* 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/Attachments"
-* responses:
-* 200:
-* description: The item was successfully added
-* content:
-* application/json:
-* schema:
-* $ref: "#/components/schemas/Attachments"
-* 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 AttachmentsService.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: [Attachments]
- * 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/Attachments"
- * responses:
- * 200:
- * description: The items were successfully imported
- * content:
- * application/json:
- * schema:
- * $ref: "#/components/schemas/Attachments"
- * 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 AttachmentsService.bulkImport(req, res, true, link.host);
- const payload = true;
- res.status(200).send(payload);
-}));
-
-/**
- * @swagger
- * /api/attachments/{id}:
- * put:
- * security:
- * - bearerAuth: []
- * tags: [Attachments]
- * 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/Attachments"
- * required:
- * - id
- * responses:
- * 200:
- * description: The item data was successfully updated
- * content:
- * application/json:
- * schema:
- * $ref: "#/components/schemas/Attachments"
- * 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 AttachmentsService.update(req.body.data, req.body.id, req.currentUser);
- const payload = true;
- res.status(200).send(payload);
-}));
-
-/**
- * @swagger
- * /api/attachments/{id}:
- * delete:
- * security:
- * - bearerAuth: []
- * tags: [Attachments]
- * 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/Attachments"
- * 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 AttachmentsService.remove(req.params.id, req.currentUser);
- const payload = true;
- res.status(200).send(payload);
-}));
-
-/**
- * @swagger
- * /api/attachments/deleteByIds:
- * post:
- * security:
- * - bearerAuth: []
- * tags: [Attachments]
- * 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/Attachments"
- * 401:
- * $ref: "#/components/responses/UnauthorizedError"
- * 404:
- * description: Items not found
- * 500:
- * description: Some server error
- */
-router.post('/deleteByIds', wrapAsync(async (req, res) => {
- await AttachmentsService.deleteByIds(req.body.data, req.currentUser);
- const payload = true;
- res.status(200).send(payload);
- }));
-
-/**
- * @swagger
- * /api/attachments:
- * get:
- * security:
- * - bearerAuth: []
- * tags: [Attachments]
- * summary: Get all attachments
- * description: Get all attachments
- * responses:
- * 200:
- * description: Attachments list successfully received
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: "#/components/schemas/Attachments"
- * 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 currentUser = req.currentUser;
- const payload = await AttachmentsDBApi.findAll(
- req.query, { currentUser }
- );
- if (filetype && filetype === 'csv') {
- const fields = ['id',
-
-
-
- ];
- 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/attachments/count:
- * get:
- * security:
- * - bearerAuth: []
- * tags: [Attachments]
- * summary: Count all attachments
- * description: Count all attachments
- * responses:
- * 200:
- * description: Attachments count successfully received
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: "#/components/schemas/Attachments"
- * 401:
- * $ref: "#/components/responses/UnauthorizedError"
- * 404:
- * description: Data not found
- * 500:
- * description: Some server error
- */
-router.get('/count', wrapAsync(async (req, res) => {
-
- const currentUser = req.currentUser;
- const payload = await AttachmentsDBApi.findAll(
- req.query,
- null,
- { countOnly: true, currentUser }
- );
-
- res.status(200).send(payload);
-}));
-
-/**
- * @swagger
- * /api/attachments/autocomplete:
- * get:
- * security:
- * - bearerAuth: []
- * tags: [Attachments]
- * summary: Find all attachments that match search criteria
- * description: Find all attachments that match search criteria
- * responses:
- * 200:
- * description: Attachments list successfully received
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: "#/components/schemas/Attachments"
- * 401:
- * $ref: "#/components/responses/UnauthorizedError"
- * 404:
- * description: Data not found
- * 500:
- * description: Some server error
- */
-router.get('/autocomplete', async (req, res) => {
-
- const payload = await AttachmentsDBApi.findAllAutocomplete(
- req.query.query,
- req.query.limit,
- req.query.offset,
-
- );
-
- res.status(200).send(payload);
-});
-
-/**
- * @swagger
- * /api/attachments/{id}:
- * get:
- * security:
- * - bearerAuth: []
- * tags: [Attachments]
- * 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/Attachments"
- * 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 AttachmentsDBApi.findBy(
- { id: req.params.id },
- );
-
-
-
- res.status(200).send(payload);
-}));
-
-router.use('/', require('../helpers').commonErrorHandler);
-
-module.exports = router;
diff --git a/backend/src/routes/comments.js b/backend/src/routes/comments.js
deleted file mode 100644
index 3e971fe..0000000
--- a/backend/src/routes/comments.js
+++ /dev/null
@@ -1,426 +0,0 @@
-
-const express = require('express');
-
-const CommentsService = require('../services/comments');
-const CommentsDBApi = require('../db/api/comments');
-const wrapAsync = require('../helpers').wrapAsync;
-
-
-const router = express.Router();
-
-const { parse } = require('json2csv');
-
-
-const {
- checkCrudPermissions,
-} = require('../middlewares/check-permissions');
-
-router.use(checkCrudPermissions('comments'));
-
-
-/**
- * @swagger
- * components:
- * schemas:
- * Comments:
- * type: object
- * properties:
-
-
-
-
- */
-
-/**
- * @swagger
- * tags:
- * name: Comments
- * description: The Comments managing API
- */
-
-/**
-* @swagger
-* /api/comments:
-* post:
-* security:
-* - bearerAuth: []
-* tags: [Comments]
-* 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/Comments"
-* responses:
-* 200:
-* description: The item was successfully added
-* content:
-* application/json:
-* schema:
-* $ref: "#/components/schemas/Comments"
-* 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 CommentsService.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: [Comments]
- * 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/Comments"
- * responses:
- * 200:
- * description: The items were successfully imported
- * content:
- * application/json:
- * schema:
- * $ref: "#/components/schemas/Comments"
- * 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 CommentsService.bulkImport(req, res, true, link.host);
- const payload = true;
- res.status(200).send(payload);
-}));
-
-/**
- * @swagger
- * /api/comments/{id}:
- * put:
- * security:
- * - bearerAuth: []
- * tags: [Comments]
- * 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/Comments"
- * required:
- * - id
- * responses:
- * 200:
- * description: The item data was successfully updated
- * content:
- * application/json:
- * schema:
- * $ref: "#/components/schemas/Comments"
- * 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 CommentsService.update(req.body.data, req.body.id, req.currentUser);
- const payload = true;
- res.status(200).send(payload);
-}));
-
-/**
- * @swagger
- * /api/comments/{id}:
- * delete:
- * security:
- * - bearerAuth: []
- * tags: [Comments]
- * 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/Comments"
- * 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 CommentsService.remove(req.params.id, req.currentUser);
- const payload = true;
- res.status(200).send(payload);
-}));
-
-/**
- * @swagger
- * /api/comments/deleteByIds:
- * post:
- * security:
- * - bearerAuth: []
- * tags: [Comments]
- * 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/Comments"
- * 401:
- * $ref: "#/components/responses/UnauthorizedError"
- * 404:
- * description: Items not found
- * 500:
- * description: Some server error
- */
-router.post('/deleteByIds', wrapAsync(async (req, res) => {
- await CommentsService.deleteByIds(req.body.data, req.currentUser);
- const payload = true;
- res.status(200).send(payload);
- }));
-
-/**
- * @swagger
- * /api/comments:
- * get:
- * security:
- * - bearerAuth: []
- * tags: [Comments]
- * summary: Get all comments
- * description: Get all comments
- * responses:
- * 200:
- * description: Comments list successfully received
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: "#/components/schemas/Comments"
- * 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 currentUser = req.currentUser;
- const payload = await CommentsDBApi.findAll(
- req.query, { currentUser }
- );
- if (filetype && filetype === 'csv') {
- const fields = ['id',
-
-
-
- ];
- 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/comments/count:
- * get:
- * security:
- * - bearerAuth: []
- * tags: [Comments]
- * summary: Count all comments
- * description: Count all comments
- * responses:
- * 200:
- * description: Comments count successfully received
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: "#/components/schemas/Comments"
- * 401:
- * $ref: "#/components/responses/UnauthorizedError"
- * 404:
- * description: Data not found
- * 500:
- * description: Some server error
- */
-router.get('/count', wrapAsync(async (req, res) => {
-
- const currentUser = req.currentUser;
- const payload = await CommentsDBApi.findAll(
- req.query,
- null,
- { countOnly: true, currentUser }
- );
-
- res.status(200).send(payload);
-}));
-
-/**
- * @swagger
- * /api/comments/autocomplete:
- * get:
- * security:
- * - bearerAuth: []
- * tags: [Comments]
- * summary: Find all comments that match search criteria
- * description: Find all comments that match search criteria
- * responses:
- * 200:
- * description: Comments list successfully received
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: "#/components/schemas/Comments"
- * 401:
- * $ref: "#/components/responses/UnauthorizedError"
- * 404:
- * description: Data not found
- * 500:
- * description: Some server error
- */
-router.get('/autocomplete', async (req, res) => {
-
- const payload = await CommentsDBApi.findAllAutocomplete(
- req.query.query,
- req.query.limit,
- req.query.offset,
-
- );
-
- res.status(200).send(payload);
-});
-
-/**
- * @swagger
- * /api/comments/{id}:
- * get:
- * security:
- * - bearerAuth: []
- * tags: [Comments]
- * 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/Comments"
- * 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 CommentsDBApi.findBy(
- { id: req.params.id },
- );
-
-
-
- res.status(200).send(payload);
-}));
-
-router.use('/', require('../helpers').commonErrorHandler);
-
-module.exports = router;
diff --git a/backend/src/routes/notifications.js b/backend/src/routes/notifications.js
deleted file mode 100644
index 60625d6..0000000
--- a/backend/src/routes/notifications.js
+++ /dev/null
@@ -1,426 +0,0 @@
-
-const express = require('express');
-
-const NotificationsService = require('../services/notifications');
-const NotificationsDBApi = require('../db/api/notifications');
-const wrapAsync = require('../helpers').wrapAsync;
-
-
-const router = express.Router();
-
-const { parse } = require('json2csv');
-
-
-const {
- checkCrudPermissions,
-} = require('../middlewares/check-permissions');
-
-router.use(checkCrudPermissions('notifications'));
-
-
-/**
- * @swagger
- * components:
- * schemas:
- * Notifications:
- * type: object
- * properties:
-
-
-
-
- */
-
-/**
- * @swagger
- * tags:
- * name: Notifications
- * description: The Notifications managing API
- */
-
-/**
-* @swagger
-* /api/notifications:
-* post:
-* security:
-* - bearerAuth: []
-* tags: [Notifications]
-* 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/Notifications"
-* responses:
-* 200:
-* description: The item was successfully added
-* content:
-* application/json:
-* schema:
-* $ref: "#/components/schemas/Notifications"
-* 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 NotificationsService.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: [Notifications]
- * 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/Notifications"
- * responses:
- * 200:
- * description: The items were successfully imported
- * content:
- * application/json:
- * schema:
- * $ref: "#/components/schemas/Notifications"
- * 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 NotificationsService.bulkImport(req, res, true, link.host);
- const payload = true;
- res.status(200).send(payload);
-}));
-
-/**
- * @swagger
- * /api/notifications/{id}:
- * put:
- * security:
- * - bearerAuth: []
- * tags: [Notifications]
- * 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/Notifications"
- * required:
- * - id
- * responses:
- * 200:
- * description: The item data was successfully updated
- * content:
- * application/json:
- * schema:
- * $ref: "#/components/schemas/Notifications"
- * 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 NotificationsService.update(req.body.data, req.body.id, req.currentUser);
- const payload = true;
- res.status(200).send(payload);
-}));
-
-/**
- * @swagger
- * /api/notifications/{id}:
- * delete:
- * security:
- * - bearerAuth: []
- * tags: [Notifications]
- * 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/Notifications"
- * 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 NotificationsService.remove(req.params.id, req.currentUser);
- const payload = true;
- res.status(200).send(payload);
-}));
-
-/**
- * @swagger
- * /api/notifications/deleteByIds:
- * post:
- * security:
- * - bearerAuth: []
- * tags: [Notifications]
- * 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/Notifications"
- * 401:
- * $ref: "#/components/responses/UnauthorizedError"
- * 404:
- * description: Items not found
- * 500:
- * description: Some server error
- */
-router.post('/deleteByIds', wrapAsync(async (req, res) => {
- await NotificationsService.deleteByIds(req.body.data, req.currentUser);
- const payload = true;
- res.status(200).send(payload);
- }));
-
-/**
- * @swagger
- * /api/notifications:
- * get:
- * security:
- * - bearerAuth: []
- * tags: [Notifications]
- * summary: Get all notifications
- * description: Get all notifications
- * responses:
- * 200:
- * description: Notifications list successfully received
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: "#/components/schemas/Notifications"
- * 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 currentUser = req.currentUser;
- const payload = await NotificationsDBApi.findAll(
- req.query, { currentUser }
- );
- if (filetype && filetype === 'csv') {
- const fields = ['id',
-
-
-
- ];
- 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/notifications/count:
- * get:
- * security:
- * - bearerAuth: []
- * tags: [Notifications]
- * summary: Count all notifications
- * description: Count all notifications
- * responses:
- * 200:
- * description: Notifications count successfully received
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: "#/components/schemas/Notifications"
- * 401:
- * $ref: "#/components/responses/UnauthorizedError"
- * 404:
- * description: Data not found
- * 500:
- * description: Some server error
- */
-router.get('/count', wrapAsync(async (req, res) => {
-
- const currentUser = req.currentUser;
- const payload = await NotificationsDBApi.findAll(
- req.query,
- null,
- { countOnly: true, currentUser }
- );
-
- res.status(200).send(payload);
-}));
-
-/**
- * @swagger
- * /api/notifications/autocomplete:
- * get:
- * security:
- * - bearerAuth: []
- * tags: [Notifications]
- * summary: Find all notifications that match search criteria
- * description: Find all notifications that match search criteria
- * responses:
- * 200:
- * description: Notifications list successfully received
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: "#/components/schemas/Notifications"
- * 401:
- * $ref: "#/components/responses/UnauthorizedError"
- * 404:
- * description: Data not found
- * 500:
- * description: Some server error
- */
-router.get('/autocomplete', async (req, res) => {
-
- const payload = await NotificationsDBApi.findAllAutocomplete(
- req.query.query,
- req.query.limit,
- req.query.offset,
-
- );
-
- res.status(200).send(payload);
-});
-
-/**
- * @swagger
- * /api/notifications/{id}:
- * get:
- * security:
- * - bearerAuth: []
- * tags: [Notifications]
- * 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/Notifications"
- * 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 NotificationsDBApi.findBy(
- { id: req.params.id },
- );
-
-
-
- res.status(200).send(payload);
-}));
-
-router.use('/', require('../helpers').commonErrorHandler);
-
-module.exports = router;
diff --git a/backend/src/routes/openai.js b/backend/src/routes/openai.js
index 6fa17ba..2d47d9f 100644
--- a/backend/src/routes/openai.js
+++ b/backend/src/routes/openai.js
@@ -4,8 +4,21 @@ const wrapAsync = require('../helpers').wrapAsync;
const router = express.Router();
const sjs = require('sequelize-json-schema');
const { getWidget, askGpt } = require('../services/openai');
-const RolesService = require('../services/roles');
-const RolesDBApi = require("../db/api/roles");
+const { LocalAIApi } = require('../ai/LocalAIApi');
+
+const loadRolesModules = () => {
+ try {
+ return {
+ RolesService: require('../services/roles'),
+ RolesDBApi: require('../db/api/roles'),
+ };
+ } catch (error) {
+ console.error('Roles modules are missing. Advanced roles are required for this endpoint.', error);
+ const err = new Error('Roles modules are missing. Advanced roles are required for this endpoint.');
+ err.originalError = error;
+ throw err;
+ }
+};
/**
* @swagger
@@ -59,6 +72,7 @@ const RolesDBApi = require("../db/api/roles");
router.delete(
'/roles-info/:infoId',
wrapAsync(async (req, res) => {
+ const { RolesService } = loadRolesModules();
const role = await RolesService.removeRoleInfoById(
req.query.infoId,
req.query.roleId,
@@ -116,6 +130,7 @@ router.delete(
router.get(
'/info-by-key',
wrapAsync(async (req, res) => {
+ const { RolesService, RolesDBApi } = loadRolesModules();
const roleId = req.query.roleId;
const key = req.query.key;
const currentUser = req.currentUser;
@@ -124,16 +139,16 @@ router.get(
roleId,
currentUser,
);
- const role = await RolesDBApi.findBy({ id: roleId });
+ const role = await RolesDBApi.findBy({ id: roleId });
if (!role?.role_customization) {
- await Promise.all(["pie","bar"].map(async (e)=>{
+ await Promise.all(["pie", "bar"].map(async (e) => {
const schema = await sjs.getSequelizeSchema(db.sequelize, {});
const payload = {
description: `Create some cool ${e} chart`,
modelDefinition: schema.definitions,
};
const widgetId = await getWidget(payload, currentUser?.id, roleId);
- if(widgetId){
+ if (widgetId) {
await RolesService.addRoleInfo(
roleId,
currentUser?.id,
@@ -156,6 +171,7 @@ router.get(
router.post(
'/create_widget',
wrapAsync(async (req, res) => {
+ const { RolesService } = loadRolesModules();
const { description, userId, roleId } = req.body;
const currentUser = req.currentUser;
@@ -185,13 +201,13 @@ router.post(
/**
* @swagger
- * /api/openai/ask:
+ * /api/openai/response:
* post:
* security:
* - bearerAuth: []
* tags: [OpenAI]
- * summary: Ask a question to ChatGPT
- * description: Send a question to OpenAI's ChatGPT and get a response
+ * summary: Proxy a Responses API request
+ * description: Sends the payload to the Flatlogic AI proxy and returns the response.
* requestBody:
* required: true
* content:
@@ -199,12 +215,73 @@ router.post(
* schema:
* type: object
* properties:
- * question:
+ * input:
+ * type: array
+ * description: List of messages with roles and content.
+ * items:
+ * type: object
+ * properties:
+ * role:
+ * type: string
+ * content:
+ * type: string
+ * options:
+ * type: object
+ * description: Optional polling controls.
+ * properties:
+ * poll_interval:
+ * type: number
+ * poll_timeout:
+ * type: number
+ * responses:
+ * 200:
+ * description: AI response received
+ * 400:
+ * description: Invalid request
+ * 401:
+ * $ref: "#/components/responses/UnauthorizedError"
+ * 502:
+ * description: Proxy error
+ */
+router.post(
+ '/response',
+ wrapAsync(async (req, res) => {
+ const body = req.body || {};
+ const options = body.options || {};
+ const payload = { ...body };
+ delete payload.options;
+
+ const response = await LocalAIApi.createResponse(payload, options);
+
+ if (response.success) {
+ return res.status(200).send(response);
+ }
+
+ console.error('AI proxy error:', response);
+ const status = response.error === 'input_missing' ? 400 : 502;
+ return res.status(status).send(response);
+ }),
+);
+
+/**
+ * @swagger
+ * /api/openai/ask:
+ * post:
+ * security:
+ * - bearerAuth: []
+ * tags: [OpenAI]
+ * summary: Ask a question to ChatGPT
+ * description: Send a question through the Flatlogic AI proxy and get a response
+ * requestBody:
+ * required: true
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * prompt:
* type: string
* description: The question to ask ChatGPT
- * apiKey:
- * type: string
- * description: OpenAI API key
* responses:
* 200:
* description: Question successfully answered
@@ -233,7 +310,7 @@ router.post(
if (!prompt) {
return res.status(400).send({
success: false,
- error: 'Question and API key are required',
+ error: 'Prompt is required',
});
}
diff --git a/backend/src/routes/reports.js b/backend/src/routes/reports.js
deleted file mode 100644
index 299fa92..0000000
--- a/backend/src/routes/reports.js
+++ /dev/null
@@ -1,426 +0,0 @@
-
-const express = require('express');
-
-const ReportsService = require('../services/reports');
-const ReportsDBApi = require('../db/api/reports');
-const wrapAsync = require('../helpers').wrapAsync;
-
-
-const router = express.Router();
-
-const { parse } = require('json2csv');
-
-
-const {
- checkCrudPermissions,
-} = require('../middlewares/check-permissions');
-
-router.use(checkCrudPermissions('reports'));
-
-
-/**
- * @swagger
- * components:
- * schemas:
- * Reports:
- * type: object
- * properties:
-
-
-
-
- */
-
-/**
- * @swagger
- * tags:
- * name: Reports
- * description: The Reports managing API
- */
-
-/**
-* @swagger
-* /api/reports:
-* post:
-* security:
-* - bearerAuth: []
-* tags: [Reports]
-* 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/Reports"
-* responses:
-* 200:
-* description: The item was successfully added
-* content:
-* application/json:
-* schema:
-* $ref: "#/components/schemas/Reports"
-* 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 ReportsService.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: [Reports]
- * 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/Reports"
- * responses:
- * 200:
- * description: The items were successfully imported
- * content:
- * application/json:
- * schema:
- * $ref: "#/components/schemas/Reports"
- * 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 ReportsService.bulkImport(req, res, true, link.host);
- const payload = true;
- res.status(200).send(payload);
-}));
-
-/**
- * @swagger
- * /api/reports/{id}:
- * put:
- * security:
- * - bearerAuth: []
- * tags: [Reports]
- * 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/Reports"
- * required:
- * - id
- * responses:
- * 200:
- * description: The item data was successfully updated
- * content:
- * application/json:
- * schema:
- * $ref: "#/components/schemas/Reports"
- * 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 ReportsService.update(req.body.data, req.body.id, req.currentUser);
- const payload = true;
- res.status(200).send(payload);
-}));
-
-/**
- * @swagger
- * /api/reports/{id}:
- * delete:
- * security:
- * - bearerAuth: []
- * tags: [Reports]
- * 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/Reports"
- * 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 ReportsService.remove(req.params.id, req.currentUser);
- const payload = true;
- res.status(200).send(payload);
-}));
-
-/**
- * @swagger
- * /api/reports/deleteByIds:
- * post:
- * security:
- * - bearerAuth: []
- * tags: [Reports]
- * 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/Reports"
- * 401:
- * $ref: "#/components/responses/UnauthorizedError"
- * 404:
- * description: Items not found
- * 500:
- * description: Some server error
- */
-router.post('/deleteByIds', wrapAsync(async (req, res) => {
- await ReportsService.deleteByIds(req.body.data, req.currentUser);
- const payload = true;
- res.status(200).send(payload);
- }));
-
-/**
- * @swagger
- * /api/reports:
- * get:
- * security:
- * - bearerAuth: []
- * tags: [Reports]
- * summary: Get all reports
- * description: Get all reports
- * responses:
- * 200:
- * description: Reports list successfully received
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: "#/components/schemas/Reports"
- * 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 currentUser = req.currentUser;
- const payload = await ReportsDBApi.findAll(
- req.query, { currentUser }
- );
- if (filetype && filetype === 'csv') {
- const fields = ['id',
-
-
-
- ];
- 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/reports/count:
- * get:
- * security:
- * - bearerAuth: []
- * tags: [Reports]
- * summary: Count all reports
- * description: Count all reports
- * responses:
- * 200:
- * description: Reports count successfully received
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: "#/components/schemas/Reports"
- * 401:
- * $ref: "#/components/responses/UnauthorizedError"
- * 404:
- * description: Data not found
- * 500:
- * description: Some server error
- */
-router.get('/count', wrapAsync(async (req, res) => {
-
- const currentUser = req.currentUser;
- const payload = await ReportsDBApi.findAll(
- req.query,
- null,
- { countOnly: true, currentUser }
- );
-
- res.status(200).send(payload);
-}));
-
-/**
- * @swagger
- * /api/reports/autocomplete:
- * get:
- * security:
- * - bearerAuth: []
- * tags: [Reports]
- * summary: Find all reports that match search criteria
- * description: Find all reports that match search criteria
- * responses:
- * 200:
- * description: Reports list successfully received
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: "#/components/schemas/Reports"
- * 401:
- * $ref: "#/components/responses/UnauthorizedError"
- * 404:
- * description: Data not found
- * 500:
- * description: Some server error
- */
-router.get('/autocomplete', async (req, res) => {
-
- const payload = await ReportsDBApi.findAllAutocomplete(
- req.query.query,
- req.query.limit,
- req.query.offset,
-
- );
-
- res.status(200).send(payload);
-});
-
-/**
- * @swagger
- * /api/reports/{id}:
- * get:
- * security:
- * - bearerAuth: []
- * tags: [Reports]
- * 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/Reports"
- * 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 ReportsDBApi.findBy(
- { id: req.params.id },
- );
-
-
-
- res.status(200).send(payload);
-}));
-
-router.use('/', require('../helpers').commonErrorHandler);
-
-module.exports = router;
diff --git a/backend/src/routes/team_members.js b/backend/src/routes/team_memberships.js
similarity index 76%
rename from backend/src/routes/team_members.js
rename to backend/src/routes/team_memberships.js
index 1016d6c..a4109e3 100644
--- a/backend/src/routes/team_members.js
+++ b/backend/src/routes/team_memberships.js
@@ -1,8 +1,8 @@
const express = require('express');
-const Team_membersService = require('../services/team_members');
-const Team_membersDBApi = require('../db/api/team_members');
+const Team_membershipsService = require('../services/team_memberships');
+const Team_membershipsDBApi = require('../db/api/team_memberships');
const wrapAsync = require('../helpers').wrapAsync;
@@ -15,14 +15,14 @@ const {
checkCrudPermissions,
} = require('../middlewares/check-permissions');
-router.use(checkCrudPermissions('team_members'));
+router.use(checkCrudPermissions('team_memberships'));
/**
* @swagger
* components:
* schemas:
- * Team_members:
+ * Team_memberships:
* type: object
* properties:
@@ -34,17 +34,17 @@ router.use(checkCrudPermissions('team_members'));
/**
* @swagger
* tags:
- * name: Team_members
- * description: The Team_members managing API
+ * name: Team_memberships
+ * description: The Team_memberships managing API
*/
/**
* @swagger
-* /api/team_members:
+* /api/team_memberships:
* post:
* security:
* - bearerAuth: []
-* tags: [Team_members]
+* tags: [Team_memberships]
* summary: Add new item
* description: Add new item
* requestBody:
@@ -56,14 +56,14 @@ router.use(checkCrudPermissions('team_members'));
* data:
* description: Data of the updated item
* type: object
-* $ref: "#/components/schemas/Team_members"
+* $ref: "#/components/schemas/Team_memberships"
* responses:
* 200:
* description: The item was successfully added
* content:
* application/json:
* schema:
-* $ref: "#/components/schemas/Team_members"
+* $ref: "#/components/schemas/Team_memberships"
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 405:
@@ -74,7 +74,7 @@ router.use(checkCrudPermissions('team_members'));
router.post('/', wrapAsync(async (req, res) => {
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
const link = new URL(referer);
- await Team_membersService.create(req.body.data, req.currentUser, true, link.host);
+ await Team_membershipsService.create(req.body.data, req.currentUser, true, link.host);
const payload = true;
res.status(200).send(payload);
}));
@@ -85,7 +85,7 @@ router.post('/', wrapAsync(async (req, res) => {
* post:
* security:
* - bearerAuth: []
- * tags: [Team_members]
+ * tags: [Team_memberships]
* summary: Bulk import items
* description: Bulk import items
* requestBody:
@@ -98,14 +98,14 @@ router.post('/', wrapAsync(async (req, res) => {
* description: Data of the updated items
* type: array
* items:
- * $ref: "#/components/schemas/Team_members"
+ * $ref: "#/components/schemas/Team_memberships"
* responses:
* 200:
* description: The items were successfully imported
* content:
* application/json:
* schema:
- * $ref: "#/components/schemas/Team_members"
+ * $ref: "#/components/schemas/Team_memberships"
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 405:
@@ -117,18 +117,18 @@ router.post('/', wrapAsync(async (req, res) => {
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 Team_membersService.bulkImport(req, res, true, link.host);
+ await Team_membershipsService.bulkImport(req, res, true, link.host);
const payload = true;
res.status(200).send(payload);
}));
/**
* @swagger
- * /api/team_members/{id}:
+ * /api/team_memberships/{id}:
* put:
* security:
* - bearerAuth: []
- * tags: [Team_members]
+ * tags: [Team_memberships]
* summary: Update the data of the selected item
* description: Update the data of the selected item
* parameters:
@@ -151,7 +151,7 @@ router.post('/bulk-import', wrapAsync(async (req, res) => {
* data:
* description: Data of the updated item
* type: object
- * $ref: "#/components/schemas/Team_members"
+ * $ref: "#/components/schemas/Team_memberships"
* required:
* - id
* responses:
@@ -160,7 +160,7 @@ router.post('/bulk-import', wrapAsync(async (req, res) => {
* content:
* application/json:
* schema:
- * $ref: "#/components/schemas/Team_members"
+ * $ref: "#/components/schemas/Team_memberships"
* 400:
* description: Invalid ID supplied
* 401:
@@ -171,18 +171,18 @@ router.post('/bulk-import', wrapAsync(async (req, res) => {
* description: Some server error
*/
router.put('/:id', wrapAsync(async (req, res) => {
- await Team_membersService.update(req.body.data, req.body.id, req.currentUser);
+ await Team_membershipsService.update(req.body.data, req.body.id, req.currentUser);
const payload = true;
res.status(200).send(payload);
}));
/**
* @swagger
- * /api/team_members/{id}:
+ * /api/team_memberships/{id}:
* delete:
* security:
* - bearerAuth: []
- * tags: [Team_members]
+ * tags: [Team_memberships]
* summary: Delete the selected item
* description: Delete the selected item
* parameters:
@@ -198,7 +198,7 @@ router.put('/:id', wrapAsync(async (req, res) => {
* content:
* application/json:
* schema:
- * $ref: "#/components/schemas/Team_members"
+ * $ref: "#/components/schemas/Team_memberships"
* 400:
* description: Invalid ID supplied
* 401:
@@ -209,18 +209,18 @@ router.put('/:id', wrapAsync(async (req, res) => {
* description: Some server error
*/
router.delete('/:id', wrapAsync(async (req, res) => {
- await Team_membersService.remove(req.params.id, req.currentUser);
+ await Team_membershipsService.remove(req.params.id, req.currentUser);
const payload = true;
res.status(200).send(payload);
}));
/**
* @swagger
- * /api/team_members/deleteByIds:
+ * /api/team_memberships/deleteByIds:
* post:
* security:
* - bearerAuth: []
- * tags: [Team_members]
+ * tags: [Team_memberships]
* summary: Delete the selected item list
* description: Delete the selected item list
* requestBody:
@@ -238,7 +238,7 @@ router.delete('/:id', wrapAsync(async (req, res) => {
* content:
* application/json:
* schema:
- * $ref: "#/components/schemas/Team_members"
+ * $ref: "#/components/schemas/Team_memberships"
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 404:
@@ -247,29 +247,29 @@ router.delete('/:id', wrapAsync(async (req, res) => {
* description: Some server error
*/
router.post('/deleteByIds', wrapAsync(async (req, res) => {
- await Team_membersService.deleteByIds(req.body.data, req.currentUser);
+ await Team_membershipsService.deleteByIds(req.body.data, req.currentUser);
const payload = true;
res.status(200).send(payload);
}));
/**
* @swagger
- * /api/team_members:
+ * /api/team_memberships:
* get:
* security:
* - bearerAuth: []
- * tags: [Team_members]
- * summary: Get all team_members
- * description: Get all team_members
+ * tags: [Team_memberships]
+ * summary: Get all team_memberships
+ * description: Get all team_memberships
* responses:
* 200:
- * description: Team_members list successfully received
+ * description: Team_memberships list successfully received
* content:
* application/json:
* schema:
* type: array
* items:
- * $ref: "#/components/schemas/Team_members"
+ * $ref: "#/components/schemas/Team_memberships"
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 404:
@@ -281,7 +281,7 @@ router.get('/', wrapAsync(async (req, res) => {
const filetype = req.query.filetype
const currentUser = req.currentUser;
- const payload = await Team_membersDBApi.findAll(
+ const payload = await Team_membershipsDBApi.findAll(
req.query, { currentUser }
);
if (filetype && filetype === 'csv') {
@@ -307,22 +307,22 @@ router.get('/', wrapAsync(async (req, res) => {
/**
* @swagger
- * /api/team_members/count:
+ * /api/team_memberships/count:
* get:
* security:
* - bearerAuth: []
- * tags: [Team_members]
- * summary: Count all team_members
- * description: Count all team_members
+ * tags: [Team_memberships]
+ * summary: Count all team_memberships
+ * description: Count all team_memberships
* responses:
* 200:
- * description: Team_members count successfully received
+ * description: Team_memberships count successfully received
* content:
* application/json:
* schema:
* type: array
* items:
- * $ref: "#/components/schemas/Team_members"
+ * $ref: "#/components/schemas/Team_memberships"
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 404:
@@ -333,7 +333,7 @@ router.get('/', wrapAsync(async (req, res) => {
router.get('/count', wrapAsync(async (req, res) => {
const currentUser = req.currentUser;
- const payload = await Team_membersDBApi.findAll(
+ const payload = await Team_membershipsDBApi.findAll(
req.query,
null,
{ countOnly: true, currentUser }
@@ -344,22 +344,22 @@ router.get('/count', wrapAsync(async (req, res) => {
/**
* @swagger
- * /api/team_members/autocomplete:
+ * /api/team_memberships/autocomplete:
* get:
* security:
* - bearerAuth: []
- * tags: [Team_members]
- * summary: Find all team_members that match search criteria
- * description: Find all team_members that match search criteria
+ * tags: [Team_memberships]
+ * summary: Find all team_memberships that match search criteria
+ * description: Find all team_memberships that match search criteria
* responses:
* 200:
- * description: Team_members list successfully received
+ * description: Team_memberships list successfully received
* content:
* application/json:
* schema:
* type: array
* items:
- * $ref: "#/components/schemas/Team_members"
+ * $ref: "#/components/schemas/Team_memberships"
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 404:
@@ -369,7 +369,7 @@ router.get('/count', wrapAsync(async (req, res) => {
*/
router.get('/autocomplete', async (req, res) => {
- const payload = await Team_membersDBApi.findAllAutocomplete(
+ const payload = await Team_membershipsDBApi.findAllAutocomplete(
req.query.query,
req.query.limit,
req.query.offset,
@@ -381,11 +381,11 @@ router.get('/autocomplete', async (req, res) => {
/**
* @swagger
- * /api/team_members/{id}:
+ * /api/team_memberships/{id}:
* get:
* security:
* - bearerAuth: []
- * tags: [Team_members]
+ * tags: [Team_memberships]
* summary: Get selected item
* description: Get selected item
* parameters:
@@ -401,7 +401,7 @@ router.get('/autocomplete', async (req, res) => {
* content:
* application/json:
* schema:
- * $ref: "#/components/schemas/Team_members"
+ * $ref: "#/components/schemas/Team_memberships"
* 400:
* description: Invalid ID supplied
* 401:
@@ -412,7 +412,7 @@ router.get('/autocomplete', async (req, res) => {
* description: Some server error
*/
router.get('/:id', wrapAsync(async (req, res) => {
- const payload = await Team_membersDBApi.findBy(
+ const payload = await Team_membershipsDBApi.findBy(
{ id: req.params.id },
);
diff --git a/backend/src/services/attachments.js b/backend/src/services/attachments.js
deleted file mode 100644
index af8af9f..0000000
--- a/backend/src/services/attachments.js
+++ /dev/null
@@ -1,138 +0,0 @@
-const db = require('../db/models');
-const AttachmentsDBApi = require('../db/api/attachments');
-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 AttachmentsService {
- static async create(data, currentUser) {
- const transaction = await db.sequelize.transaction();
- try {
- await AttachmentsDBApi.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 AttachmentsDBApi.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 attachments = await AttachmentsDBApi.findBy(
- {id},
- {transaction},
- );
-
- if (!attachments) {
- throw new ValidationError(
- 'attachmentsNotFound',
- );
- }
-
- const updatedAttachments = await AttachmentsDBApi.update(
- id,
- data,
- {
- currentUser,
- transaction,
- },
- );
-
- await transaction.commit();
- return updatedAttachments;
-
- } catch (error) {
- await transaction.rollback();
- throw error;
- }
- };
-
- static async deleteByIds(ids, currentUser) {
- const transaction = await db.sequelize.transaction();
-
- try {
- await AttachmentsDBApi.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 AttachmentsDBApi.remove(
- id,
- {
- currentUser,
- transaction,
- },
- );
-
- await transaction.commit();
- } catch (error) {
- await transaction.rollback();
- throw error;
- }
- }
-
-
-};
-
-
diff --git a/backend/src/services/notifications.js b/backend/src/services/notifications.js
deleted file mode 100644
index 0aa0f9c..0000000
--- a/backend/src/services/notifications.js
+++ /dev/null
@@ -1,138 +0,0 @@
-const db = require('../db/models');
-const NotificationsDBApi = require('../db/api/notifications');
-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 NotificationsService {
- static async create(data, currentUser) {
- const transaction = await db.sequelize.transaction();
- try {
- await NotificationsDBApi.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 NotificationsDBApi.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 notifications = await NotificationsDBApi.findBy(
- {id},
- {transaction},
- );
-
- if (!notifications) {
- throw new ValidationError(
- 'notificationsNotFound',
- );
- }
-
- const updatedNotifications = await NotificationsDBApi.update(
- id,
- data,
- {
- currentUser,
- transaction,
- },
- );
-
- await transaction.commit();
- return updatedNotifications;
-
- } catch (error) {
- await transaction.rollback();
- throw error;
- }
- };
-
- static async deleteByIds(ids, currentUser) {
- const transaction = await db.sequelize.transaction();
-
- try {
- await NotificationsDBApi.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 NotificationsDBApi.remove(
- id,
- {
- currentUser,
- transaction,
- },
- );
-
- await transaction.commit();
- } catch (error) {
- await transaction.rollback();
- throw error;
- }
- }
-
-
-};
-
-
diff --git a/backend/src/services/notifications/list.js b/backend/src/services/notifications/list.js
index d21ba97..46a3ae0 100644
--- a/backend/src/services/notifications/list.js
+++ b/backend/src/services/notifications/list.js
@@ -1,6 +1,6 @@
const errors = {
app: {
- title: 'Team Projects Hub',
+ title: 'TeamFlow Manager',
},
auth: {
diff --git a/backend/src/services/openai.js b/backend/src/services/openai.js
index 063bed5..3793398 100644
--- a/backend/src/services/openai.js
+++ b/backend/src/services/openai.js
@@ -1,13 +1,24 @@
const axios = require('axios');
-const { v4: uuid } = require('uuid');
-const RoleService = require('./roles');
const config = require('../config');
+const { LocalAIApi } = require('../ai/LocalAIApi');
+
+const loadRoleService = () => {
+ try {
+ return require('./roles');
+ } catch (error) {
+ console.error('Role service is missing. Advanced roles are required for this operation.', error);
+ const err = new Error('Role service is missing. Advanced roles are required for this operation.');
+ err.originalError = error;
+ throw err;
+ }
+};
module.exports = class OpenAiService {
static async getWidget(payload, userId, roleId) {
+ const RoleService = loadRoleService();
const response = await axios.post(
- `${config.flHost}/${config.project_uuid}/project_customization_widgets.json`,
- payload,
+ `${config.flHost}/${config.project_uuid}/project_customization_widgets.json`,
+ payload,
);
if (response.status >= 200 && response.status < 300) {
@@ -21,47 +32,49 @@ module.exports = class OpenAiService {
}
static async askGpt(prompt) {
- if (!config.gpt_key) {
+ if (!prompt) {
return {
success: false,
- error: 'API key is required'
+ error: 'Prompt is required'
};
}
- try {
- const response = await axios.post(
- 'https://api.openai.com/v1/chat/completions',
- {
- model: 'gpt-4o',
- messages: [
- { role: 'user', content: prompt }
- ]
- },
- {
- headers: {
- 'Content-Type': 'application/json',
- 'Authorization': `Bearer ${config.gpt_key}`
- }
- }
- );
- if (response.status >= 200 && response.status < 300) {
- return {
- success: true,
- data: response.data.choices[0].message.content
- };
- } else {
- console.error('Error asking question to ChatGPT:', response.data);
- return {
- success: false,
- error: response.data
- };
+ const response = await LocalAIApi.createResponse(
+ {
+ input: [{ role: 'user', content: prompt }],
+ },
+ {
+ poll_interval: 5,
+ poll_timeout: 300,
+ },
+ );
+
+ if (response.success) {
+ let text = LocalAIApi.extractText(response);
+ if (!text) {
+ try {
+ const decoded = LocalAIApi.decodeJsonFromResponse(response);
+ text = JSON.stringify(decoded);
+ } catch (error) {
+ console.error('AI JSON decode failed:', error);
+ return {
+ success: false,
+ error: 'AI response parsing failed',
+ details: error.message || String(error),
+ };
+ }
}
- } catch (error) {
- console.error('Error asking question to ChatGPT:', error.response?.data || error.message);
return {
- success: false,
- error: error.response?.data || error.message
+ success: true,
+ data: text,
};
}
+
+ console.error('AI proxy error:', response);
+ return {
+ success: false,
+ error: response.error || response.message || 'AI proxy error',
+ response,
+ };
}
};
diff --git a/backend/src/services/reports.js b/backend/src/services/reports.js
deleted file mode 100644
index 4fcb050..0000000
--- a/backend/src/services/reports.js
+++ /dev/null
@@ -1,138 +0,0 @@
-const db = require('../db/models');
-const ReportsDBApi = require('../db/api/reports');
-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 ReportsService {
- static async create(data, currentUser) {
- const transaction = await db.sequelize.transaction();
- try {
- await ReportsDBApi.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 ReportsDBApi.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 reports = await ReportsDBApi.findBy(
- {id},
- {transaction},
- );
-
- if (!reports) {
- throw new ValidationError(
- 'reportsNotFound',
- );
- }
-
- const updatedReports = await ReportsDBApi.update(
- id,
- data,
- {
- currentUser,
- transaction,
- },
- );
-
- await transaction.commit();
- return updatedReports;
-
- } catch (error) {
- await transaction.rollback();
- throw error;
- }
- };
-
- static async deleteByIds(ids, currentUser) {
- const transaction = await db.sequelize.transaction();
-
- try {
- await ReportsDBApi.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 ReportsDBApi.remove(
- id,
- {
- currentUser,
- transaction,
- },
- );
-
- await transaction.commit();
- } catch (error) {
- await transaction.rollback();
- throw error;
- }
- }
-
-
-};
-
-
diff --git a/backend/src/services/search.js b/backend/src/services/search.js
index 44eafde..ce13465 100644
--- a/backend/src/services/search.js
+++ b/backend/src/services/search.js
@@ -78,26 +78,6 @@ module.exports = class SearchService {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -122,22 +102,6 @@ module.exports = class SearchService {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/backend/src/services/team_members.js b/backend/src/services/team_members.js
deleted file mode 100644
index 3f35cca..0000000
--- a/backend/src/services/team_members.js
+++ /dev/null
@@ -1,138 +0,0 @@
-const db = require('../db/models');
-const Team_membersDBApi = require('../db/api/team_members');
-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 Team_membersService {
- static async create(data, currentUser) {
- const transaction = await db.sequelize.transaction();
- try {
- await Team_membersDBApi.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 Team_membersDBApi.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 team_members = await Team_membersDBApi.findBy(
- {id},
- {transaction},
- );
-
- if (!team_members) {
- throw new ValidationError(
- 'team_membersNotFound',
- );
- }
-
- const updatedTeam_members = await Team_membersDBApi.update(
- id,
- data,
- {
- currentUser,
- transaction,
- },
- );
-
- await transaction.commit();
- return updatedTeam_members;
-
- } catch (error) {
- await transaction.rollback();
- throw error;
- }
- };
-
- static async deleteByIds(ids, currentUser) {
- const transaction = await db.sequelize.transaction();
-
- try {
- await Team_membersDBApi.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 Team_membersDBApi.remove(
- id,
- {
- currentUser,
- transaction,
- },
- );
-
- await transaction.commit();
- } catch (error) {
- await transaction.rollback();
- throw error;
- }
- }
-
-
-};
-
-
diff --git a/backend/src/services/comments.js b/backend/src/services/team_memberships.js
similarity index 82%
rename from backend/src/services/comments.js
rename to backend/src/services/team_memberships.js
index f570fed..54580f9 100644
--- a/backend/src/services/comments.js
+++ b/backend/src/services/team_memberships.js
@@ -1,5 +1,5 @@
const db = require('../db/models');
-const CommentsDBApi = require('../db/api/comments');
+const Team_membershipsDBApi = require('../db/api/team_memberships');
const processFile = require("../middlewares/upload");
const ValidationError = require('./notifications/errors/validation');
const csv = require('csv-parser');
@@ -11,11 +11,11 @@ const stream = require('stream');
-module.exports = class CommentsService {
+module.exports = class Team_membershipsService {
static async create(data, currentUser) {
const transaction = await db.sequelize.transaction();
try {
- await CommentsDBApi.create(
+ await Team_membershipsDBApi.create(
data,
{
currentUser,
@@ -51,7 +51,7 @@ module.exports = class CommentsService {
.on('error', (error) => reject(error));
})
- await CommentsDBApi.bulkImport(results, {
+ await Team_membershipsDBApi.bulkImport(results, {
transaction,
ignoreDuplicates: true,
validate: true,
@@ -68,18 +68,18 @@ module.exports = class CommentsService {
static async update(data, id, currentUser) {
const transaction = await db.sequelize.transaction();
try {
- let comments = await CommentsDBApi.findBy(
+ let team_memberships = await Team_membershipsDBApi.findBy(
{id},
{transaction},
);
- if (!comments) {
+ if (!team_memberships) {
throw new ValidationError(
- 'commentsNotFound',
+ 'team_membershipsNotFound',
);
}
- const updatedComments = await CommentsDBApi.update(
+ const updatedTeam_memberships = await Team_membershipsDBApi.update(
id,
data,
{
@@ -89,7 +89,7 @@ module.exports = class CommentsService {
);
await transaction.commit();
- return updatedComments;
+ return updatedTeam_memberships;
} catch (error) {
await transaction.rollback();
@@ -101,7 +101,7 @@ module.exports = class CommentsService {
const transaction = await db.sequelize.transaction();
try {
- await CommentsDBApi.deleteByIds(ids, {
+ await Team_membershipsDBApi.deleteByIds(ids, {
currentUser,
transaction,
});
@@ -117,7 +117,7 @@ module.exports = class CommentsService {
const transaction = await db.sequelize.transaction();
try {
- await CommentsDBApi.remove(
+ await Team_membershipsDBApi.remove(
id,
{
currentUser,
diff --git a/backend/watcher.js b/backend/watcher.js
index c9218d5..3796f8d 100644
--- a/backend/watcher.js
+++ b/backend/watcher.js
@@ -2,13 +2,16 @@ const chokidar = require('chokidar');
const { exec } = require('child_process');
const nodemon = require('nodemon');
+const nodeEnv = 'dev_stage';
+const childEnv = { ...process.env, NODE_ENV: nodeEnv };
+
const migrationsWatcher = chokidar.watch('./src/db/migrations', {
persistent: true,
ignoreInitial: true
});
migrationsWatcher.on('add', (filePath) => {
console.log(`[DEBUG] New migration file: ${filePath}`);
- exec('npm run db:migrate', (error, stdout, stderr) => {
+ exec('npm run db:migrate', { env: childEnv }, (error, stdout, stderr) => {
console.log(stdout);
if (error) {
console.error(stderr);
@@ -22,7 +25,7 @@ const seedersWatcher = chokidar.watch('./src/db/seeders', {
});
seedersWatcher.on('add', (filePath) => {
console.log(`[DEBUG] New seed file: ${filePath}`);
- exec('npm run db:seed', (error, stdout, stderr) => {
+ exec('npm run db:seed', { env: childEnv }, (error, stdout, stderr) => {
console.log(stdout);
if (error) {
console.error(stderr);
@@ -32,6 +35,7 @@ seedersWatcher.on('add', (filePath) => {
nodemon({
script: './src/index.js',
+ env: childEnv,
ignore: ['./src/db/migrations', './src/db/seeders'],
delay: '500'
});
@@ -42,4 +46,4 @@ nodemon.on('start', () => {
nodemon.on('restart', (files) => {
console.log('Nodemon restarted due changes in:', files);
-});
\ No newline at end of file
+});
diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml
index 634655e..8f7de8b 100644
--- a/docker/docker-compose.yml
+++ b/docker/docker-compose.yml
@@ -25,7 +25,7 @@ services:
- ./data/db:/var/lib/postgresql/data
environment:
- POSTGRES_HOST_AUTH_METHOD=trust
- - POSTGRES_DB=db_team_projects_hub
+ - POSTGRES_DB=db_teamflow_manager
ports:
- "5432:5432"
logging:
diff --git a/frontend/README.md b/frontend/README.md
index 64359be..c42fd4d 100644
--- a/frontend/README.md
+++ b/frontend/README.md
@@ -1,4 +1,4 @@
-# Team Projects Hub
+# TeamFlow Manager
## This project was generated by Flatlogic Platform.
## Install
diff --git a/frontend/next-env.d.ts b/frontend/next-env.d.ts
index 00a8785..254b73c 100644
--- a/frontend/next-env.d.ts
+++ b/frontend/next-env.d.ts
@@ -1,6 +1,6 @@
///
///
-///
+///
// NOTE: This file should not be edited
// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information.
diff --git a/frontend/src/colors.ts b/frontend/src/colors.ts
index 71e116a..ca08bb9 100644
--- a/frontend/src/colors.ts
+++ b/frontend/src/colors.ts
@@ -1,42 +1,49 @@
import type { ColorButtonKey } from './interfaces'
-export const gradientBgBase = 'bg-gradient-to-tr'
-export const colorBgBase = "bg-violet-50/50"
-export const gradientBgPurplePink = `${gradientBgBase} from-purple-400 via-pink-500 to-red-500`
-export const gradientBgViolet = `${gradientBgBase} ${colorBgBase}`
-export const gradientBgDark = `${gradientBgBase} from-dark-700 via-dark-900 to-dark-800`;
-export const gradientBgPinkRed = `${gradientBgBase} from-pink-400 via-red-500 to-yellow-500`
+// Base background color
+export const colorBgBase = 'bg-gray-100 dark:bg-gray-900'
+// No more gradients
+export const gradientBgBase = ''
+export const gradientBgPurplePink = ''
+export const gradientBgViolet = ''
+export const gradientBgDark = ''
+export const gradientBgPinkRed = ''
+
+// Simplified background colors
export const colorsBgLight = {
- white: 'bg-white text-black',
- light: ' bg-white text-black text-black dark:bg-dark-900 dark:text-white',
+ white: 'bg-white text-black dark:bg-gray-800 dark:text-white',
+ light: 'bg-gray-100 text-black dark:bg-gray-800 dark:text-white',
contrast: 'bg-gray-800 text-white dark:bg-white dark:text-black',
- success: 'bg-emerald-500 border-emerald-500 dark:bg-pavitra-blue dark:border-pavitra-blue text-white',
- danger: 'bg-red-500 border-red-500 text-white',
+ success: 'bg-green-500 border-green-500 text-white',
+ danger: 'bg-red-600 border-red-600 text-white',
warning: 'bg-yellow-500 border-yellow-500 text-white',
- info: 'bg-blue-500 border-blue-500 dark:bg-pavitra-blue dark:border-pavitra-blue text-white',
+ info: 'bg-blue-500 border-blue-500 text-white',
}
+// Simplified text colors
export const colorsText = {
- white: 'text-black dark:text-slate-100',
- light: 'text-gray-700 dark:text-slate-400',
+ white: 'text-black dark:text-gray-100',
+ light: 'text-gray-700 dark:text-gray-400',
contrast: 'dark:text-white',
- success: 'text-emerald-500',
- danger: 'text-red-500',
+ success: 'text-green-500',
+ danger: 'text-red-600',
warning: 'text-yellow-500',
info: 'text-blue-500',
-};
+}
+// Simplified outline colors
export const colorsOutline = {
- white: [colorsText.white, 'border-gray-100'].join(' '),
- light: [colorsText.light, 'border-gray-100'].join(' '),
- contrast: [colorsText.contrast, 'border-gray-900 dark:border-slate-100'].join(' '),
- success: [colorsText.success, 'border-emerald-500'].join(' '),
- danger: [colorsText.danger, 'border-red-500'].join(' '),
+ white: [colorsText.white, 'border-gray-200 dark:border-gray-700'].join(' '),
+ light: [colorsText.light, 'border-gray-200 dark:border-gray-700'].join(' '),
+ contrast: [colorsText.contrast, 'border-gray-700 dark:border-gray-200'].join(' '),
+ success: [colorsText.success, 'border-green-500'].join(' '),
+ danger: [colorsText.danger, 'border-red-600'].join(' '),
warning: [colorsText.warning, 'border-yellow-500'].join(' '),
info: [colorsText.info, 'border-blue-500'].join(' '),
-};
+}
+// Simplified button color logic
export const getButtonColor = (
color: ColorButtonKey,
isOutlined: boolean,
@@ -47,92 +54,104 @@ export const getButtonColor = (
return ''
}
- const colors = {
- ring: {
- white: 'ring-gray-200 dark:ring-gray-500',
- whiteDark: 'ring-gray-200 dark:ring-dark-500',
- lightDark: 'ring-gray-200 dark:ring-gray-500',
- contrast: 'ring-gray-300 dark:ring-gray-400',
- success: 'ring-emerald-300 dark:ring-pavitra-blue',
- danger: 'ring-red-300 dark:ring-red-700',
- warning: 'ring-yellow-300 dark:ring-yellow-700',
- info: "ring-blue-300 dark:ring-pavitra-blue",
+ const baseColors = {
+ white: {
+ bg: 'bg-white text-black',
+ border: 'border-gray-300',
+ hover: 'hover:bg-gray-50',
+ active: 'bg-gray-100',
+ ring: 'ring-gray-300',
},
- active: {
- white: 'bg-gray-100',
- whiteDark: 'bg-gray-100 dark:bg-dark-800',
- lightDark: 'bg-gray-200 dark:bg-slate-700',
- contrast: 'bg-gray-700 dark:bg-slate-100',
- success: 'bg-emerald-700 dark:bg-pavitra-blue',
- danger: 'bg-red-700 dark:bg-red-600',
- warning: 'bg-yellow-700 dark:bg-yellow-600',
- info: 'bg-blue-700 dark:bg-pavitra-blue',
+ light: {
+ bg: 'bg-gray-200 text-black',
+ border: 'border-gray-300',
+ hover: 'hover:bg-gray-300',
+ active: 'bg-gray-300',
+ ring: 'ring-gray-300',
},
- bg: {
- white: 'bg-white text-black',
- whiteDark: 'bg-white text-black dark:bg-dark-900 dark:text-white',
- lightDark: 'bg-gray-100 text-black dark:bg-slate-800 dark:text-white',
- contrast: 'bg-gray-800 text-white dark:bg-white dark:text-black',
- success: 'bg-emerald-600 dark:bg-pavitra-blue text-white',
- danger: 'bg-red-600 text-white dark:bg-red-500 ',
- warning: 'bg-yellow-600 dark:bg-yellow-500 text-white',
- info: " bg-blue-600 dark:bg-pavitra-blue text-white ",
+ contrast: {
+ bg: 'bg-gray-800 text-white',
+ border: 'border-gray-800',
+ hover: 'hover:bg-gray-700',
+ active: 'bg-gray-700',
+ ring: 'ring-gray-300',
},
- bgHover: {
- white: 'hover:bg-gray-100',
- whiteDark: 'hover:bg-gray-100 hover:dark:bg-dark-800',
- lightDark: 'hover:bg-gray-200 hover:dark:bg-slate-700',
- contrast: 'hover:bg-gray-700 hover:dark:bg-slate-100',
- success:
- 'hover:bg-emerald-700 hover:border-emerald-700 hover:dark:bg-pavitra-blue hover:dark:border-pavitra-blue',
- danger:
- 'hover:bg-red-700 hover:border-red-700 hover:dark:bg-red-600 hover:dark:border-red-600',
- warning:
- 'hover:bg-yellow-700 hover:border-yellow-700 hover:dark:bg-yellow-600 hover:dark:border-yellow-600',
- info: "hover:bg-blue-700 hover:border-blue-700 hover:dark:bg-pavitra-blue/80 hover:dark:border-pavitra-blue/80",
+ success: {
+ bg: 'bg-green-500 text-white',
+ border: 'border-green-500',
+ hover: 'hover:bg-green-600',
+ active: 'bg-green-600',
+ ring: 'ring-green-300',
},
- borders: {
- white: 'border-white',
- whiteDark: 'border-white dark:border-dark-900',
- lightDark: 'border-gray-100 dark:border-slate-800',
- contrast: 'border-gray-800 dark:border-white',
- success: 'border-emerald-600 dark:border-pavitra-blue',
- danger: 'border-red-600 dark:border-red-500',
- warning: 'border-yellow-600 dark:border-yellow-500',
- info: "border-blue-600 border-blue-600 dark:border-pavitra-blue",
+ danger: {
+ bg: 'bg-red-600 text-white',
+ border: 'border-red-600',
+ hover: 'hover:bg-red-700',
+ active: 'bg-red-700',
+ ring: 'ring-red-300',
},
- text: {
- contrast: 'dark:text-slate-100',
- success: 'text-emerald-600 dark:text-pavitra-blue',
- danger: 'text-red-600 dark:text-red-500',
- warning: 'text-yellow-600 dark:text-yellow-500',
- info: 'text-blue-600 dark:text-pavitra-blue',
+ warning: {
+ bg: 'bg-yellow-500 text-white',
+ border: 'border-yellow-500',
+ hover: 'hover:bg-yellow-600',
+ active: 'bg-yellow-600',
+ ring: 'ring-yellow-300',
},
- outlineHover: {
- contrast:
- 'hover:bg-gray-800 hover:text-gray-100 hover:dark:bg-slate-100 hover:dark:text-black',
- success: 'hover:bg-emerald-600 hover:text-white hover:text-white hover:dark:text-white hover:dark:border-pavitra-blue',
- danger:
- 'hover:bg-red-600 hover:text-white hover:text-white hover:dark:text-white hover:dark:border-red-600',
- warning:
- 'hover:bg-yellow-600 hover:text-white hover:text-white hover:dark:text-white hover:dark:border-yellow-600',
- info: "hover:bg-blue-600 hover:bg-blue-600 hover:text-white hover:dark:text-white hover:dark:border-pavitra-blue",
+ info: {
+ bg: 'bg-blue-500 text-white',
+ border: 'border-blue-500',
+ hover: 'hover:bg-blue-600',
+ active: 'bg-blue-600',
+ ring: 'ring-blue-300',
},
+ whiteDark: { // Kept for mapping, but simplified
+ bg: 'bg-white text-black',
+ border: 'border-gray-300',
+ hover: 'hover:bg-gray-50',
+ active: 'bg-gray-100',
+ ring: 'ring-gray-300',
+ },
+ lightDark: { // Kept for mapping, but simplified
+ bg: 'bg-gray-200 text-black',
+ border: 'border-gray-300',
+ hover: 'hover:bg-gray-300',
+ active: 'bg-gray-300',
+ ring: 'ring-gray-300',
+ },
+ };
+
+ const colorSet = baseColors[color] || baseColors.info; // Default to 'info'
+
+ const base = [
+ 'w-full',
+ 'inline-flex',
+ 'justify-center',
+ 'items-center',
+ 'whitespace-nowrap',
+ 'focus:outline-none',
+ 'transition-colors',
+ 'focus:ring',
+ 'duration-150',
+ 'rounded',
+ colorSet.ring,
+ ]
+
+ if (isOutlined) {
+ base.push('bg-transparent', colorSet.border, `text-${color}-500`);
+ if (hasHover) {
+ base.push(`hover:bg-${color}-500`, 'hover:text-white');
+ }
+ } else {
+ base.push(colorSet.bg, colorSet.border);
+ if (hasHover) {
+ base.push(colorSet.hover);
+ }
}
- const isOutlinedProcessed = isOutlined && ['white', 'whiteDark', 'lightDark'].indexOf(color) < 0
-
- const base = [colors.borders[color], colors.ring[color]]
-
if (isActive) {
- base.push(colors.active[color])
- } else {
- base.push(isOutlinedProcessed ? colors.text[color] : colors.bg[color])
+ base.push(colorSet.active);
}
- if (hasHover) {
- base.push(isOutlinedProcessed ? colors.outlineHover[color] : colors.bgHover[color])
- }
return base.join(' ')
-}
+}
\ No newline at end of file
diff --git a/frontend/src/components/AsideMenu.tsx b/frontend/src/components/AsideMenu.tsx
index 442dfac..9be0413 100644
--- a/frontend/src/components/AsideMenu.tsx
+++ b/frontend/src/components/AsideMenu.tsx
@@ -19,7 +19,7 @@ export default function AsideMenu({
<>
state.style.corners);
- const asideStyle = useAppSelector((state) => state.style.asideStyle)
- const asideBrandStyle = useAppSelector((state) => state.style.asideBrandStyle)
- const asideScrollbarsStyle = useAppSelector((state) => state.style.asideScrollbarsStyle)
const darkMode = useAppSelector((state) => state.style.darkMode)
const handleAsideLgCloseClick = (e: React.MouseEvent) => {
@@ -25,35 +19,23 @@ export default function AsideMenuLayer({ menu, className = '', ...props }: Props
props.onAsideLgCloseClick()
}
-
return (