Initial commit: Angular frontend and Expressjs backend

This commit is contained in:
chamikaJ
2024-05-17 09:32:30 +05:30
parent eb0a0d77d6
commit 298ca6beeb
3548 changed files with 193558 additions and 3 deletions

View File

View File

@@ -0,0 +1,17 @@
import {IPassportSession} from "../interfaces/passport-session";
export class AuthResponse {
private authenticated = false;
private user: IPassportSession | null = null;
private title: string | null = null;
private auth_error: string | null = null;
private message: string | null = null;
constructor(title: string | null, authenticated: boolean, user: IPassportSession | null, auth_error: string | null, message: string | null) {
this.title = title;
this.authenticated = !!authenticated;
this.user = user;
this.auth_error = auth_error;
this.message = message;
}
}

View File

@@ -0,0 +1,166 @@
import moment from "moment";
import db from "../config/db";
import ReportingOverviewBase from "../controllers/reporting/overview/reporting-overview-base";
import { formatDuration, getColor, int } from "../shared/utils";
export class ReportingExportModel extends ReportingOverviewBase {
public static async getMembersByTeam(teamId: string | null) {
const q = `
SELECT team_member_id AS id,
name,
email,
(SELECT COUNT(*)
FROM project_members
WHERE project_members.team_member_id = team_member_info_view.team_member_id) AS projects,
(SELECT COUNT(*)
FROM tasks_assignees
WHERE tasks_assignees.team_member_id = team_member_info_view.team_member_id) AS tasks,
(SELECT COUNT(*)
FROM tasks_assignees
WHERE tasks_assignees.team_member_id = team_member_info_view.team_member_id
AND is_overdue(task_id) IS TRUE) AS overdue,
(SELECT COUNT(*)
FROM tasks_assignees
WHERE tasks_assignees.team_member_id = team_member_info_view.team_member_id
AND task_id IN (SELECT id
FROM tasks
WHERE is_completed(tasks.status_id, tasks.project_id))) AS completed,
(SELECT COUNT(*)
FROM tasks_assignees
WHERE tasks_assignees.team_member_id = team_member_info_view.team_member_id
AND task_id IN (SELECT id
FROM tasks
WHERE is_doing(tasks.status_id, tasks.project_id))) AS ongoing
FROM team_member_info_view
WHERE team_id = $1
ORDER BY name;
`;
const result = await db.query(q, [teamId]);
return result.rows;
}
public static async getProjectMembers(projectId: string) {
const q = `
SELECT pm.id,
pm.team_member_id,
(SELECT name FROM team_member_info_view WHERE team_member_id = pm.team_member_id) AS name,
COUNT(ta.task_id) AS tasks_count,
COUNT(CASE WHEN is_completed(t.status_id, t.project_id) IS TRUE THEN 1 END) AS completed,
COUNT(CASE WHEN is_completed(t.status_id, t.project_id) IS FALSE THEN 1 END) AS incompleted,
COUNT(CASE WHEN is_overdue(t.id) THEN 1 END) AS overdue,
(SELECT SUM(time_spent)
FROM task_work_log twl
WHERE user_id =
(SELECT user_id FROM team_member_info_view WHERE team_member_id = pm.team_member_id)
AND twl.task_id IN (SELECT id FROM tasks WHERE project_id = pm.project_id)) AS time_logged
FROM project_members pm
LEFT JOIN tasks_assignees ta
ON pm.id = ta.project_member_id AND ta.team_member_id = pm.team_member_id
LEFT JOIN tasks t ON ta.task_id = t.id
WHERE pm.project_id = $1
GROUP BY pm.id
ORDER BY name
`;
const result = await db.query(q, [projectId]);
const total = await this.getTotalTasksCount(projectId);
for (const member of result.rows) {
member.tasks_count = int(member.tasks_count);
member.completed = int(member.completed);
member.incompleted = int(member.incompleted);
member.overdue = int(member.overdue);
member.contribution = this.getPercentage(member.tasks_count, total);
member.progress = this.getPercentage(member.completed, member.tasks_count);
member.time_logged = formatDuration(moment.duration(int(member.time_logged) || "0", "seconds"));
}
return result.rows;
}
public static async getMemberTasks(teamMemberId: string, projectId: string | null, onlySingleMember: string, key: string, dateRange: string[] | [], includeArchived: boolean, userId: string) {
const projectFilter = projectId ? ` AND t.project_id = $2` : "";
let activityLogDurationFilterClause = ``;
let archivedClause = ``;
if (onlySingleMember === "true") {
activityLogDurationFilterClause = this.activityLogDurationFilter(key, dateRange);
archivedClause = includeArchived ? "" : `AND t.project_id NOT IN (SELECT project_id FROM archived_projects WHERE project_id = t.project_id AND archived_projects.user_id = '${userId}')`;
}
const q = `
WITH work_log AS (SELECT task_id, SUM(time_spent) AS total_time_spent
FROM task_work_log
GROUP BY task_id)
SELECT t.id,
t.name,
t.project_id,
t.parent_task_id,
t.parent_task_id IS NOT NULL AS is_sub_task,
(SELECT name FROM projects WHERE id = t.project_id) AS project_name,
(SELECT name
FROM teams
WHERE id = (SELECT team_id FROM projects WHERE projects.id = t.project_id)) AS team_name,
(CASE
WHEN (CURRENT_DATE::DATE > end_date::DATE AND
status_id IN (SELECT id
FROM task_statuses
WHERE project_id = t.project_id
AND category_id IN
(SELECT id FROM sys_task_status_categories WHERE is_done IS FALSE)))
THEN CURRENT_DATE::DATE - end_date::DATE
ELSE 0 END) AS days_overdue,
tp.name AS priority_name,
tp.color_code AS priority_color,
ts.name AS status_name,
sc.color_code AS status_color,
t.end_date,
t.completed_at,
(total_minutes * 60) AS total_minutes,
(work_log.total_time_spent - (total_minutes * 60)) AS overlogged_time,
(SELECT SUM(time_spent)
FROM task_work_log twl
WHERE team_member_id = ta.team_member_id
AND twl.task_id = t.id
AND twl.task_id IN
(SELECT id FROM tasks WHERE tasks.project_id = t.project_id)) AS time_logged
FROM tasks t
JOIN tasks_assignees ta ON t.id = ta.task_id
LEFT JOIN work_log ON work_log.task_id = t.id
LEFT JOIN task_priorities tp ON t.priority_id = tp.id
LEFT JOIN task_statuses ts ON t.status_id = ts.id
LEFT JOIN sys_task_status_categories sc ON ts.category_id = sc.id
WHERE ta.team_member_id = $1 ${projectFilter} ${archivedClause}
ORDER BY t.end_date DESC;`;
const params = projectId ? [teamMemberId, projectId] : [teamMemberId];
const result = await db.query(q, params);
for (const project of result.rows) {
project.project_color = getColor(project.project_name);
// estimated time
project.estimated_string = formatDuration(moment.duration(~~(project.total_minutes), "seconds"));
// logged time
project.time_spent_string = formatDuration(moment.duration(~~(project.time_logged), "seconds"));
// overlogged_time
project.overlogged_time = formatDuration(moment.duration(~~(project.overlogged_time), "seconds"));
project.completed_date = project.completed_at ? project.completed_at : null;
}
return result.rows;
}
}

View File

@@ -0,0 +1,22 @@
export class ServerResponse<T> {
public done: boolean;
public body: T | null;
public title: string | null = null;
public message: string | null;
constructor(done: boolean, body: T, message: string | null = null) {
this.done = !!done;
this.body = body === null || body === undefined ? null : body;
this.message = message?.toString().trim() ?? null;
}
public withTitle(title: string) {
this.title = title;
return this;
}
public setMessage(message: string) {
this.message = message;
return this;
}
}