mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-01-23 18:56:01 +00:00
881 lines
34 KiB
HTML
881 lines
34 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta
|
|
name="viewport"
|
|
content="width=device-width, initial-scale=1.0"
|
|
/>
|
|
<title>API Test Plugin Dashboard</title>
|
|
<style>
|
|
body {
|
|
font-family: monospace;
|
|
margin: 0;
|
|
padding: 20px;
|
|
/* Use injected CSS variables for theming */
|
|
background: var(--bg, transparent);
|
|
color: var(--text-color, #ccc);
|
|
}
|
|
|
|
h1 {
|
|
font-size: 18px;
|
|
margin: 0 0 20px 0;
|
|
}
|
|
|
|
h2 {
|
|
font-size: 14px;
|
|
margin: 0 0 10px 0;
|
|
}
|
|
|
|
h3 {
|
|
font-size: 12px;
|
|
margin: 0 0 8px 0;
|
|
}
|
|
|
|
.test-section {
|
|
margin-bottom: 20px;
|
|
border-left: 2px solid var(--divider-color, #666);
|
|
padding-left: 10px;
|
|
}
|
|
|
|
.button-grid {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 8px;
|
|
}
|
|
|
|
button {
|
|
padding: 6px 12px;
|
|
border: 1px solid var(--divider-color, #666);
|
|
background: var(--card-bg, transparent);
|
|
color: var(--text-color, #ccc);
|
|
font-size: 12px;
|
|
font-family: monospace;
|
|
cursor: pointer;
|
|
}
|
|
|
|
button:hover {
|
|
background: var(--select-hover-bg, rgba(255, 255, 255, 0.1));
|
|
border-color: var(--c-primary, #999);
|
|
}
|
|
|
|
.run-all {
|
|
display: block;
|
|
width: 100%;
|
|
margin-bottom: 20px;
|
|
border-color: var(--color-success, #4caf50);
|
|
color: var(--color-success, #4caf50);
|
|
}
|
|
|
|
.run-all:hover {
|
|
background: var(--color-overlay-light-10, rgba(76, 175, 80, 0.1));
|
|
}
|
|
|
|
.console {
|
|
background: var(--card-bg, rgba(0, 0, 0, 0.3));
|
|
color: var(--text-color, #ccc);
|
|
padding: 10px;
|
|
font-size: 11px;
|
|
max-height: 200px;
|
|
overflow-y: auto;
|
|
margin-top: 20px;
|
|
border: 1px solid var(--divider-color, #333);
|
|
}
|
|
|
|
.console-entry {
|
|
margin: 2px 0;
|
|
}
|
|
|
|
.console-entry.success {
|
|
color: var(--color-success, #4caf50);
|
|
}
|
|
|
|
.console-entry.error {
|
|
color: var(--color-danger, #f44336);
|
|
}
|
|
|
|
.console-entry.info {
|
|
color: var(--text-color-muted, #999);
|
|
}
|
|
|
|
.api-info {
|
|
margin-bottom: 20px;
|
|
padding-bottom: 10px;
|
|
border-bottom: 1px solid var(--divider-color, #333);
|
|
}
|
|
|
|
.api-list {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 8px;
|
|
margin-top: 8px;
|
|
}
|
|
|
|
.api-item {
|
|
padding: 4px 8px;
|
|
border: 1px solid var(--divider-color, #444);
|
|
font-size: 11px;
|
|
color: var(--text-color-muted, #999);
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>API Test Plugin</h1>
|
|
|
|
<div class="api-info">
|
|
<h3>Available API Methods</h3>
|
|
<div class="api-list">
|
|
<div class="api-item">getTasks()</div>
|
|
<div class="api-item">getArchivedTasks()</div>
|
|
<div class="api-item">getCurrentContextTasks()</div>
|
|
<div class="api-item">addTask(data)</div>
|
|
<div class="api-item">updateTask(id, data)</div>
|
|
<div class="api-item">getAllProjects()</div>
|
|
<div class="api-item">addProject(data)</div>
|
|
<div class="api-item">updateProject(id, data)</div>
|
|
<div class="api-item">getAllTags()</div>
|
|
<div class="api-item">addTag(data)</div>
|
|
<div class="api-item">updateTag(id, data)</div>
|
|
<div class="api-item">showSnack(config)</div>
|
|
<div class="api-item">notify(config)</div>
|
|
<div class="api-item">openDialog(config)</div>
|
|
<div class="api-item">persistDataSynced(data)</div>
|
|
<div class="api-item">loadSyncedData()</div>
|
|
<div class="api-item">registerHook(hook, handler)</div>
|
|
<div class="api-item">registerHeaderButton(config)</div>
|
|
<div class="api-item">registerMenuEntry(config)</div>
|
|
<div class="api-item">registerShortcut(config)</div>
|
|
<div class="api-item">setCounter(key, value)</div>
|
|
<div class="api-item">getCounter(key)</div>
|
|
<div class="api-item">incrementCounter(key, amount)</div>
|
|
<div class="api-item">decrementCounter(key, amount)</div>
|
|
<div class="api-item">deleteCounter(key)</div>
|
|
<div class="api-item">getAllCounters()</div>
|
|
</div>
|
|
</div>
|
|
|
|
<button
|
|
class="run-all"
|
|
onclick="runAllTests()"
|
|
>
|
|
Run All API Tests
|
|
</button>
|
|
|
|
<div class="test-section">
|
|
<h2>Data Persistence Tests</h2>
|
|
<div class="button-grid">
|
|
<button onclick="testPersistData()">Test Save Data</button>
|
|
<button onclick="testLoadData()">Test Load Data</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h2>Task Operations</h2>
|
|
<div class="button-grid">
|
|
<button onclick="testGetTasks()">Get All Tasks</button>
|
|
<button onclick="testGetArchivedTasks()">Get Archived Tasks</button>
|
|
<button onclick="testGetContextTasks()">Get Context Tasks</button>
|
|
<button onclick="testCreateTask()">Create Test Task</button>
|
|
<button onclick="testUpdateTask()">Update Last Task</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h2>Project & Tag Operations</h2>
|
|
<div class="button-grid">
|
|
<button onclick="testGetProjects()">Get All Projects</button>
|
|
<button onclick="testCreateProject()">Create Test Project</button>
|
|
<button onclick="testGetTags()">Get All Tags</button>
|
|
<button onclick="testCreateTag()">Create Test Tag</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h2>UI Operations</h2>
|
|
<div class="button-grid">
|
|
<button onclick="testSnackSuccess()">Success Snack</button>
|
|
<button onclick="testSnackError()">Error Snack</button>
|
|
<button onclick="testSnackCustom()">Info Snack</button>
|
|
<button onclick="testNotification()">Show Notification</button>
|
|
<button onclick="testDialog()">Open Dialog</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h2>Advanced Dialog Examples</h2>
|
|
<div class="button-grid">
|
|
<button onclick="showTaskPlannerDialog()">Task Planner</button>
|
|
<button onclick="showAnalyticsDialog()">Analytics Dashboard</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
class="console"
|
|
id="console"
|
|
>
|
|
<div class="console-entry info">Console output will appear here...</div>
|
|
</div>
|
|
|
|
<script>
|
|
let lastTaskId = null;
|
|
let lastProjectId = null;
|
|
let lastTagId = null;
|
|
|
|
// Console logging
|
|
function log(message, type = 'info') {
|
|
const console = document.getElementById('console');
|
|
const entry = document.createElement('div');
|
|
entry.className = `console-entry ${type}`;
|
|
entry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
|
|
console.appendChild(entry);
|
|
console.scrollTop = console.scrollHeight;
|
|
}
|
|
|
|
// Clear console
|
|
function clearConsole() {
|
|
document.getElementById('console').innerHTML =
|
|
'<div class="console-entry info">Console cleared. Starting new test run...</div>';
|
|
}
|
|
|
|
// Test functions
|
|
async function testPersistData() {
|
|
try {
|
|
const testData = {
|
|
timestamp: new Date().toISOString(),
|
|
randomValue: Math.floor(Math.random() * 1000),
|
|
message: 'Test data from iframe',
|
|
};
|
|
await PluginAPI.persistDataSynced(JSON.stringify(testData));
|
|
log('Data saved successfully: ' + JSON.stringify(testData), 'success');
|
|
} catch (error) {
|
|
log('Failed to save data: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
async function testLoadData() {
|
|
try {
|
|
const data = await PluginAPI.loadSyncedData();
|
|
if (data) {
|
|
const parsed = JSON.parse(data);
|
|
log('Data loaded successfully: ' + JSON.stringify(parsed), 'success');
|
|
} else {
|
|
log('No saved data found', 'info');
|
|
}
|
|
} catch (error) {
|
|
log('Failed to load data: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
async function testGetTasks() {
|
|
try {
|
|
const tasks = await PluginAPI.getTasks();
|
|
log(`Found ${tasks.length} tasks`, 'success');
|
|
if (tasks.length > 0) {
|
|
lastTaskId = tasks[0].id;
|
|
log(`Sample task: "${tasks[0].title}"`, 'info');
|
|
}
|
|
} catch (error) {
|
|
log('Failed to get tasks: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
async function testGetArchivedTasks() {
|
|
try {
|
|
const tasks = await PluginAPI.getArchivedTasks();
|
|
log(`Found ${tasks.length} archived tasks`, 'success');
|
|
} catch (error) {
|
|
log('Failed to get archived tasks: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
async function testGetContextTasks() {
|
|
try {
|
|
const tasks = await PluginAPI.getCurrentContextTasks();
|
|
log(`Found ${tasks.length} tasks in current context`, 'success');
|
|
} catch (error) {
|
|
log('Failed to get context tasks: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
async function testCreateTask() {
|
|
try {
|
|
const taskData = {
|
|
title: 'Test Task from iFrame - ' + new Date().toLocaleTimeString(),
|
|
notes: 'Created from the API Test Plugin dashboard',
|
|
timeEstimate: 1800000, // 30 minutes
|
|
};
|
|
lastTaskId = await PluginAPI.addTask(taskData);
|
|
log(`Task created with ID: ${lastTaskId}`, 'success');
|
|
} catch (error) {
|
|
log('Failed to create task: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
async function testUpdateTask() {
|
|
if (!lastTaskId) {
|
|
log('No task ID available. Create a task first!', 'error');
|
|
return;
|
|
}
|
|
try {
|
|
await PluginAPI.updateTask(lastTaskId, {
|
|
notes: 'Updated from dashboard at ' + new Date().toLocaleTimeString(),
|
|
});
|
|
log(`Task ${lastTaskId} updated successfully`, 'success');
|
|
} catch (error) {
|
|
log('Failed to update task: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
async function testGetProjects() {
|
|
try {
|
|
const projects = await PluginAPI.getAllProjects();
|
|
log(`Found ${projects.length} projects`, 'success');
|
|
if (projects.length > 0) {
|
|
lastProjectId = projects[0].id;
|
|
log(`Sample project: "${projects[0].title}"`, 'info');
|
|
}
|
|
} catch (error) {
|
|
log('Failed to get projects: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
async function testCreateProject() {
|
|
try {
|
|
const project = await PluginAPI.addProject({
|
|
title: 'Test Project - ' + new Date().toLocaleDateString(),
|
|
themeColor: '#' + Math.floor(Math.random() * 16777215).toString(16),
|
|
});
|
|
lastProjectId = project.id;
|
|
log(`Project created: "${project.title}"`, 'success');
|
|
} catch (error) {
|
|
log('Failed to create project: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
// Counter test functions
|
|
async function testSetCounter() {
|
|
try {
|
|
const value = Math.floor(Math.random() * 100);
|
|
await PluginAPI.setCounter('testCounter', value);
|
|
log(`Counter 'testCounter' set to ${value}`, 'success');
|
|
} catch (error) {
|
|
log('Failed to set counter: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
async function testGetCounter() {
|
|
try {
|
|
const value = await PluginAPI.getCounter('testCounter');
|
|
if (value !== null) {
|
|
log(`Counter 'testCounter' value: ${value}`, 'success');
|
|
} else {
|
|
log("Counter 'testCounter' not found", 'info');
|
|
}
|
|
} catch (error) {
|
|
log('Failed to get counter: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
async function testIncrementCounter() {
|
|
try {
|
|
const newValue = await PluginAPI.incrementCounter('testCounter', 5);
|
|
log(
|
|
`Counter 'testCounter' incremented by 5, new value: ${newValue}`,
|
|
'success',
|
|
);
|
|
} catch (error) {
|
|
log('Failed to increment counter: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
async function testDecrementCounter() {
|
|
try {
|
|
const newValue = await PluginAPI.decrementCounter('testCounter', 3);
|
|
log(
|
|
`Counter 'testCounter' decremented by 3, new value: ${newValue}`,
|
|
'success',
|
|
);
|
|
} catch (error) {
|
|
log('Failed to decrement counter: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
async function testDeleteCounter() {
|
|
try {
|
|
await PluginAPI.deleteCounter('testCounter');
|
|
log("Counter 'testCounter' deleted", 'success');
|
|
} catch (error) {
|
|
log('Failed to delete counter: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
async function testGetAllCounters() {
|
|
try {
|
|
// Create some test counters first
|
|
await PluginAPI.setCounter('counter1', 10);
|
|
await PluginAPI.setCounter('counter2', 20);
|
|
await PluginAPI.setCounter('counter3', 30);
|
|
|
|
const counters = await PluginAPI.getAllCounters();
|
|
log('All counters: ' + JSON.stringify(counters), 'success');
|
|
} catch (error) {
|
|
log('Failed to get all counters: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
async function testGetTags() {
|
|
try {
|
|
const tags = await PluginAPI.getAllTags();
|
|
log(`Found ${tags.length} tags`, 'success');
|
|
if (tags.length > 0) {
|
|
lastTagId = tags[0].id;
|
|
log(`Sample tag: "${tags[0].title}"`, 'info');
|
|
}
|
|
} catch (error) {
|
|
log('Failed to get tags: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
async function testCreateTag() {
|
|
try {
|
|
const tag = await PluginAPI.addTag({
|
|
title: 'Test Tag - ' + Date.now(),
|
|
color: '#' + Math.floor(Math.random() * 16777215).toString(16),
|
|
});
|
|
lastTagId = tag.id;
|
|
log(`Tag created: "${tag.title}"`, 'success');
|
|
} catch (error) {
|
|
log('Failed to create tag: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
function testSnackSuccess() {
|
|
PluginAPI.showSnack({
|
|
msg: 'This is a success message',
|
|
type: 'SUCCESS',
|
|
ico: 'check_circle',
|
|
});
|
|
log('Success snack shown', 'success');
|
|
}
|
|
|
|
function testSnackError() {
|
|
PluginAPI.showSnack({
|
|
msg: 'This is an error message',
|
|
type: 'ERROR',
|
|
ico: 'error',
|
|
});
|
|
log('Error snack shown', 'success');
|
|
}
|
|
|
|
function testSnackCustom() {
|
|
PluginAPI.showSnack({
|
|
msg: 'This is an info message',
|
|
type: 'INFO',
|
|
ico: 'info',
|
|
});
|
|
log('Info snack shown', 'success');
|
|
}
|
|
|
|
function testNotification() {
|
|
PluginAPI.notify({
|
|
title: 'API Test Notification',
|
|
body: 'This notification was triggered from the plugin dashboard!',
|
|
});
|
|
log('Notification sent', 'success');
|
|
}
|
|
|
|
function testDialog() {
|
|
PluginAPI.openDialog({
|
|
title: 'Test Dialog from iFrame',
|
|
htmlContent: `
|
|
<div style="padding: 20px; color: #ccc; font-family: monospace;">
|
|
<h3 style="margin: 0 0 10px 0; font-size: 14px;">Test Dialog</h3>
|
|
<p style="margin: 5px 0; font-size: 12px;">Dialog opened from plugin dashboard</p>
|
|
<p style="margin: 5px 0; font-size: 12px; color: #999;">${new Date().toLocaleString()}</p>
|
|
</div>
|
|
`,
|
|
buttons: [
|
|
{
|
|
label: 'Awesome',
|
|
icon: 'thumb_up',
|
|
color: 'primary',
|
|
onClick: () => {
|
|
log('Dialog button clicked', 'success');
|
|
},
|
|
},
|
|
],
|
|
});
|
|
log('Dialog opened', 'success');
|
|
}
|
|
|
|
function testThemeInfo() {
|
|
try {
|
|
const themeInfo = PluginAPI.getThemeInfo();
|
|
log('Theme Info:', 'info');
|
|
log(' Dark Theme: ' + themeInfo.isDarkTheme, 'info');
|
|
log(' Primary Color: ' + themeInfo.primaryColor, 'info');
|
|
log(' Accent Color: ' + themeInfo.accentColor, 'info');
|
|
log(' Warn Color: ' + themeInfo.warnColor, 'info');
|
|
log(' Background: ' + themeInfo.backgroundColor, 'info');
|
|
log(' Text Color: ' + themeInfo.textColor, 'info');
|
|
|
|
// Also show in a dialog
|
|
PluginAPI.openDialog({
|
|
title: 'Current Theme Information',
|
|
htmlContent: `
|
|
<div style="padding: 20px; font-family: monospace;">
|
|
<h3 style="margin: 0 0 15px 0;">Theme Variables</h3>
|
|
<table style="width: 100%; border-collapse: collapse;">
|
|
<tr style="border-bottom: 1px solid var(--divider-color, #333);">
|
|
<td style="padding: 8px;">Dark Theme</td>
|
|
<td style="padding: 8px; text-align: right;">${themeInfo.isDarkTheme ? 'Yes' : 'No'}</td>
|
|
</tr>
|
|
<tr style="border-bottom: 1px solid var(--divider-color, #333);">
|
|
<td style="padding: 8px;">Primary Color</td>
|
|
<td style="padding: 8px; text-align: right;">
|
|
<span style="display: inline-block; width: 20px; height: 20px; background: ${themeInfo.primaryColor}; vertical-align: middle; margin-right: 8px; border: 1px solid var(--divider-color, #333);"></span>
|
|
${themeInfo.primaryColor}
|
|
</td>
|
|
</tr>
|
|
<tr style="border-bottom: 1px solid var(--divider-color, #333);">
|
|
<td style="padding: 8px;">Accent Color</td>
|
|
<td style="padding: 8px; text-align: right;">
|
|
<span style="display: inline-block; width: 20px; height: 20px; background: ${themeInfo.accentColor}; vertical-align: middle; margin-right: 8px; border: 1px solid var(--divider-color, #333);"></span>
|
|
${themeInfo.accentColor}
|
|
</td>
|
|
</tr>
|
|
<tr style="border-bottom: 1px solid var(--divider-color, #333);">
|
|
<td style="padding: 8px;">Warn Color</td>
|
|
<td style="padding: 8px; text-align: right;">
|
|
<span style="display: inline-block; width: 20px; height: 20px; background: ${themeInfo.warnColor}; vertical-align: middle; margin-right: 8px; border: 1px solid var(--divider-color, #333);"></span>
|
|
${themeInfo.warnColor}
|
|
</td>
|
|
</tr>
|
|
<tr style="border-bottom: 1px solid var(--divider-color, #333);">
|
|
<td style="padding: 8px;">Background</td>
|
|
<td style="padding: 8px; text-align: right;">
|
|
<span style="display: inline-block; width: 20px; height: 20px; background: ${themeInfo.backgroundColor}; vertical-align: middle; margin-right: 8px; border: 1px solid var(--divider-color, #333);"></span>
|
|
${themeInfo.backgroundColor}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding: 8px;">Text Color</td>
|
|
<td style="padding: 8px; text-align: right;">
|
|
<span style="display: inline-block; width: 20px; height: 20px; background: ${themeInfo.textColor}; vertical-align: middle; margin-right: 8px; border: 1px solid var(--divider-color, #333);"></span>
|
|
${themeInfo.textColor}
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p style="margin-top: 15px; font-size: 12px; color: var(--text-color-muted, #999);">
|
|
Plugins automatically receive all CSS variables from the host application, allowing seamless theme integration.
|
|
</p>
|
|
</div>
|
|
`,
|
|
buttons: [
|
|
{
|
|
label: 'Close',
|
|
color: 'primary',
|
|
},
|
|
],
|
|
});
|
|
} catch (error) {
|
|
log('Failed to get theme info: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
async function runAllTests() {
|
|
clearConsole();
|
|
log('Starting comprehensive API test suite...', 'info');
|
|
|
|
// Run all tests with delays
|
|
await testPersistData();
|
|
await new Promise((r) => setTimeout(r, 500));
|
|
|
|
await testLoadData();
|
|
await new Promise((r) => setTimeout(r, 500));
|
|
|
|
await testGetTasks();
|
|
await new Promise((r) => setTimeout(r, 500));
|
|
|
|
await testGetArchivedTasks();
|
|
await new Promise((r) => setTimeout(r, 500));
|
|
|
|
await testGetContextTasks();
|
|
await new Promise((r) => setTimeout(r, 500));
|
|
|
|
await testCreateTask();
|
|
await new Promise((r) => setTimeout(r, 500));
|
|
|
|
if (lastTaskId) {
|
|
await testUpdateTask();
|
|
await new Promise((r) => setTimeout(r, 500));
|
|
}
|
|
|
|
await testGetProjects();
|
|
await new Promise((r) => setTimeout(r, 500));
|
|
|
|
await testCreateProject();
|
|
await new Promise((r) => setTimeout(r, 500));
|
|
|
|
await testGetTags();
|
|
await new Promise((r) => setTimeout(r, 500));
|
|
|
|
await testCreateTag();
|
|
await new Promise((r) => setTimeout(r, 500));
|
|
|
|
// Test counter API
|
|
await testSetCounter();
|
|
await new Promise((r) => setTimeout(r, 500));
|
|
|
|
await testGetCounter();
|
|
await new Promise((r) => setTimeout(r, 500));
|
|
|
|
await testIncrementCounter();
|
|
await new Promise((r) => setTimeout(r, 500));
|
|
|
|
await testDecrementCounter();
|
|
await new Promise((r) => setTimeout(r, 500));
|
|
|
|
await testGetAllCounters();
|
|
await new Promise((r) => setTimeout(r, 500));
|
|
|
|
testSnackSuccess();
|
|
await new Promise((r) => setTimeout(r, 1500));
|
|
|
|
testSnackError();
|
|
await new Promise((r) => setTimeout(r, 1500));
|
|
|
|
testSnackCustom();
|
|
await new Promise((r) => setTimeout(r, 1500));
|
|
|
|
testNotification();
|
|
await new Promise((r) => setTimeout(r, 1000));
|
|
|
|
testDialog();
|
|
|
|
log('All tests completed! Check console for detailed results.', 'success');
|
|
}
|
|
|
|
// Advanced Dialog Examples
|
|
function showTaskPlannerDialog() {
|
|
PluginAPI.openDialog({
|
|
title: 'AI Task Planner (Demo)',
|
|
htmlContent: `
|
|
<div style="padding: 20px; max-width: 700px;">
|
|
<div style="display: flex; gap: 20px;">
|
|
<div style="flex: 1;">
|
|
<h4 style="margin-top: 0;">Describe Your Goal</h4>
|
|
<textarea style="width: 100%; min-height: 100px; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-family: inherit;" placeholder="E.g., 'Launch a new mobile app by Q3 2024'">Build a comprehensive plugin system for Super Productivity that allows users to extend functionality</textarea>
|
|
|
|
<h4 style="margin-top: 20px;">Constraints & Preferences</h4>
|
|
<div style="margin-bottom: 10px;">
|
|
<label>
|
|
<input type="checkbox" checked> Break down into weekly milestones
|
|
</label>
|
|
</div>
|
|
<div style="margin-bottom: 10px;">
|
|
<label>
|
|
<input type="checkbox" checked> Include time estimates
|
|
</label>
|
|
</div>
|
|
<div style="margin-bottom: 10px;">
|
|
<label>
|
|
<input type="checkbox"> Add dependencies between tasks
|
|
</label>
|
|
</div>
|
|
<div style="margin-bottom: 10px;">
|
|
<label>
|
|
<input type="checkbox" checked> Prioritize by impact
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="flex: 1; background: #f9f9f9; padding: 15px; border-radius: 8px;">
|
|
<h4 style="margin-top: 0;">Generated Task Breakdown</h4>
|
|
<div style="max-height: 300px; overflow-y: auto;">
|
|
<div style="margin-bottom: 15px; padding: 10px; background: white; border-radius: 4px; border-left: 4px solid #4caf50;">
|
|
<div style="font-weight: bold;">📋 Design Plugin Architecture</div>
|
|
<div style="font-size: 0.9em; color: #666; margin-top: 5px;">Est: 8h | Priority: High</div>
|
|
<div style="font-size: 0.85em; margin-top: 5px;">Define API surface, security model, and manifest structure</div>
|
|
</div>
|
|
<div style="margin-bottom: 15px; padding: 10px; background: white; border-radius: 4px; border-left: 4px solid #ff9800;">
|
|
<div style="font-weight: bold;">🔧 Implement Core Plugin Loader</div>
|
|
<div style="font-size: 0.9em; color: #666; margin-top: 5px;">Est: 16h | Priority: High</div>
|
|
<div style="font-size: 0.85em; margin-top: 5px;">Build sandboxed execution environment and API bridge</div>
|
|
</div>
|
|
<div style="margin-bottom: 15px; padding: 10px; background: white; border-radius: 4px; border-left: 4px solid #2196f3;">
|
|
<div style="font-weight: bold;">🎨 Create Plugin UI Components</div>
|
|
<div style="font-size: 0.9em; color: #666; margin-top: 5px;">Est: 12h | Priority: Medium</div>
|
|
<div style="font-size: 0.85em; margin-top: 5px;">Design settings UI, permission dialogs, and plugin store</div>
|
|
</div>
|
|
<div style="margin-bottom: 15px; padding: 10px; background: white; border-radius: 4px; border-left: 4px solid #9c27b0;">
|
|
<div style="font-weight: bold;">📚 Write Documentation</div>
|
|
<div style="font-size: 0.9em; color: #666; margin-top: 5px;">Est: 6h | Priority: Medium</div>
|
|
<div style="font-size: 0.85em; margin-top: 5px;">Create plugin development guide and API reference</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top: 20px; padding: 15px; background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 4px;">
|
|
<strong>🤖 AI Analysis:</strong> This project would take approximately 42 hours (5-6 days) with the current breakdown. Consider adding a testing phase and security audit.
|
|
</div>
|
|
</div>
|
|
`,
|
|
buttons: [
|
|
{
|
|
label: 'Regenerate',
|
|
icon: 'refresh',
|
|
onClick: async () => {
|
|
await PluginAPI.showSnack({
|
|
msg: 'Regenerating task breakdown...',
|
|
type: 'INFO',
|
|
ico: 'refresh',
|
|
});
|
|
},
|
|
},
|
|
{
|
|
label: 'Create All Tasks',
|
|
icon: 'add_task',
|
|
color: 'primary',
|
|
onClick: async () => {
|
|
await PluginAPI.showSnack({
|
|
msg: 'Would create 4 tasks in your project',
|
|
type: 'SUCCESS',
|
|
});
|
|
},
|
|
},
|
|
],
|
|
});
|
|
log('Task planner dialog opened', 'success');
|
|
}
|
|
|
|
function showAnalyticsDialog() {
|
|
PluginAPI.openDialog({
|
|
title: 'Productivity Analytics',
|
|
htmlContent: `
|
|
<div style="padding: 20px; max-width: 800px;">
|
|
<div style="display: flex; justify-content: space-between; margin-bottom: 20px;">
|
|
<div>
|
|
<h3 style="margin: 0;">Weekly Performance</h3>
|
|
<p style="margin: 5px 0; color: #666;">Dec 11 - Dec 17, 2023</p>
|
|
</div>
|
|
<div style="display: flex; gap: 10px; align-items: center;">
|
|
<button style="padding: 8px 16px; border: 1px solid #ddd; background: white; border-radius: 4px; cursor: pointer;">Week</button>
|
|
<button style="padding: 8px 16px; border: 1px solid #4caf50; background: #4caf50; color: white; border-radius: 4px; cursor: pointer;">Month</button>
|
|
<button style="padding: 8px 16px; border: 1px solid #ddd; background: white; border-radius: 4px; cursor: pointer;">Year</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 15px; margin-bottom: 30px;">
|
|
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 8px;">
|
|
<div style="font-size: 2em; font-weight: bold;">147</div>
|
|
<div style="opacity: 0.9;">Tasks Completed</div>
|
|
<div style="font-size: 0.9em; margin-top: 5px; opacity: 0.8;">↑ 23% from last week</div>
|
|
</div>
|
|
<div style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); color: white; padding: 20px; border-radius: 8px;">
|
|
<div style="font-size: 2em; font-weight: bold;">42.5h</div>
|
|
<div style="opacity: 0.9;">Time Tracked</div>
|
|
<div style="font-size: 0.9em; margin-top: 5px; opacity: 0.8;">↑ 5% from last week</div>
|
|
</div>
|
|
<div style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); color: white; padding: 20px; border-radius: 8px;">
|
|
<div style="font-size: 2em; font-weight: bold;">89%</div>
|
|
<div style="opacity: 0.9;">Focus Score</div>
|
|
<div style="font-size: 0.9em; margin-top: 5px; opacity: 0.8;">↓ 2% from last week</div>
|
|
</div>
|
|
<div style="background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%); color: white; padding: 20px; border-radius: 8px;">
|
|
<div style="font-size: 2em; font-weight: bold;">12</div>
|
|
<div style="opacity: 0.9;">Streaks Active</div>
|
|
<div style="font-size: 0.9em; margin-top: 5px; opacity: 0.8;">Keep it up! 🔥</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="background: #f9f9f9; padding: 20px; border-radius: 8px;">
|
|
<h4 style="margin-top: 0;">Daily Activity Heatmap</h4>
|
|
<div style="display: grid; grid-template-columns: auto repeat(7, 1fr); gap: 10px; font-size: 0.9em;">
|
|
<div></div>
|
|
<div style="text-align: center;">Mon</div>
|
|
<div style="text-align: center;">Tue</div>
|
|
<div style="text-align: center;">Wed</div>
|
|
<div style="text-align: center;">Thu</div>
|
|
<div style="text-align: center;">Fri</div>
|
|
<div style="text-align: center;">Sat</div>
|
|
<div style="text-align: center;">Sun</div>
|
|
|
|
<div>Morning</div>
|
|
<div style="background: #c8e6c9; height: 40px; border-radius: 4px;"></div>
|
|
<div style="background: #4caf50; height: 40px; border-radius: 4px;"></div>
|
|
<div style="background: #81c784; height: 40px; border-radius: 4px;"></div>
|
|
<div style="background: #4caf50; height: 40px; border-radius: 4px;"></div>
|
|
<div style="background: #a5d6a7; height: 40px; border-radius: 4px;"></div>
|
|
<div style="background: #e8f5e9; height: 40px; border-radius: 4px;"></div>
|
|
<div style="background: #e8f5e9; height: 40px; border-radius: 4px;"></div>
|
|
|
|
<div>Afternoon</div>
|
|
<div style="background: #4caf50; height: 40px; border-radius: 4px;"></div>
|
|
<div style="background: #2e7d32; height: 40px; border-radius: 4px;"></div>
|
|
<div style="background: #4caf50; height: 40px; border-radius: 4px;"></div>
|
|
<div style="background: #81c784; height: 40px; border-radius: 4px;"></div>
|
|
<div style="background: #4caf50; height: 40px; border-radius: 4px;"></div>
|
|
<div style="background: #a5d6a7; height: 40px; border-radius: 4px;"></div>
|
|
<div style="background: #c8e6c9; height: 40px; border-radius: 4px;"></div>
|
|
|
|
<div>Evening</div>
|
|
<div style="background: #81c784; height: 40px; border-radius: 4px;"></div>
|
|
<div style="background: #a5d6a7; height: 40px; border-radius: 4px;"></div>
|
|
<div style="background: #c8e6c9; height: 40px; border-radius: 4px;"></div>
|
|
<div style="background: #e8f5e9; height: 40px; border-radius: 4px;"></div>
|
|
<div style="background: #e8f5e9; height: 40px; border-radius: 4px;"></div>
|
|
<div style="background: #81c784; height: 40px; border-radius: 4px;"></div>
|
|
<div style="background: #4caf50; height: 40px; border-radius: 4px;"></div>
|
|
</div>
|
|
<div style="margin-top: 15px; text-align: center; color: #666;">
|
|
<span style="display: inline-block; width: 12px; height: 12px; background: #e8f5e9; margin-right: 5px;"></span> Low
|
|
<span style="display: inline-block; width: 12px; height: 12px; background: #81c784; margin: 0 5px 0 20px;"></span> Medium
|
|
<span style="display: inline-block; width: 12px; height: 12px; background: #4caf50; margin: 0 5px 0 20px;"></span> High
|
|
<span style="display: inline-block; width: 12px; height: 12px; background: #2e7d32; margin: 0 5px 0 20px;"></span> Very High
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`,
|
|
buttons: [
|
|
{
|
|
label: 'Export Report',
|
|
icon: 'download',
|
|
onClick: async () => {
|
|
await PluginAPI.showSnack({
|
|
msg: 'Generating productivity report...',
|
|
type: 'INFO',
|
|
ico: 'download',
|
|
});
|
|
},
|
|
},
|
|
{
|
|
label: 'Share',
|
|
icon: 'share',
|
|
onClick: async () => {
|
|
await PluginAPI.showSnack({
|
|
msg: 'Sharing options would appear here',
|
|
type: 'INFO',
|
|
ico: 'share',
|
|
});
|
|
},
|
|
},
|
|
{
|
|
label: 'Close',
|
|
icon: 'close',
|
|
color: 'primary',
|
|
},
|
|
],
|
|
});
|
|
log('Analytics dialog opened', 'success');
|
|
}
|
|
|
|
// Initial message
|
|
log(
|
|
'API Test Plugin Dashboard loaded. Click buttons to test individual APIs or run all tests.',
|
|
'info',
|
|
);
|
|
</script>
|
|
</body>
|
|
</html>
|