feat(taskbuffer-dashboard): Add TaskBuffer dashboard web component, demo and browser tests; add HTML entry and update dependencies
This commit is contained in:
		
							
								
								
									
										311
									
								
								ts_web/elements/taskbuffer-dashboard.demo.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										311
									
								
								ts_web/elements/taskbuffer-dashboard.demo.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,311 @@
 | 
			
		||||
import { html, css, cssManager } from '@design.estate/dees-element';
 | 
			
		||||
import { TaskManager, Task } from '../../ts/index.js';
 | 
			
		||||
import '../taskbuffer-dashboard.js';
 | 
			
		||||
 | 
			
		||||
export const demoFunc = () => html`
 | 
			
		||||
  <style>
 | 
			
		||||
    ${css`
 | 
			
		||||
      .demoWrapper {
 | 
			
		||||
        box-sizing: border-box;
 | 
			
		||||
        position: relative;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        min-height: 100vh;
 | 
			
		||||
        padding: 48px;
 | 
			
		||||
        background: ${cssManager.bdTheme('#f8f9fa', '#0a0a0a')};
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      h1 {
 | 
			
		||||
        font-size: 32px;
 | 
			
		||||
        font-weight: 700;
 | 
			
		||||
        color: ${cssManager.bdTheme('#09090b', '#fafafa')};
 | 
			
		||||
        margin-bottom: 12px;
 | 
			
		||||
        text-align: center;
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      p {
 | 
			
		||||
        font-size: 16px;
 | 
			
		||||
        color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
 | 
			
		||||
        text-align: center;
 | 
			
		||||
        margin-bottom: 48px;
 | 
			
		||||
      }
 | 
			
		||||
    `}
 | 
			
		||||
  </style>
 | 
			
		||||
  
 | 
			
		||||
  <div class="demoWrapper">
 | 
			
		||||
    <h1>TaskBuffer Dashboard Demo</h1>
 | 
			
		||||
    <p>Real-time visualization of task execution, progress tracking, and scheduling</p>
 | 
			
		||||
    
 | 
			
		||||
    <dees-demowrapper 
 | 
			
		||||
      .title=${'Live Dashboard'}
 | 
			
		||||
      .subtitle=${'Interactive task management dashboard with real-time updates'}
 | 
			
		||||
      .runAfterRender=${async (element) => {
 | 
			
		||||
        // Create TaskManager instance
 | 
			
		||||
        const taskManager = new TaskManager();
 | 
			
		||||
        
 | 
			
		||||
        // Get dashboard element
 | 
			
		||||
        const dashboard = element.querySelector('taskbuffer-dashboard');
 | 
			
		||||
        dashboard.taskManager = taskManager;
 | 
			
		||||
        dashboard.refreshInterval = 500;
 | 
			
		||||
        
 | 
			
		||||
        // Task counter for unique names
 | 
			
		||||
        let taskCounter = 0;
 | 
			
		||||
        
 | 
			
		||||
        // Helper to create random delay
 | 
			
		||||
        const randomDelay = () => new Promise(resolve => 
 | 
			
		||||
          setTimeout(resolve, Math.random() * 2000 + 500)
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
        // Add initial demo tasks
 | 
			
		||||
        const addDemoTasks = () => {
 | 
			
		||||
          // Add simple task
 | 
			
		||||
          const simpleTask = new Task({
 | 
			
		||||
            name: `SimpleTask_${++taskCounter}`,
 | 
			
		||||
            taskFunction: async () => {
 | 
			
		||||
              console.log(`Executing SimpleTask_${taskCounter}`);
 | 
			
		||||
              await randomDelay();
 | 
			
		||||
              return `Result from SimpleTask_${taskCounter}`;
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
          taskManager.addTask(simpleTask);
 | 
			
		||||
          
 | 
			
		||||
          // Add task with steps
 | 
			
		||||
          const steppedTask = new Task({
 | 
			
		||||
            name: `SteppedTask_${++taskCounter}`,
 | 
			
		||||
            steps: [
 | 
			
		||||
              { name: 'init', description: 'Initializing', percentage: 20 },
 | 
			
		||||
              { name: 'fetch', description: 'Fetching data', percentage: 30 },
 | 
			
		||||
              { name: 'process', description: 'Processing', percentage: 35 },
 | 
			
		||||
              { name: 'save', description: 'Saving results', percentage: 15 }
 | 
			
		||||
            ],
 | 
			
		||||
            taskFunction: async function() {
 | 
			
		||||
              this.notifyStep('init');
 | 
			
		||||
              await randomDelay();
 | 
			
		||||
              this.notifyStep('fetch');
 | 
			
		||||
              await randomDelay();
 | 
			
		||||
              this.notifyStep('process');
 | 
			
		||||
              await randomDelay();
 | 
			
		||||
              this.notifyStep('save');
 | 
			
		||||
              await randomDelay();
 | 
			
		||||
              return `Completed SteppedTask_${taskCounter}`;
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
          taskManager.addTask(steppedTask);
 | 
			
		||||
          
 | 
			
		||||
          // Add buffered task
 | 
			
		||||
          const bufferedTask = new Task({
 | 
			
		||||
            name: `BufferedTask_${++taskCounter}`,
 | 
			
		||||
            buffered: true,
 | 
			
		||||
            bufferMax: 3,
 | 
			
		||||
            steps: [
 | 
			
		||||
              { name: 'buffer', description: 'Processing buffered item', percentage: 100 }
 | 
			
		||||
            ],
 | 
			
		||||
            taskFunction: async function(item) {
 | 
			
		||||
              this.notifyStep('buffer');
 | 
			
		||||
              console.log(`Processing buffered item: ${item}`);
 | 
			
		||||
              await randomDelay();
 | 
			
		||||
              return `Buffered task ${taskCounter} processed: ${item}`;
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
          taskManager.addTask(bufferedTask);
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        // Add initial tasks
 | 
			
		||||
        addDemoTasks();
 | 
			
		||||
        
 | 
			
		||||
        // Automatically trigger some tasks
 | 
			
		||||
        setTimeout(() => {
 | 
			
		||||
          const tasks = taskManager.getAllTasksMetadata();
 | 
			
		||||
          tasks.forEach(taskMeta => {
 | 
			
		||||
            const task = taskManager.getTaskByName(taskMeta.name);
 | 
			
		||||
            if (task && !taskMeta.name.includes('Scheduled')) {
 | 
			
		||||
              if (taskMeta.buffered) {
 | 
			
		||||
                // Trigger buffered task multiple times
 | 
			
		||||
                for (let i = 0; i < 5; i++) {
 | 
			
		||||
                  task.trigger(`Data_${i}`);
 | 
			
		||||
                }
 | 
			
		||||
              } else {
 | 
			
		||||
                task.trigger();
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
        }, 2000);
 | 
			
		||||
      }}
 | 
			
		||||
    >
 | 
			
		||||
      <taskbuffer-dashboard></taskbuffer-dashboard>
 | 
			
		||||
    </dees-demowrapper>
 | 
			
		||||
    
 | 
			
		||||
    <dees-demowrapper
 | 
			
		||||
      .title=${'Scheduled Tasks'}
 | 
			
		||||
      .subtitle=${'Tasks scheduled with cron expressions'}
 | 
			
		||||
      .runAfterRender=${async (element) => {
 | 
			
		||||
        // Create TaskManager instance
 | 
			
		||||
        const taskManager = new TaskManager();
 | 
			
		||||
        
 | 
			
		||||
        // Get dashboard element
 | 
			
		||||
        const dashboard = element.querySelector('taskbuffer-dashboard');
 | 
			
		||||
        dashboard.taskManager = taskManager;
 | 
			
		||||
        dashboard.refreshInterval = 1000;
 | 
			
		||||
        
 | 
			
		||||
        // Add scheduled tasks
 | 
			
		||||
        const scheduledTask1 = new Task({
 | 
			
		||||
          name: 'HourlyBackup',
 | 
			
		||||
          steps: [
 | 
			
		||||
            { name: 'prepare', description: 'Preparing backup', percentage: 30 },
 | 
			
		||||
            { name: 'backup', description: 'Creating backup', percentage: 50 },
 | 
			
		||||
            { name: 'verify', description: 'Verifying backup', percentage: 20 }
 | 
			
		||||
          ],
 | 
			
		||||
          taskFunction: async function() {
 | 
			
		||||
            this.notifyStep('prepare');
 | 
			
		||||
            await new Promise(resolve => setTimeout(resolve, 1000));
 | 
			
		||||
            this.notifyStep('backup');
 | 
			
		||||
            await new Promise(resolve => setTimeout(resolve, 2000));
 | 
			
		||||
            this.notifyStep('verify');
 | 
			
		||||
            await new Promise(resolve => setTimeout(resolve, 500));
 | 
			
		||||
            return 'Backup completed';
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
        
 | 
			
		||||
        const scheduledTask2 = new Task({
 | 
			
		||||
          name: 'DailyReport',
 | 
			
		||||
          steps: [
 | 
			
		||||
            { name: 'collect', description: 'Collecting data', percentage: 40 },
 | 
			
		||||
            { name: 'analyze', description: 'Analyzing data', percentage: 40 },
 | 
			
		||||
            { name: 'send', description: 'Sending report', percentage: 20 }
 | 
			
		||||
          ],
 | 
			
		||||
          taskFunction: async function() {
 | 
			
		||||
            this.notifyStep('collect');
 | 
			
		||||
            await new Promise(resolve => setTimeout(resolve, 1500));
 | 
			
		||||
            this.notifyStep('analyze');
 | 
			
		||||
            await new Promise(resolve => setTimeout(resolve, 1500));
 | 
			
		||||
            this.notifyStep('send');
 | 
			
		||||
            await new Promise(resolve => setTimeout(resolve, 500));
 | 
			
		||||
            return 'Report sent';
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
        
 | 
			
		||||
        // Schedule tasks
 | 
			
		||||
        taskManager.addAndScheduleTask(scheduledTask1, '0 * * * *'); // Every hour
 | 
			
		||||
        taskManager.addAndScheduleTask(scheduledTask2, '0 0 * * *'); // Daily at midnight
 | 
			
		||||
        
 | 
			
		||||
        // Also add them as regular tasks for demo
 | 
			
		||||
        const demoTask = new Task({
 | 
			
		||||
          name: 'DemoScheduledExecution',
 | 
			
		||||
          steps: [
 | 
			
		||||
            { name: 'execute', description: 'Simulating scheduled execution', percentage: 100 }
 | 
			
		||||
          ],
 | 
			
		||||
          taskFunction: async function() {
 | 
			
		||||
            this.notifyStep('execute');
 | 
			
		||||
            await new Promise(resolve => setTimeout(resolve, 1000));
 | 
			
		||||
            
 | 
			
		||||
            // Trigger scheduled tasks for demo
 | 
			
		||||
            scheduledTask1.trigger();
 | 
			
		||||
            scheduledTask2.trigger();
 | 
			
		||||
            
 | 
			
		||||
            return 'Triggered scheduled tasks for demo';
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
        taskManager.addTask(demoTask);
 | 
			
		||||
        
 | 
			
		||||
        // Trigger demo after 2 seconds
 | 
			
		||||
        setTimeout(() => {
 | 
			
		||||
          demoTask.trigger();
 | 
			
		||||
        }, 2000);
 | 
			
		||||
      }}
 | 
			
		||||
    >
 | 
			
		||||
      <taskbuffer-dashboard></taskbuffer-dashboard>
 | 
			
		||||
    </dees-demowrapper>
 | 
			
		||||
    
 | 
			
		||||
    <dees-demowrapper
 | 
			
		||||
      .title=${'Task Execution Control'}
 | 
			
		||||
      .subtitle=${'Interactive controls for task management'}
 | 
			
		||||
      .runAfterRender=${async (element) => {
 | 
			
		||||
        // Create TaskManager instance
 | 
			
		||||
        const taskManager = new TaskManager();
 | 
			
		||||
        
 | 
			
		||||
        // Get dashboard element
 | 
			
		||||
        const dashboard = element.querySelector('taskbuffer-dashboard');
 | 
			
		||||
        dashboard.taskManager = taskManager;
 | 
			
		||||
        dashboard.refreshInterval = 300;
 | 
			
		||||
        
 | 
			
		||||
        // Add control buttons
 | 
			
		||||
        const controlsDiv = document.createElement('div');
 | 
			
		||||
        controlsDiv.style.cssText = `
 | 
			
		||||
          display: flex;
 | 
			
		||||
          gap: 8px;
 | 
			
		||||
          margin-bottom: 16px;
 | 
			
		||||
          flex-wrap: wrap;
 | 
			
		||||
        `;
 | 
			
		||||
        
 | 
			
		||||
        const createButton = (text, onClick, style = '') => {
 | 
			
		||||
          const button = document.createElement('button');
 | 
			
		||||
          button.textContent = text;
 | 
			
		||||
          button.style.cssText = `
 | 
			
		||||
            padding: 8px 16px;
 | 
			
		||||
            border: none;
 | 
			
		||||
            border-radius: 6px;
 | 
			
		||||
            cursor: pointer;
 | 
			
		||||
            font-size: 14px;
 | 
			
		||||
            transition: all 0.2s;
 | 
			
		||||
            ${style}
 | 
			
		||||
          `;
 | 
			
		||||
          button.onclick = onClick;
 | 
			
		||||
          return button;
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        let taskCounter = 0;
 | 
			
		||||
        
 | 
			
		||||
        // Add task button
 | 
			
		||||
        controlsDiv.appendChild(createButton('Add Task', () => {
 | 
			
		||||
          const task = new Task({
 | 
			
		||||
            name: `Task_${++taskCounter}`,
 | 
			
		||||
            steps: [
 | 
			
		||||
              { name: 'step1', description: 'Step 1', percentage: 33 },
 | 
			
		||||
              { name: 'step2', description: 'Step 2', percentage: 33 },
 | 
			
		||||
              { name: 'step3', description: 'Step 3', percentage: 34 }
 | 
			
		||||
            ],
 | 
			
		||||
            taskFunction: async function() {
 | 
			
		||||
              for (const step of ['step1', 'step2', 'step3']) {
 | 
			
		||||
                this.notifyStep(step);
 | 
			
		||||
                await new Promise(resolve => setTimeout(resolve, 1000));
 | 
			
		||||
              }
 | 
			
		||||
              return `Task_${taskCounter} completed`;
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
          taskManager.addTask(task);
 | 
			
		||||
        }, 'background: #3b82f6; color: white;'));
 | 
			
		||||
        
 | 
			
		||||
        // Trigger all button
 | 
			
		||||
        controlsDiv.appendChild(createButton('Trigger All', () => {
 | 
			
		||||
          const tasks = taskManager.getAllTasksMetadata();
 | 
			
		||||
          tasks.forEach(taskMeta => {
 | 
			
		||||
            const task = taskManager.getTaskByName(taskMeta.name);
 | 
			
		||||
            if (task) {
 | 
			
		||||
              task.trigger();
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
        }, 'background: #22c55e; color: white;'));
 | 
			
		||||
        
 | 
			
		||||
        // Clear all button
 | 
			
		||||
        controlsDiv.appendChild(createButton('Clear All', () => {
 | 
			
		||||
          const tasks = taskManager.getAllTasksMetadata();
 | 
			
		||||
          tasks.forEach(taskMeta => {
 | 
			
		||||
            const task = taskManager.getTaskByName(taskMeta.name);
 | 
			
		||||
            if (task) {
 | 
			
		||||
              taskManager.taskMap.remove(task);
 | 
			
		||||
              taskManager.descheduleTaskByName(taskMeta.name);
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
        }, 'background: #ef4444; color: white;'));
 | 
			
		||||
        
 | 
			
		||||
        element.insertBefore(controlsDiv, dashboard);
 | 
			
		||||
        
 | 
			
		||||
        // Add some initial tasks
 | 
			
		||||
        for (let i = 0; i < 3; i++) {
 | 
			
		||||
          controlsDiv.querySelector('button').click();
 | 
			
		||||
        }
 | 
			
		||||
      }}
 | 
			
		||||
    >
 | 
			
		||||
      <taskbuffer-dashboard></taskbuffer-dashboard>
 | 
			
		||||
    </dees-demowrapper>
 | 
			
		||||
  </div>
 | 
			
		||||
`;
 | 
			
		||||
		Reference in New Issue
	
	Block a user