← back to Designer Wallcoverings
DW-Agents/dw-agents/agent-completed-tasks/completed-tasks-agent.ts.backup-auth-1762615744
298 lines
/**
* DW-Agents: Completed Tasks Agent
*
* Shows all completed tasks from all agents in chronological order
* Port: 9889
*/
import express, { Request, Response } from 'express';
import { requireAuth as ssoAuth, handleLogin, setSSOToken, SSO_TOKEN_NAME, SSO_TOKEN_VALUE } from './shared-auth';
import cookieParser from 'cookie-parser';
import session from 'express-session';
const app = express();
const PORT = 9889;
app.use(express.json());
app.use(cookieParser());
app.use(express.urlencoded({ extended: true }));
declare module 'express-session' {
interface SessionData {
authenticated: boolean;
}
}
app.use(
session({
secret: 'dw-completed-tasks-2025',
resave: false,
saveUninitialized: true,
cookie: {
secure: false,
httpOnly: true,
maxAge: 7 * 24 * 60 * 60 * 1000,
},
})
);
const requireAuth = (req: Request, res: Response, next: any) => {
if (req.session.authenticated) {
return next();
}
if (req.cookies && req.cookies[SSO_TOKEN_NAME] === SSO_TOKEN_VALUE) {
req.session.authenticated = true;
return next();
}
res.redirect('/login');
};
// Login page
app.get('/login', (req: Request, res: Response) => {
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>Completed Tasks - Login</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
}
.login-container {
background: white;
padding: 40px;
border-radius: 15px;
box-shadow: 0 15px 35px rgba(0,0,0,0.2);
max-width: 400px;
width: 100%;
}
h1 { color: #28a745; text-align: center; margin-bottom: 30px; }
input {
width: 100%;
padding: 12px;
margin: 10px 0;
border: 2px solid #e0e0e0;
border-radius: 8px;
}
button {
width: 100%;
background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
color: white;
border: none;
padding: 15px;
border-radius: 8px;
cursor: pointer;
font-weight: 600;
margin-top: 10px;
}
</style>
</head>
<body>
<div class="login-container">
<h1>✅ Completed Tasks</h1>
<form method="POST">
<input type="text" name="username" placeholder="Username" required>
<input type="password" name="password" placeholder="Password" required>
<button type="submit">Login</button>
</form>
</div>
</body>
</html>
`);
});
app.post('/login', (req: Request, res: Response) => {
const { username, password } = req.body;
if (username === 'admin' && password === '2025') {
req.session.authenticated = true;
setSSOToken(res);
res.redirect('/');
} else {
res.redirect('/login');
}
});
// Sample completed tasks data
const completedTasks = [
{ agent: 'Legal Team', task: 'Reviewed 15 products for settlement compliance', timestamp: new Date('2025-11-05T19:30:00'), status: 'All clear' },
{ agent: 'Marketing', task: 'Published blog post: "Top Wallpaper Trends 2025"', timestamp: new Date('2025-11-05T18:45:00'), status: 'Live' },
{ agent: 'Digital Samples', task: 'Processed DIG-25 order and delivered files', timestamp: new Date('2025-11-05T17:20:00'), status: 'Delivered' },
{ agent: 'Purchasing Office', task: 'Ordered printer paper (5 reams) from Amazon Business', timestamp: new Date('2025-11-05T16:10:00'), status: 'Ordered' },
{ agent: 'Trend Research', task: 'Generated market intelligence report', timestamp: new Date('2025-11-05T15:30:00'), status: 'Complete' },
{ agent: 'Accounting', task: 'Generated P&L report for October 2025', timestamp: new Date('2025-11-05T14:00:00'), status: 'Complete' },
{ agent: 'Zendesk Chat', task: 'Resolved 8 customer inquiries', timestamp: new Date('2025-11-05T13:45:00'), status: 'Closed' },
{ agent: 'Server Uptime', task: 'Auto-restarted dw-master-hub', timestamp: new Date('2025-11-05T12:30:00'), status: 'Online' },
{ agent: 'Digital Samples', task: 'Processed DIG-24 order', timestamp: new Date('2025-11-05T11:15:00'), status: 'Delivered' },
{ agent: 'Legal Team', task: 'Updated settlement criteria documentation', timestamp: new Date('2025-11-05T10:00:00'), status: 'Updated' }
];
// Main dashboard
app.get('/', requireAuth, (req: Request, res: Response) => {
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>Completed Tasks - DW-Agents</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
padding: 20px;
min-height: 100vh;
}
.header {
background: white;
padding: 30px;
border-radius: 15px;
margin-bottom: 20px;
box-shadow: 0 5px 20px rgba(0,0,0,0.1);
}
.header h1 { color: #28a745; font-size: 2.5em; margin-bottom: 10px; }
.header .subtitle { color: #666; font-size: 1.1em; }
.timeline {
background: white;
border-radius: 15px;
padding: 30px;
box-shadow: 0 5px 20px rgba(0,0,0,0.1);
}
.task-item {
border-left: 4px solid #28a745;
padding: 20px;
margin-bottom: 20px;
background: #f8f9fa;
border-radius: 8px;
transition: all 0.2s;
}
.task-item:hover {
transform: translateX(5px);
box-shadow: 0 3px 10px rgba(40, 167, 69, 0.2);
}
.task-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.task-agent {
font-weight: 600;
color: #28a745;
font-size: 1.1em;
}
.task-time {
color: #888;
font-size: 0.9em;
}
.task-description {
color: #333;
margin-bottom: 8px;
font-size: 1.05em;
}
.task-status {
display: inline-block;
background: #28a745;
color: white;
padding: 4px 12px;
border-radius: 12px;
font-size: 0.85em;
font-weight: 600;
}
.filters {
background: white;
padding: 20px;
border-radius: 15px;
margin-bottom: 20px;
box-shadow: 0 5px 20px rgba(0,0,0,0.1);
display: flex;
gap: 15px;
align-items: center;
}
.filters select {
padding: 10px;
border: 2px solid #e0e0e0;
border-radius: 8px;
font-size: 1em;
}
.filters label {
font-weight: 600;
color: #666;
}
</style>
</head>
<body>
<div class="header">
<h1>✅ Completed Tasks</h1>
<div class="subtitle">All completed tasks from DW-Agents in chronological order</div>
</div>
<div class="filters">
<label>Filter by Agent:</label>
<select id="agentFilter" onchange="filterTasks()">
<option value="all">All Agents</option>
<option value="Legal Team">Legal Team</option>
<option value="Marketing">Marketing</option>
<option value="Digital Samples">Digital Samples</option>
<option value="Purchasing Office">Purchasing Office</option>
<option value="Trend Research">Trend Research</option>
<option value="Accounting">Accounting</option>
<option value="Zendesk Chat">Zendesk Chat</option>
<option value="Server Uptime">Server Uptime</option>
</select>
<span style="margin-left: auto; color: #888;" id="lastUpdate">Last updated: --:--</span>
</div>
<div class="timeline" id="timeline">
${completedTasks.map(task => `
<div class="task-item" data-agent="${task.agent}">
<div class="task-header">
<div class="task-agent">${task.agent}</div>
<div class="task-time">${task.timestamp.toLocaleString()}</div>
</div>
<div class="task-description">${task.task}</div>
<div class="task-status">${task.status}</div>
</div>
`).join('')}
</div>
<script>
function filterTasks() {
const filter = document.getElementById('agentFilter').value;
const items = document.querySelectorAll('.task-item');
items.forEach(item => {
if (filter === 'all' || item.dataset.agent === filter) {
item.style.display = 'block';
} else {
item.style.display = 'none';
}
});
}
function updateTimestamp() {
document.getElementById('lastUpdate').textContent = 'Last updated: ' + new Date().toLocaleTimeString();
}
// Auto-refresh every 30 seconds
setInterval(() => {
location.reload();
}, 30000);
updateTimestamp();
</script>
</body>
</html>
`);
});
app.listen(PORT, '0.0.0.0', () => {
console.log(`✅ Completed Tasks Agent running on port ${PORT}`);
console.log(`Dashboard: http://45.61.58.125:${PORT}`);
});