📸 Add screenshots, live demo section, and seed data
- 6 app screenshots (login, dashboard, kanban, card detail, users, email) - Live demo URL with 4 demo accounts (admin + 3 members) - Demo data: 3 boards, 21 cards, labels, comments, activity - Seed script for reproducible demo environment - Updated README with screenshots section and demo credentials
This commit is contained in:
71
README.md
71
README.md
@@ -24,6 +24,53 @@
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Live Demo
|
||||
|
||||
Try TeamFlow right now — no signup required.
|
||||
|
||||
👉 **[teamflow.95-216-124-247.sslip.io](https://teamflow.95-216-124-247.sslip.io)**
|
||||
|
||||
### Demo Accounts
|
||||
|
||||
| Role | Email | Password |
|
||||
|------|-------|----------|
|
||||
| 👑 Admin | `admin@teamflow.local` | `demo1234` |
|
||||
| 👤 Member | `sarah@demo.teamflow` | `demo1234` |
|
||||
| 👤 Member | `alex@demo.teamflow` | `demo1234` |
|
||||
| 👤 Member | `jordan@demo.teamflow` | `demo1234` |
|
||||
|
||||
> **Tip:** Use the admin account to explore user management and email settings. All member accounts have the same password.
|
||||
|
||||
---
|
||||
|
||||
## 📸 Screenshots
|
||||
|
||||
### Login
|
||||
|
||||
<img src="docs/screenshots/06-login.png" alt="TeamFlow Login" width="100%" />
|
||||
|
||||
### Dashboard — Board Overview
|
||||
|
||||
<img src="docs/screenshots/01-dashboard.png" alt="TeamFlow Dashboard" width="100%" />
|
||||
|
||||
### Kanban Board — Drag & Drop
|
||||
|
||||
<img src="docs/screenshots/02-kanban-board.png" alt="TeamFlow Kanban Board" width="100%" />
|
||||
|
||||
### Card Detail — Full Feature View
|
||||
|
||||
<img src="docs/screenshots/03-card-detail.png" alt="TeamFlow Card Detail" width="100%" />
|
||||
|
||||
### User Management — Admin Panel
|
||||
|
||||
<img src="docs/screenshots/04-user-management.png" alt="TeamFlow User Management" width="100%" />
|
||||
|
||||
### Email Settings — SMTP & IMAP Configuration
|
||||
|
||||
<img src="docs/screenshots/05-email-settings.png" alt="TeamFlow Email Settings" width="100%" />
|
||||
|
||||
---
|
||||
|
||||
## ✨ Features
|
||||
|
||||
### 🏗️ Kanban Boards
|
||||
@@ -71,7 +118,7 @@
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Quick Start
|
||||
## ⚡ Quick Start
|
||||
|
||||
```bash
|
||||
# Clone the repo
|
||||
@@ -149,6 +196,7 @@ teamflow/
|
||||
├── server/
|
||||
│ ├── index.js # Express server + HTTPS support
|
||||
│ ├── db.js # SQLite schema (auto-migrates)
|
||||
│ ├── seed-demo.cjs # Demo data seeder
|
||||
│ ├── middleware/
|
||||
│ │ └── auth.js # JWT auth + admin guard
|
||||
│ ├── routes/
|
||||
@@ -181,6 +229,8 @@ teamflow/
|
||||
│ │ ├── UserManagement.jsx
|
||||
│ │ └── EmailSettings.jsx
|
||||
│ └── ...config files
|
||||
├── docs/
|
||||
│ └── screenshots/ # App screenshots
|
||||
└── package.json
|
||||
```
|
||||
|
||||
@@ -200,25 +250,6 @@ teamflow/
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Screenshots
|
||||
|
||||
### Setup Wizard
|
||||
Step-by-step email configuration and admin creation — verified live before saving.
|
||||
|
||||
### Kanban Board
|
||||
Drag-and-drop cards between lists. Priority indicators, due dates, labels, assignees, and checklist progress — all visible at a glance.
|
||||
|
||||
### Card Detail Modal
|
||||
Full-featured card editor with description, checklists, time tracking, comments, labels, priority, and activity history.
|
||||
|
||||
### User Management
|
||||
Admin panel to create users, manage roles, reset passwords, and enable/disable accounts.
|
||||
|
||||
### Email Settings
|
||||
Configure SMTP/IMAP, send test emails, view email logs and stats, and manage inbound processing.
|
||||
|
||||
---
|
||||
|
||||
## 📄 License
|
||||
|
||||
MIT — use it, fork it, ship it.
|
||||
|
||||
BIN
docs/screenshots/01-dashboard.png
Normal file
BIN
docs/screenshots/01-dashboard.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 123 KiB |
BIN
docs/screenshots/02-kanban-board.png
Normal file
BIN
docs/screenshots/02-kanban-board.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 133 KiB |
BIN
docs/screenshots/03-card-detail.png
Normal file
BIN
docs/screenshots/03-card-detail.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 133 KiB |
BIN
docs/screenshots/04-user-management.png
Normal file
BIN
docs/screenshots/04-user-management.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 69 KiB |
BIN
docs/screenshots/05-email-settings.png
Normal file
BIN
docs/screenshots/05-email-settings.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 84 KiB |
BIN
docs/screenshots/06-login.png
Normal file
BIN
docs/screenshots/06-login.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 415 KiB |
1027
server/package-lock.json
generated
1027
server/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,7 @@
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"mailparser": "^3.7.2",
|
||||
"nodemailer": "^6.10.0",
|
||||
"puppeteer-core": "^24.40.0",
|
||||
"uuid": "^11.0.5"
|
||||
}
|
||||
}
|
||||
|
||||
101
server/seed-demo.cjs
Normal file
101
server/seed-demo.cjs
Normal file
@@ -0,0 +1,101 @@
|
||||
const bcrypt = require('bcryptjs');
|
||||
const db = require('better-sqlite3')('./data/teamflow.db');
|
||||
|
||||
db.exec(`DELETE FROM card_comments; DELETE FROM card_activity; DELETE FROM card_labels;
|
||||
DELETE FROM checklist_items; DELETE FROM checklists; DELETE FROM email_tokens;
|
||||
DELETE FROM cards; DELETE FROM lists; DELETE FROM board_members; DELETE FROM labels;
|
||||
DELETE FROM boards; DELETE FROM notifications; DELETE FROM email_log; DELETE FROM users;`);
|
||||
|
||||
const users = [
|
||||
{ email: 'admin@teamflow.local', name: 'Admin', role: 'admin', color: '#6366f1' },
|
||||
{ email: 'sarah@demo.teamflow', name: 'Sarah Chen', role: 'member', color: '#ec4899' },
|
||||
{ email: 'alex@demo.teamflow', name: 'Alex Rivera', role: 'member', color: '#14b8a6' },
|
||||
{ email: 'jordan@demo.teamflow', name: 'Jordan Lee', role: 'member', color: '#f97316' },
|
||||
];
|
||||
|
||||
const ins = db.prepare('INSERT INTO users (email, name, password, role, avatar_color) VALUES (?, ?, ?, ?, ?)');
|
||||
users.forEach(u => ins.run(u.email, u.name, bcrypt.hashSync('demo1234', 12), u.role, u.color));
|
||||
|
||||
const listIns = db.prepare('INSERT INTO lists (board_id, title, position) VALUES (?, ?, ?)');
|
||||
const labIns = db.prepare('INSERT INTO labels (board_id, name, color) VALUES (?, ?, ?)');
|
||||
const cardIns = db.prepare(`INSERT INTO cards (list_id, title, description, position, priority, assigned_to, created_by, due_date, estimated_hours, time_spent) VALUES (?,?,?,?,?,?,?,?,?,?)`);
|
||||
const clIns = db.prepare('INSERT OR IGNORE INTO card_labels (card_id, label_id) VALUES (?, ?)');
|
||||
const actIns = db.prepare('INSERT INTO card_activity (card_id, user_id, action, details) VALUES (?, ?, ?, ?)');
|
||||
const commIns = db.prepare('INSERT INTO card_comments (card_id, user_id, content) VALUES (?, ?, ?)');
|
||||
const bmIns = db.prepare('INSERT INTO board_members (board_id, user_id, role) VALUES (?, ?, ?)');
|
||||
const bIns = db.prepare('INSERT INTO boards (title, description, background, created_by) VALUES (?, ?, ?, ?)');
|
||||
|
||||
// Board 1: Sprint
|
||||
const b1 = bIns.run('Sprint 24 — Product Launch', 'Current sprint deliverables for Q2 product launch', 'gradient-indigo', 1);
|
||||
const b1id = b1.lastInsertRowid;
|
||||
[1,2,3,4].forEach((uid,i) => bmIns.run(b1id, uid, i===0?'admin':'member'));
|
||||
|
||||
const l1ids = ['📋 Backlog','🔄 In Progress','👀 In Review','✅ Done'].map((t,i) => listIns.run(b1id,t,i*65536).lastInsertRowid);
|
||||
const lab1ids = [
|
||||
['Bug','#ef4444'],['Feature','#3b82f6'],['Design','#a855f7'],['Urgent','#f97316'],['Documentation','#22c55e']
|
||||
].map(([n,c]) => labIns.run(b1id,n,c).lastInsertRowid);
|
||||
|
||||
const cards1 = [
|
||||
[0,'Fix payment gateway timeout','Users report intermittent 504 errors during checkout on mobile Safari.','urgent',3,[0,3],'2026-04-05',4,2],
|
||||
[0,'Design onboarding flow v2','New 5-step onboarding with progress indicator and skip option.','high',2,[2],'2026-04-10',8,3],
|
||||
[0,'Add SSO integration for enterprise','Support SAML and OIDC providers. Okta, Azure AD, Google Workspace.','medium',1,[1],'2026-04-15',16,0],
|
||||
[0,'Write API documentation','OpenAPI 3.0 spec for all public endpoints.','low',4,[4],'2026-04-20',6,0],
|
||||
[1,'Implement dark mode toggle','System preference detection + manual override.','medium',2,[1,2],'2026-04-08',3,2],
|
||||
[1,'Optimize image loading pipeline','Lazy loading, WebP conversion, responsive srcsets.','high',3,[1],'2026-04-07',5,4],
|
||||
[1,'Refactor auth middleware','JWT validation, refresh token rotation, rate limiting.','medium',1,[1],'2026-04-09',6,1],
|
||||
[2,'Dashboard analytics widgets','Revenue chart, user growth, conversion funnel.','medium',4,[1,2],'2026-04-06',5,5],
|
||||
[3,'Set up CI/CD pipeline','GitHub Actions with staging and production deployments.','high',1,[1],'2026-04-03',4,4],
|
||||
[3,'Fix email notification formatting','HTML templates breaking on Outlook. Switched to table-based layout.','medium',3,[0],'2026-04-02',2,1.5],
|
||||
[3,'Add rate limiting to API','Express-rate-limit with Redis backend.','low',1,[1],'2026-04-01',3,2],
|
||||
];
|
||||
|
||||
const cids1 = [];
|
||||
cards1.forEach((c,i) => {
|
||||
const [list,title,desc,pri,assign,labs,due,est,spent] = c;
|
||||
const r = cardIns.run(l1ids[list],title,desc,i*65536,pri,assign,assign,due,est,spent);
|
||||
const cid = r.lastInsertRowid;
|
||||
cids1.push(cid);
|
||||
labs.forEach(l => clIns.run(cid, lab1ids[l]));
|
||||
actIns.run(cid, assign, 'created', '');
|
||||
});
|
||||
|
||||
commIns.run(cids1[0], 3, 'I can reproduce this on iPhone 15 Pro with Safari 17.4. Request hangs ~30s then 504.');
|
||||
commIns.run(cids1[0], 1, 'Stripe webhook is timing out. Check the timeout config in our payment service.');
|
||||
commIns.run(cids1[0], 2, 'Related to the issue we saw in staging last week. Gateway config was set to 10s timeout.');
|
||||
commIns.run(cids1[4], 2, 'Using CSS custom properties with prefers-color-scheme. Manual toggle in localStorage.');
|
||||
commIns.run(cids1[4], 1, 'Great approach. Make sure email templates also respect the preference.');
|
||||
|
||||
// Board 2: Marketing
|
||||
const b2 = bIns.run('Marketing Campaigns', 'Q2 marketing initiatives and content calendar', 'gradient-pink', 2);
|
||||
const b2id = b2.lastInsertRowid;
|
||||
[1,2,4].forEach((uid,i) => bmIns.run(b2id, uid, i===0?'admin':'member'));
|
||||
const l2ids = ['📝 Ideas','🎨 Creating','📅 Scheduled','📊 Analytics'].map((t,i) => listIns.run(b2id,t,i*65536).lastInsertRowid);
|
||||
[
|
||||
[0,'Product demo video series','medium',2],
|
||||
[0,'Blog: 10 Tips for Remote Teams','low',4],
|
||||
[1,'Social media launch graphics','high',2],
|
||||
[1,'Email drip campaign for onboarding','medium',4],
|
||||
[2,'Launch announcement blog post','high',2],
|
||||
[3,'March analytics review','low',4],
|
||||
].forEach(([list,title,pri,assign],i) => cardIns.run(l2ids[list],title,'',i*65536,pri,assign,assign,null,0,0));
|
||||
|
||||
// Board 3: Bug Tracker
|
||||
const b3 = bIns.run('Bug Tracker', 'Open bugs and issue triage', 'gradient-red', 3);
|
||||
const b3id = b3.lastInsertRowid;
|
||||
[1,3].forEach((uid,i) => bmIns.run(b3id, uid, i===0?'admin':'member'));
|
||||
const l3ids = ['🐛 New','🔧 Fixing','✅ Resolved'].map((t,i) => listIns.run(b3id,t,i*65536).lastInsertRowid);
|
||||
[
|
||||
[0,'Memory leak in dashboard widgets','high',3],
|
||||
[0,'CSV export truncates at 10k rows','medium',1],
|
||||
[1,'Login redirect loop on Safari','urgent',3],
|
||||
[2,'Tooltip z-index overlap on modals','low',1],
|
||||
].forEach(([list,title,pri,assign],i) => cardIns.run(l3ids[list],title,'',i*65536,pri,assign,assign,null,0,0));
|
||||
|
||||
db.prepare('INSERT OR REPLACE INTO email_config (id, smtp_host, smtp_port, email, app_password) VALUES (1,?,?,?,?)')
|
||||
.run('smtp.gmail.com', 587, 'demo@teamflow.app', 'demo-app-password');
|
||||
|
||||
const jwt = require('jsonwebtoken');
|
||||
const token = jwt.sign({id:1,email:'admin@teamflow.local',role:'admin'},'teamflow-secret-change-in-production',{expiresIn:'365d'});
|
||||
|
||||
console.log('OK');
|
||||
console.log('TOKEN:' + token);
|
||||
Reference in New Issue
Block a user