Skip to content

Commit b0bc536

Browse files
author
catlog22
committed
feat(dashboard): complete icon unification across all views
- Update home.js: inbox, calendar, list-checks icons - Update project-overview.js: code-2, blocks, component, git-branch, sparkles, bug, wrench, book-open icons - Update session-detail.js: list-checks, package, file-text, ruler, scale, search icons for tabs - Update lite-tasks.js: zap, file-edit, wrench, calendar, list-checks, ruler, package, file-text icons - Update mcp-manager.js: plug, building-2, user, map-pin, check-circle, x-circle, circle-dashed, lock icons - Update hook-manager.js: webhook, pencil, trash-2, clock, check-circle, bell, octagon-x icons - Add getHookEventIconLucide() helper function - Initialize Lucide icons after dynamic content rendering All emoji icons replaced with consistent Lucide SVG icons
1 parent 5f31c9a commit b0bc536

File tree

10 files changed

+303
-160
lines changed

10 files changed

+303
-160
lines changed

ccw/src/core/server.js

Lines changed: 91 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1810,54 +1810,109 @@ async function getFileContent(filePath) {
18101810
}
18111811

18121812
/**
1813-
* Trigger update-module-claude tool
1813+
* Trigger update-module-claude tool (async execution)
18141814
* @param {string} targetPath - Directory path to update
18151815
* @param {string} tool - CLI tool to use (gemini, qwen, codex)
18161816
* @param {string} strategy - Update strategy (single-layer, multi-layer)
18171817
* @returns {Promise<Object>}
18181818
*/
18191819
async function triggerUpdateClaudeMd(targetPath, tool, strategy) {
1820-
const { execSync } = await import('child_process');
1820+
const { spawn } = await import('child_process');
18211821

1822-
try {
1823-
// Normalize path
1824-
let normalizedPath = targetPath.replace(/\\/g, '/');
1825-
if (normalizedPath.match(/^\/[a-zA-Z]\//)) {
1826-
normalizedPath = normalizedPath.charAt(1).toUpperCase() + ':' + normalizedPath.slice(2);
1827-
}
1822+
// Normalize path
1823+
let normalizedPath = targetPath.replace(/\\/g, '/');
1824+
if (normalizedPath.match(/^\/[a-zA-Z]\//)) {
1825+
normalizedPath = normalizedPath.charAt(1).toUpperCase() + ':' + normalizedPath.slice(2);
1826+
}
1827+
1828+
if (!existsSync(normalizedPath)) {
1829+
return { error: 'Directory not found' };
1830+
}
1831+
1832+
if (!statSync(normalizedPath).isDirectory()) {
1833+
return { error: 'Not a directory' };
1834+
}
1835+
1836+
// Build ccw tool command with JSON parameters
1837+
const params = JSON.stringify({
1838+
strategy,
1839+
path: normalizedPath,
1840+
tool
1841+
});
1842+
1843+
console.log(`[Explorer] Running async: ccw tool exec update_module_claude with ${tool} (${strategy})`);
1844+
1845+
return new Promise((resolve) => {
1846+
const isWindows = process.platform === 'win32';
18281847

1829-
if (!existsSync(normalizedPath)) {
1830-
return { error: 'Directory not found' };
1831-
}
1848+
// Spawn the process
1849+
const child = spawn('ccw', ['tool', 'exec', 'update_module_claude', params], {
1850+
cwd: normalizedPath,
1851+
shell: isWindows,
1852+
stdio: ['ignore', 'pipe', 'pipe']
1853+
});
18321854

1833-
if (!statSync(normalizedPath).isDirectory()) {
1834-
return { error: 'Not a directory' };
1835-
}
1855+
let stdout = '';
1856+
let stderr = '';
18361857

1837-
// Build ccw tool command
1838-
const ccwBin = join(import.meta.dirname, '../../bin/ccw.js');
1839-
const command = `node "${ccwBin}" tool update_module_claude --strategy="${strategy}" --path="${normalizedPath}" --tool="${tool}"`;
1858+
child.stdout.on('data', (data) => {
1859+
stdout += data.toString();
1860+
});
18401861

1841-
console.log(`[Explorer] Running: ${command}`);
1862+
child.stderr.on('data', (data) => {
1863+
stderr += data.toString();
1864+
});
18421865

1843-
const output = execSync(command, {
1844-
encoding: 'utf8',
1845-
timeout: 300000, // 5 minutes
1846-
cwd: normalizedPath
1866+
child.on('close', (code) => {
1867+
if (code === 0) {
1868+
// Parse the JSON output from the tool
1869+
let result;
1870+
try {
1871+
result = JSON.parse(stdout);
1872+
} catch {
1873+
result = { output: stdout };
1874+
}
1875+
1876+
if (result.success === false || result.error) {
1877+
resolve({
1878+
success: false,
1879+
error: result.error || result.message || 'Update failed',
1880+
output: stdout
1881+
});
1882+
} else {
1883+
resolve({
1884+
success: true,
1885+
message: result.message || `CLAUDE.md updated successfully using ${tool} (${strategy})`,
1886+
output: stdout,
1887+
path: normalizedPath
1888+
});
1889+
}
1890+
} else {
1891+
resolve({
1892+
success: false,
1893+
error: stderr || `Process exited with code ${code}`,
1894+
output: stdout + stderr
1895+
});
1896+
}
18471897
});
18481898

1849-
return {
1850-
success: true,
1851-
message: `CLAUDE.md updated successfully using ${tool} (${strategy})`,
1852-
output,
1853-
path: normalizedPath
1854-
};
1855-
} catch (error) {
1856-
console.error('Error updating CLAUDE.md:', error);
1857-
return {
1858-
success: false,
1859-
error: error.message,
1860-
output: error.stdout || error.stderr || ''
1861-
};
1862-
}
1899+
child.on('error', (error) => {
1900+
console.error('Error spawning process:', error);
1901+
resolve({
1902+
success: false,
1903+
error: error.message,
1904+
output: ''
1905+
});
1906+
});
1907+
1908+
// Timeout after 5 minutes
1909+
setTimeout(() => {
1910+
child.kill();
1911+
resolve({
1912+
success: false,
1913+
error: 'Timeout: Process took longer than 5 minutes',
1914+
output: stdout
1915+
});
1916+
}, 300000);
1917+
});
18631918
}

ccw/src/templates/dashboard-css/09-explorer.css

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -847,11 +847,55 @@
847847
color: hsl(var(--foreground));
848848
}
849849

850-
.task-queue-actions {
850+
/* Task Queue Toolbar */
851+
.task-queue-toolbar {
851852
display: flex;
852-
gap: 8px;
853-
padding: 10px 16px;
853+
align-items: center;
854+
justify-content: space-between;
855+
padding: 10px 12px;
854856
border-bottom: 1px solid hsl(var(--border));
857+
gap: 8px;
858+
}
859+
860+
/* CLI Selector */
861+
.queue-cli-selector {
862+
display: flex;
863+
align-items: center;
864+
gap: 6px;
865+
}
866+
867+
.queue-cli-selector label {
868+
font-size: 12px;
869+
font-weight: 500;
870+
color: hsl(var(--muted-foreground));
871+
}
872+
873+
.queue-cli-selector select {
874+
padding: 5px 8px;
875+
border: 1px solid hsl(var(--border));
876+
background: hsl(var(--background));
877+
color: hsl(var(--foreground));
878+
border-radius: 6px;
879+
font-size: 12px;
880+
font-weight: 500;
881+
cursor: pointer;
882+
transition: all 0.15s ease;
883+
min-width: 100px;
884+
}
885+
886+
.queue-cli-selector select:hover {
887+
border-color: hsl(var(--primary));
888+
}
889+
890+
.queue-cli-selector select:focus {
891+
outline: none;
892+
border-color: hsl(var(--primary));
893+
box-shadow: 0 0 0 2px hsl(var(--primary) / 0.2);
894+
}
895+
896+
.task-queue-actions {
897+
display: flex;
898+
gap: 4px;
855899
}
856900

857901
.queue-action-btn {

ccw/src/templates/dashboard-js/components/hook-manager.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,3 +271,13 @@ function getHookEventIcon(event) {
271271
};
272272
return icons[event] || '🪝';
273273
}
274+
275+
function getHookEventIconLucide(event) {
276+
const icons = {
277+
'PreToolUse': '<i data-lucide="clock" class="w-5 h-5"></i>',
278+
'PostToolUse': '<i data-lucide="check-circle" class="w-5 h-5"></i>',
279+
'Notification': '<i data-lucide="bell" class="w-5 h-5"></i>',
280+
'Stop': '<i data-lucide="octagon-x" class="w-5 h-5"></i>'
281+
};
282+
return icons[event] || '<i data-lucide="webhook" class="w-5 h-5"></i>';
283+
}

0 commit comments

Comments
 (0)