/** * GoingsOn - Demo Data Generator * Creates sample projects, tasks, and events for testing * * Usage: Call GoingsOn.seedData.seed() from the browser console */ (function() { 'use strict'; const DemoData = { // Project names and types projects: [ { name: 'Website Redesign', type: 'Job', description: 'Complete overhaul of company website with modern design' }, { name: 'Mobile App MVP', type: 'SideProject', description: 'Build minimum viable product for task management app' }, { name: 'Q1 Marketing Campaign', type: 'Job', description: 'Launch new marketing initiative across all channels' }, { name: 'Blog Writing', type: 'Article', description: 'Weekly blog posts on productivity and tech' }, { name: 'Learning Rust', type: 'SideProject', description: 'Self-study Rust programming language' }, { name: 'Home Office Setup', type: 'Other', description: 'Optimize home workspace for productivity' }, { name: 'Investment Research', type: 'Company', description: 'Research potential investment opportunities' }, { name: 'Photography Portfolio', type: 'SideProject', description: 'Curate and showcase best photography work' }, { name: 'Client Onboarding System', type: 'Job', description: 'Automate new client onboarding process' }, { name: 'Annual Review Essay', type: 'Essay', description: 'Reflections on the past year and goals for next' }, ], // Task descriptions by category taskTemplates: { development: [ 'Set up development environment', 'Create database schema', 'Implement user authentication', 'Build REST API endpoints', 'Write unit tests', 'Fix bug in login flow', 'Optimize database queries', 'Add caching layer', 'Implement rate limiting', 'Create admin dashboard', 'Add export to CSV feature', 'Implement search functionality', 'Fix mobile responsiveness', 'Add dark mode support', 'Implement WebSocket notifications', ], design: [ 'Create wireframes', 'Design landing page mockup', 'Update color palette', 'Design email templates', 'Create icon set', 'Design onboarding flow', 'Update typography system', 'Create component library', 'Design error states', 'Update illustration style', ], marketing: [ 'Write press release', 'Create social media content calendar', 'Design banner ads', 'Write email newsletter', 'Analyze competitor strategies', 'Update SEO keywords', 'Create video script', 'Plan influencer outreach', 'Design promotional materials', 'Write case study', ], admin: [ 'Schedule team meeting', 'Review quarterly budget', 'Update documentation', 'Organize file structure', 'Backup important files', 'Review contracts', 'Update contact list', 'Plan team offsite', 'Review insurance policies', 'Prepare monthly report', ], personal: [ 'Read industry articles', 'Complete online course module', 'Practice new skill', 'Write journal entry', 'Review personal goals', 'Organize workspace', 'Update resume', 'Network with peers', 'Research new tools', 'Plan next week priorities', ], }, // Event templates eventTemplates: [ { title: 'Team Standup', location: 'Zoom', durationMins: 15 }, { title: 'Client Call', location: 'Google Meet', durationMins: 30 }, { title: 'Project Review', location: 'Conference Room A', durationMins: 60 }, { title: 'Design Review', location: 'Figma', durationMins: 45 }, { title: 'Sprint Planning', location: 'Zoom', durationMins: 90 }, { title: 'Code Review Session', location: 'VS Code Live Share', durationMins: 30 }, { title: 'Lunch with Mentor', location: 'Downtown Cafe', durationMins: 60 }, { title: 'Workshop: New Tools', location: 'Training Room', durationMins: 120 }, { title: 'Interview: Frontend Dev', location: 'Office', durationMins: 60 }, { title: 'Strategy Meeting', location: 'Board Room', durationMins: 90 }, { title: 'Coffee Chat', location: 'Local Coffee Shop', durationMins: 30 }, { title: 'Demo to Stakeholders', location: 'Presentation Room', durationMins: 60 }, ], // Annotation templates annotations: [ 'Updated scope based on client feedback', 'Blocked by external dependency', 'Need to follow up with team', 'Good progress today', 'Waiting for approval', 'Resources identified', 'Dependencies resolved', 'On track for deadline', 'Complexity higher than expected', 'Found alternative approach', ], // Tag templates tags: ['urgent', 'blocked', 'review', 'research', 'quick-win', 'backend', 'frontend', 'design', 'docs', 'meeting'], }; /** * Get a random item from an array */ function randomItem(arr) { return arr[Math.floor(Math.random() * arr.length)]; } /** * Get a random number between min and max (inclusive) */ function randomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } /** * Get a random date within a range */ function randomDate(startDays, endDays) { const now = new Date(); const offsetDays = randomInt(startDays, endDays); const date = new Date(now.getTime() + offsetDays * 24 * 60 * 60 * 1000); date.setHours(randomInt(8, 18), randomInt(0, 3) * 15, 0, 0); return date.toISOString(); } /** * Get random tags */ function randomTags(maxCount = 3) { const count = randomInt(0, maxCount); const tags = []; const availableTags = [...DemoData.tags]; for (let i = 0; i < count && availableTags.length > 0; i++) { const idx = randomInt(0, availableTags.length - 1); tags.push(availableTags.splice(idx, 1)[0]); } return tags; } /** * Generate demo projects */ async function generateProjects() { const projects = []; const statuses = ['Active', 'Active', 'Active', 'OnHold', 'Completed']; for (const proj of DemoData.projects) { try { const project = await GoingsOn.api.projects.create({ name: proj.name, description: proj.description, projectType: proj.type, status: randomItem(statuses), }); projects.push(project); console.log(`Created project: ${proj.name}`); } catch (err) { console.error(`Failed to create project ${proj.name}:`, err); } } return projects; } /** * Generate demo tasks */ async function generateTasks(projects, count = 120) { const tasks = []; const priorities = ['High', 'Medium', 'Medium', 'Low']; const recurrences = ['None', 'None', 'None', 'None', 'Daily', 'Weekly', 'Monthly']; const categories = Object.keys(DemoData.taskTemplates); for (let i = 0; i < count; i++) { const category = randomItem(categories); const description = randomItem(DemoData.taskTemplates[category]); const project = Math.random() > 0.2 ? randomItem(projects) : null; // Vary due dates: some past (overdue), some today, some future, some null let due = null; const dueChance = Math.random(); if (dueChance < 0.1) { due = randomDate(-7, -1); // Overdue } else if (dueChance < 0.2) { due = randomDate(0, 0); // Today } else if (dueChance < 0.7) { due = randomDate(1, 30); // Future } try { const task = await GoingsOn.api.tasks.create({ description: `${description} ${i + 1}`, projectId: project?.id || null, priority: randomItem(priorities), due: due, tags: randomTags(2), recurrence: randomItem(recurrences), }); tasks.push(task); // Add subtasks to some tasks if (Math.random() > 0.7) { const subtaskCount = randomInt(2, 5); for (let j = 0; j < subtaskCount; j++) { await GoingsOn.api.subtasks.add(task.id, `Subtask ${j + 1} for this task`); // Complete some subtasks if (Math.random() > 0.5) { const subtasks = await GoingsOn.api.subtasks.list(task.id); if (subtasks.length > j) { await GoingsOn.api.subtasks.toggle(task.id, subtasks[j].id); } } } } // Add annotations to some tasks if (Math.random() > 0.8) { await GoingsOn.api.annotations.add(task.id, randomItem(DemoData.annotations)); } // Snooze some tasks if (Math.random() > 0.9) { await GoingsOn.api.tasks.snooze(task.id, randomDate(1, 7)); } if ((i + 1) % 20 === 0) { console.log(`Created ${i + 1}/${count} tasks...`); } } catch (err) { console.error(`Failed to create task:`, err); } } console.log(`Created ${tasks.length} tasks`); return tasks; } /** * Generate demo events */ async function generateEvents(projects, count = 50) { const events = []; for (let i = 0; i < count; i++) { const template = randomItem(DemoData.eventTemplates); const project = Math.random() > 0.3 ? randomItem(projects) : null; const startTime = randomDate(-7, 30); const endTime = new Date(new Date(startTime).getTime() + template.durationMins * 60000).toISOString(); try { const event = await GoingsOn.api.events.create({ title: `${template.title} ${i + 1}`, description: `Scheduled ${template.title.toLowerCase()} session`, projectId: project?.id || null, startTime: startTime, endTime: endTime, location: template.location, }); events.push(event); if ((i + 1) % 10 === 0) { console.log(`Created ${i + 1}/${count} events...`); } } catch (err) { console.error(`Failed to create event:`, err); } } console.log(`Created ${events.length} events`); return events; } /** * Main function to seed all demo data */ async function seedDemoData() { console.log('=== Starting Demo Data Generation ==='); console.log('This will create sample projects, tasks, and events.'); console.log(''); console.log('Step 1/3: Creating projects...'); const projects = await generateProjects(); console.log(`Created ${projects.length} projects\n`); console.log('Step 2/3: Creating tasks...'); const tasks = await generateTasks(projects, 120); console.log(`Created ${tasks.length} tasks\n`); console.log('Step 3/3: Creating events...'); const events = await generateEvents(projects, 50); console.log(`Created ${events.length} events\n`); console.log('=== Demo Data Generation Complete ==='); console.log(`Summary:`); console.log(` - ${projects.length} projects`); console.log(` - ${tasks.length} tasks`); console.log(` - ${events.length} events`); console.log(''); console.log('Refresh the page to see the data.'); // Refresh the current view if (GoingsOn.navigation?.loadViewData) { await GoingsOn.navigation.loadViewData(GoingsOn.navigation.getCurrentView()); } return { projects, tasks, events }; } /** * Clear all demo data (use with caution!) */ async function clearAllData() { const ok = await GoingsOn.ui.showConfirmDialog( 'Clear all data', 'This will delete ALL projects, tasks, and events. Are you sure?', { confirmText: 'Delete everything', danger: true } ); if (!ok) { console.log('Cancelled.'); return; } console.log('Clearing all data...'); try { // Delete all tasks const tasks = await GoingsOn.api.tasks.list(); for (const task of tasks) { await GoingsOn.api.tasks.delete(task.id); } console.log(`Deleted ${tasks.length} tasks`); // Delete all events const events = await GoingsOn.api.events.list(); for (const event of events) { await GoingsOn.api.events.delete(event.id); } console.log(`Deleted ${events.length} events`); // Delete all projects const projects = await GoingsOn.api.projects.list(); for (const project of projects) { await GoingsOn.api.projects.delete(project.id); } console.log(`Deleted ${projects.length} projects`); console.log('All data cleared.'); // Refresh the current view if (GoingsOn.navigation?.loadViewData) { await GoingsOn.navigation.loadViewData(GoingsOn.navigation.getCurrentView()); } } catch (err) { console.error('Error clearing data:', err); } } // ============ Populate GoingsOn Namespace ============ GoingsOn.seedData = { seed: seedDemoData, clearAll: clearAllData, }; })();