feat: Implement internationalization for task management components

- Added translation support for task-related strings in ProjectTaskForm and ProjectTasksSection components.
- Integrated translation for navigation items in the Navigation component.
- Created ProjectCalendarWidget component with Polish translations for project statuses and deadlines.
- Developed Tooltip component for enhanced user experience with tooltips.
- Established a field change history logging system in the database with associated queries.
- Enhanced task update logging to include translated status and priority changes.
- Introduced server-side translations for system messages to improve localization.
This commit is contained in:
2025-09-11 15:49:07 +02:00
parent 50adc50a24
commit 0dd988730f
24 changed files with 1945 additions and 114 deletions

View File

@@ -0,0 +1,94 @@
import db from "../db.js";
/**
* Log a field change to the history table
*/
export function logFieldChange(tableName, recordId, fieldName, oldValue, newValue, changedBy = null, reason = null) {
// Don't log if values are the same
if (oldValue === newValue) return null;
const stmt = db.prepare(`
INSERT INTO field_change_history
(table_name, record_id, field_name, old_value, new_value, changed_by, change_reason)
VALUES (?, ?, ?, ?, ?, ?, ?)
`);
return stmt.run(
tableName,
recordId,
fieldName,
oldValue || null,
newValue || null,
changedBy,
reason
);
}
/**
* Get field change history for a specific field
*/
export function getFieldHistory(tableName, recordId, fieldName) {
const stmt = db.prepare(`
SELECT
fch.*,
u.name as changed_by_name,
u.username as changed_by_username
FROM field_change_history fch
LEFT JOIN users u ON fch.changed_by = u.id
WHERE fch.table_name = ? AND fch.record_id = ? AND fch.field_name = ?
ORDER BY fch.changed_at DESC
`);
return stmt.all(tableName, recordId, fieldName);
}
/**
* Get all field changes for a specific record
*/
export function getAllFieldHistory(tableName, recordId) {
const stmt = db.prepare(`
SELECT
fch.*,
u.name as changed_by_name,
u.username as changed_by_username
FROM field_change_history fch
LEFT JOIN users u ON fch.changed_by = u.id
WHERE fch.table_name = ? AND fch.record_id = ?
ORDER BY fch.changed_at DESC, fch.field_name ASC
`);
return stmt.all(tableName, recordId);
}
/**
* Check if a field has any change history
*/
export function hasFieldHistory(tableName, recordId, fieldName) {
const stmt = db.prepare(`
SELECT COUNT(*) as count
FROM field_change_history
WHERE table_name = ? AND record_id = ? AND field_name = ?
`);
const result = stmt.get(tableName, recordId, fieldName);
return result.count > 0;
}
/**
* Get the most recent change for a field
*/
export function getLatestFieldChange(tableName, recordId, fieldName) {
const stmt = db.prepare(`
SELECT
fch.*,
u.name as changed_by_name,
u.username as changed_by_username
FROM field_change_history fch
LEFT JOIN users u ON fch.changed_by = u.id
WHERE fch.table_name = ? AND fch.record_id = ? AND fch.field_name = ?
ORDER BY fch.changed_at DESC
LIMIT 1
`);
return stmt.get(tableName, recordId, fieldName);
}

View File

@@ -6,7 +6,7 @@ export function getNotesByProjectId(project_id) {
`
SELECT n.*,
u.name as created_by_name,
u.email as created_by_email
u.username as created_by_username
FROM notes n
LEFT JOIN users u ON n.created_by = u.id
WHERE n.project_id = ?
@@ -31,7 +31,7 @@ export function getNotesByTaskId(task_id) {
`
SELECT n.*,
u.name as created_by_name,
u.email as created_by_email
u.username as created_by_username
FROM notes n
LEFT JOIN users u ON n.created_by = u.id
WHERE n.task_id = ?
@@ -64,7 +64,7 @@ export function getAllNotesWithUsers() {
`
SELECT n.*,
u.name as created_by_name,
u.email as created_by_email,
u.username as created_by_username,
p.project_name,
COALESCE(pt.custom_task_name, t.name) as task_name
FROM notes n
@@ -85,7 +85,7 @@ export function getNotesByCreator(userId) {
`
SELECT n.*,
u.name as created_by_name,
u.email as created_by_email,
u.username as created_by_username,
p.project_name,
COALESCE(pt.custom_task_name, t.name) as task_name
FROM notes n

View File

@@ -1,5 +1,6 @@
import db from "../db.js";
import { addNoteToTask } from "./notes.js";
import { getUserLanguage, serverT, translateStatus, translatePriority } from "../serverTranslations.js";
// Get all task templates (for dropdown selection)
export function getAllTaskTemplates() {
@@ -182,8 +183,10 @@ export function updateProjectTaskStatus(taskId, status, userId = null) {
// Add system note for status change (only if status actually changed)
if (result.changes > 0 && oldStatus !== status) {
const taskName = currentTask.task_name || "Unknown task";
const logMessage = `Status changed from "${oldStatus}" to "${status}"`;
const language = getUserLanguage(); // Default to Polish for now
const fromStatus = translateStatus(oldStatus, language);
const toStatus = translateStatus(status, language);
const logMessage = `${serverT("Status changed from", language)} "${fromStatus}" ${serverT("to", language)} "${toStatus}"`;
addNoteToTask(taskId, logMessage, true, userId);
}
@@ -359,41 +362,48 @@ export function updateProjectTask(taskId, updates, userId = null) {
// Log the update
if (userId) {
const language = getUserLanguage(); // Default to Polish for now
const changes = [];
if (
updates.priority !== undefined &&
updates.priority !== currentTask.priority
) {
const oldPriority = translatePriority(currentTask.priority, language) || serverT("None", language);
const newPriority = translatePriority(updates.priority, language) || serverT("None", language);
changes.push(
`Priority: ${currentTask.priority || "None"}${
updates.priority || "None"
}`
`${serverT("Priority", language)}: ${oldPriority}${newPriority}`
);
}
if (updates.status !== undefined && updates.status !== currentTask.status) {
const oldStatus = translateStatus(currentTask.status, language) || serverT("None", language);
const newStatus = translateStatus(updates.status, language) || serverT("None", language);
changes.push(
`Status: ${currentTask.status || "None"} ${updates.status || "None"}`
`${serverT("Status", language)}: ${oldStatus}${newStatus}`
);
}
if (
updates.assigned_to !== undefined &&
updates.assigned_to !== currentTask.assigned_to
) {
changes.push(`Assignment updated`);
changes.push(serverT("Assignment updated", language));
}
if (
updates.date_started !== undefined &&
updates.date_started !== currentTask.date_started
) {
const oldDate = currentTask.date_started || serverT("None", language);
const newDate = updates.date_started || serverT("None", language);
changes.push(
`Date started: ${currentTask.date_started || "None"}${
updates.date_started || "None"
}`
`${serverT("Date started", language)}: ${oldDate}${newDate}`
);
}
if (changes.length > 0) {
const logMessage = `Task updated: ${changes.join(", ")}`;
const logMessage = `${serverT("Task updated", language)}: ${changes.join(", ")}`;
addNoteToTask(taskId, logMessage, true, userId);
}
}