feat: Enhance task filtering, smart scheduling, audit logs and translations
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-12-17 14:26:54 +01:00
parent 9819d8db0b
commit 2579df0b89
32 changed files with 2219 additions and 456 deletions
+81
View File
@@ -0,0 +1,81 @@
import { storage } from '../server/storage';
import { db } from '../server/db';
import { users, tasks, labels } from '../shared/schema';
import { scrypt, randomBytes } from "crypto";
import { promisify } from "util";
const scryptAsync = promisify(scrypt);
async function hashPassword(password: string) {
const salt = randomBytes(16).toString("hex");
const buf = (await scryptAsync(password, salt, 64)) as Buffer;
return `${buf.toString("hex")}.${salt}`;
}
async function seedAiTest() {
console.log("🌱 Seeding AI Benchmark Tasks...");
// 1. Get User
let user = await storage.getUserByUsername('admin');
if (!user) user = await storage.getUserByUsername('paul');
if (!user) {
console.error("❌ No user found.");
process.exit(1);
}
// Reset Password
const newPass = await hashPassword('admin123');
await storage.updateUser(user.id, { password: newPass });
console.log(`🔑 Reset Password for ${user.username} to 'admin123'`);
// Check AI Settings
// Check AI Settings
const provider = await storage.getSystemSettings("ai_provider");
const key = await storage.getSystemSettings("ai_api_key");
const model = await storage.getSystemSettings("ai_model");
console.log(`🤖 AI Configuration: Provider=${provider || 'default(openai)'}, Model=${model || 'default'}, KeySet=${!!key}`);
// 3. Create Labels
let workLabel = await storage.createLabel({ name: 'Work', color: '#3b82f6', creatorId: user.id });
let personalLabel = await storage.createLabel({ name: 'Personal', color: '#10b981', creatorId: user.id });
// Handle potential duplication if labels already exist (storage.createLabel might return existing?)
// server/storage.ts doesn't dedupe by name usually?
// server/ai.ts createLabel tool logic specifically checks for existing.
// Let's assume for this script we just create them or continue.
// 4. Create Tasks
const tasksToCreate = [
{
title: "Review quarterly report",
status: "todo",
priority: "high",
labelId: workLabel.id,
userId: user.id
},
{
title: "Buy milk",
status: "todo",
priority: "medium",
labelId: personalLabel.id,
userId: user.id
},
{
title: "Review movie script",
status: "todo",
priority: "low",
labelId: personalLabel.id,
userId: user.id
}
];
for (const t of tasksToCreate) {
await storage.createTask(t);
console.log(`Created task: "${t.title}" [${t.labelId === workLabel.id ? 'Work' : 'Personal'}]`);
}
console.log("✅ Seeding Complete. ready for AI usage.");
process.exit(0);
}
seedAiTest();
+41
View File
@@ -0,0 +1,41 @@
import { storage } from '../server/storage';
import { getDatabase } from '../server/db';
import { systemSettings, users } from '../shared/schema';
import { eq } from 'drizzle-orm';
async function triggerMorningRoutine() {
console.log("🔧 Configuring System for Morning Routine Trigger...");
// 1. Enable Morning Routine and set time to 00:00 (so it's definitely 'past' start time)
await storage.setSystemSettings('morning_routine_enabled', 'true');
await storage.setSystemSettings('morning_routine_time', '00:00');
// Disable evening to avoid conflict
await storage.setSystemSettings('evening_routine_enabled', 'false');
console.log("✅ System Settings Updated: Morning Enabled @ 00:00");
// 2. Reset User's lastMorningRoutine
const db = getDatabase();
const allUsers = await db.select().from(users).limit(1);
if (allUsers.length > 0) {
const user = allUsers[0];
console.log(`Resetting routine for user: ${user.username} (${user.id})`);
// Update directly via DB to ensure it's null or old
// Set to yesterday
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
await storage.updateUser(user.id, { lastMorningRoutine: yesterday });
console.log("✅ User Updated: lastMorningRoutine set to yesterday.");
console.log("🚀 The app should now block navigation and show the Morning Routine wizard.");
} else {
console.error("❌ No users found to update.");
}
process.exit(0);
}
triggerMorningRoutine();
+39
View File
@@ -0,0 +1,39 @@
import nodemailer from 'nodemailer';
async function verifySmtp() {
console.log("Verifying SMTP Connection...");
// Settings mirroring the default fallback in email.ts
const host = process.env.SMTP_HOST || 'localhost';
const port = parseInt(process.env.SMTP_PORT || '1025');
console.log(`Configuration: ${host}:${port}`);
const transporter = nodemailer.createTransport({
host,
port,
secure: false,
ignoreTLS: true
});
try {
await transporter.verify();
console.log("✅ SMTP Connection Successful! MailHog is likely running.");
const info = await transporter.sendMail({
from: '"Test" <test@example.com>',
to: 'test@example.com',
subject: 'Test Email',
text: 'If you see this, email sending works.'
});
console.log(`✅ Test email sent: ${info.messageId}`);
process.exit(0);
} catch (error) {
console.error("❌ SMTP Connection Failed:", error);
console.log("Make sure MailHog is running (usually 'brew install mailhog' & 'brew services start mailhog' or docker).");
process.exit(1);
}
}
verifySmtp();