mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-05 01:50:27 +08:00
Enhance CLI Stream Viewer and Navigation Lifecycle Management
- Added lifecycle management for CLI Stream Viewer with destroy function to clean up event listeners and timers. - Improved navigation state management by registering destroy functions for views and ensuring cleanup on transitions. - Updated Claude Manager to include lifecycle functions for better resource management. - Enhanced CLI History View with state reset functionality and improved dropdown handling for batch delete. - Introduced round solutions rendering in Lite Tasks View, including collapsible sections for implementation plans, dependencies, and technical concerns.
This commit is contained in:
@@ -1190,12 +1190,27 @@
|
||||
border-radius: 0.5rem;
|
||||
padding: 1rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.multi-cli-card::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: 0.5rem;
|
||||
border: 2px solid transparent;
|
||||
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.multi-cli-card:hover {
|
||||
border-color: hsl(var(--purple, 280 60% 50%) / 0.5);
|
||||
box-shadow: 0 4px 12px hsl(var(--purple, 280 60% 50%) / 0.1);
|
||||
box-shadow: 0 4px 16px hsl(var(--purple, 280 60% 50%) / 0.15);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.multi-cli-card:hover::before {
|
||||
border-color: hsl(var(--purple, 280 60% 50%) / 0.3);
|
||||
}
|
||||
|
||||
.multi-cli-card-header {
|
||||
@@ -1246,7 +1261,8 @@
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.multi-cli-status.converged {
|
||||
.multi-cli-status.converged,
|
||||
.multi-cli-status.decided {
|
||||
background: hsl(var(--success-light, 142 70% 95%));
|
||||
color: hsl(var(--success, 142 70% 45%));
|
||||
}
|
||||
@@ -1256,16 +1272,25 @@
|
||||
color: hsl(var(--warning, 45 90% 40%));
|
||||
}
|
||||
|
||||
.multi-cli-status.blocked {
|
||||
.multi-cli-status.blocked,
|
||||
.multi-cli-status.conflict {
|
||||
background: hsl(var(--destructive) / 0.1);
|
||||
color: hsl(var(--destructive));
|
||||
}
|
||||
|
||||
.multi-cli-status.pending {
|
||||
background: hsl(var(--muted));
|
||||
.multi-cli-status.pending,
|
||||
.multi-cli-status.exploring,
|
||||
.multi-cli-status.initialized {
|
||||
) background: hsl(var(--muted));
|
||||
color: hsl(var(--muted-foreground));
|
||||
}
|
||||
|
||||
.multi-cli-status.plan_generated,
|
||||
.multi-cli-status.completed {
|
||||
background: hsl(var(--success-light, 142 70% 95%));
|
||||
color: hsl(var(--success, 142 70% 45%));
|
||||
}
|
||||
|
||||
/* Multi-CLI Detail Page */
|
||||
.multi-cli-detail-page {
|
||||
display: flex;
|
||||
@@ -1286,6 +1311,25 @@
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.multi-cli-detail-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
flex-wrap: wrap;
|
||||
font-size: 0.85rem;
|
||||
color: hsl(var(--muted-foreground));
|
||||
}
|
||||
|
||||
.multi-cli-detail-meta .info-label {
|
||||
font-weight: 500;
|
||||
color: hsl(var(--muted-foreground));
|
||||
}
|
||||
|
||||
.multi-cli-detail-meta .info-value {
|
||||
color: hsl(var(--foreground));
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.multi-cli-detail-title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
@@ -1305,43 +1349,70 @@
|
||||
/* Multi-CLI Tabs */
|
||||
.multi-cli-tabs {
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
gap: 0;
|
||||
border-bottom: 1px solid hsl(var(--border));
|
||||
margin-bottom: 1rem;
|
||||
margin-bottom: 1.5rem;
|
||||
overflow-x: auto;
|
||||
background: hsl(var(--muted) / 0.2);
|
||||
padding: 0 0.5rem;
|
||||
border-radius: 0.5rem 0.5rem 0 0;
|
||||
}
|
||||
|
||||
.multi-cli-tab {
|
||||
padding: 0.75rem 1rem;
|
||||
padding: 0.75rem 1.25rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
color: hsl(var(--muted-foreground));
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-bottom: 2px solid transparent;
|
||||
border-bottom: 3px solid transparent;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
white-space: nowrap;
|
||||
border-radius: 0.375rem 0.375rem 0 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.multi-cli-tab:hover {
|
||||
color: hsl(var(--foreground));
|
||||
background: hsl(var(--hover));
|
||||
border-bottom-color: hsl(var(--purple, 280 60% 50%) / 0.5);
|
||||
}
|
||||
|
||||
.multi-cli-tab.active {
|
||||
color: hsl(var(--purple, 280 60% 50%));
|
||||
border-bottom-color: hsl(var(--purple, 280 60% 50%));
|
||||
background: hsl(var(--purple, 280 60% 50%) / 0.05);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.multi-cli-tab .tab-icon {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
.multi-cli-tab-content {
|
||||
display: none;
|
||||
animation: fadeIn 0.2s ease;
|
||||
}
|
||||
|
||||
.multi-cli-tab-content.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(4px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Multi-CLI Topic Tab */
|
||||
.multi-cli-topic-section {
|
||||
background: hsl(var(--muted) / 0.3);
|
||||
@@ -1349,6 +1420,12 @@
|
||||
border-radius: 0.5rem;
|
||||
padding: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
transition: border-color 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.multi-cli-topic-section:hover {
|
||||
border-color: hsl(var(--purple, 280 60% 50%) / 0.3);
|
||||
box-shadow: 0 2px 8px hsl(var(--purple, 280 60% 50%) / 0.05);
|
||||
}
|
||||
|
||||
.multi-cli-topic-title {
|
||||
@@ -1359,6 +1436,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.multi-cli-topic-description {
|
||||
@@ -1379,13 +1457,20 @@
|
||||
|
||||
/* Tag Badge */
|
||||
.tag-badge {
|
||||
display: inline-block;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
background: hsl(var(--primary) / 0.1);
|
||||
color: hsl(var(--primary));
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
transition: background 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
|
||||
.tag-badge:hover {
|
||||
background: hsl(var(--primary) / 0.15);
|
||||
}
|
||||
|
||||
/* Additional Multi-CLI Status Variants */
|
||||
@@ -1613,23 +1698,32 @@
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
/* Unified Solution Card - used in both Decision and Rounds tabs */
|
||||
.solution-card {
|
||||
background: hsl(var(--card));
|
||||
border: 1px solid hsl(var(--border));
|
||||
border-radius: 0.5rem;
|
||||
padding: 1rem;
|
||||
transition: all 0.2s ease;
|
||||
overflow: hidden;
|
||||
transition: border-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.solution-card:hover {
|
||||
border-color: hsl(var(--primary) / 0.3);
|
||||
box-shadow: 0 4px 12px hsla(var(--primary), 0.1);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.solution-card.selected {
|
||||
border-color: hsl(var(--success, 142 70% 45%));
|
||||
background: hsl(var(--success, 142 70% 45%) / 0.05);
|
||||
box-shadow: 0 0 0 6px hsl(var(--success, 142 70% 45%) / 0.15);
|
||||
}
|
||||
|
||||
.solution-card.rejected {
|
||||
border-color: hsl(var(--destructive) / 0.5);
|
||||
background: hsl(var(--destructive) / 0.03);
|
||||
opacity: 0.8;
|
||||
opacity: 0.7;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.solution-header {
|
||||
@@ -1638,6 +1732,9 @@
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
margin-bottom: 0.75rem;
|
||||
padding: 0.75rem 1rem;
|
||||
background: hsl(var(--muted) / 0.2);
|
||||
border-bottom: 1px solid hsl(var(--border));
|
||||
}
|
||||
|
||||
.solution-title {
|
||||
@@ -1740,8 +1837,9 @@
|
||||
|
||||
.timeline-event {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
gap: 1.25rem;
|
||||
position: relative;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.timeline-marker {
|
||||
@@ -1749,7 +1847,7 @@
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
width: 2rem;
|
||||
width: 2.25rem;
|
||||
}
|
||||
|
||||
.timeline-dot {
|
||||
@@ -1761,6 +1859,13 @@
|
||||
justify-content: center;
|
||||
z-index: 1;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0 0 0 3px currentColor;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.timeline-dot:hover {
|
||||
transform: scale(1.2);
|
||||
box-shadow: 0 0 0 8px currentColor;
|
||||
}
|
||||
|
||||
.timeline-dot.proposal {
|
||||
@@ -1806,12 +1911,15 @@
|
||||
background: hsl(var(--card));
|
||||
border: 1px solid hsl(var(--border));
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.75rem;
|
||||
padding: 1rem;
|
||||
margin-bottom: 0.75rem;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.timeline-content:hover {
|
||||
border-color: hsl(var(--primary) / 0.3);
|
||||
border-color: hsl(var(--primary) / 0.4);
|
||||
box-shadow: 0 2px 8px hsl(var(--primary) / 0.05);
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.timeline-event-header {
|
||||
@@ -1989,16 +2097,20 @@
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 3rem;
|
||||
padding: 4rem 2rem;
|
||||
text-align: center;
|
||||
color: hsl(var(--muted-foreground));
|
||||
background: hsl(var(--muted) / 0.2);
|
||||
border: 1px dashed hsl(var(--border));
|
||||
border-radius: 0.75rem;
|
||||
}
|
||||
|
||||
.multi-cli-empty-icon {
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
margin-bottom: 1rem;
|
||||
color: hsl(var(--muted-foreground) / 0.5);
|
||||
width: 3.5rem;
|
||||
height: 3.5rem;
|
||||
margin-bottom: 1.25rem;
|
||||
color: hsl(var(--purple, 280 60% 50%) / 0.4);
|
||||
animation: float 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.multi-cli-empty-title {
|
||||
@@ -2010,6 +2122,17 @@
|
||||
|
||||
.multi-cli-empty-description {
|
||||
font-size: 0.875rem;
|
||||
color: hsl(var(--muted-foreground));
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-8px);
|
||||
}
|
||||
}
|
||||
|
||||
/* ===================================
|
||||
@@ -2020,26 +2143,38 @@
|
||||
.scope-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.375rem;
|
||||
gap: 0.5rem;
|
||||
margin: 0;
|
||||
padding-left: 1rem;
|
||||
padding-left: 0;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.scope-list li {
|
||||
padding: 0.375rem 0.5rem;
|
||||
background: hsl(var(--muted) / 0.3);
|
||||
border-radius: 0.25rem;
|
||||
padding: 0.5rem 0.75rem;
|
||||
background: hsl(var(--card));
|
||||
border: 1px solid hsl(var(--border));
|
||||
border-radius: 0.375rem;
|
||||
font-family: var(--font-mono);
|
||||
color: hsl(var(--foreground));
|
||||
line-height: 1.4;
|
||||
line-height: 1.5;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.scope-list li:hover {
|
||||
border-color: hsl(var(--primary) / 0.5);
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.scope-list.excluded li {
|
||||
background: hsl(var(--destructive) / 0.08);
|
||||
background: hsl(var(--destructive) / 0.05);
|
||||
border-color: hsl(var(--destructive) / 0.2);
|
||||
color: hsl(var(--muted-foreground));
|
||||
text-decoration: line-through;
|
||||
opacity: 0.8;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.scope-list.excluded li:hover {
|
||||
border-color: hsl(var(--destructive) / 0.4);
|
||||
}
|
||||
|
||||
/* Acceptance List */
|
||||
@@ -2195,7 +2330,7 @@
|
||||
.cons-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.375rem;
|
||||
gap: 0.5rem;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
@@ -2205,17 +2340,24 @@
|
||||
.con-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 0.5rem;
|
||||
padding: 0.5rem 0.75rem;
|
||||
border-radius: 0.375rem;
|
||||
gap: 0.75rem;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 0.5rem;
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.5;
|
||||
line-height: 1.6;
|
||||
color: hsl(var(--foreground));
|
||||
transition: all 0.2s ease;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.pro-item {
|
||||
background: hsl(142 71% 45% / 0.08);
|
||||
border-left: 3px solid #10b981;
|
||||
border-left: 4px solid #10b981;
|
||||
}
|
||||
|
||||
.pro-item:hover {
|
||||
background: hsl(142 71% 45% / 0.12);
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.pro-item::before {
|
||||
@@ -2223,11 +2365,26 @@
|
||||
font-weight: 700;
|
||||
color: #10b981;
|
||||
flex-shrink: 0;
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #10b981;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
font-size: 1rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.con-item {
|
||||
background: hsl(0 84% 60% / 0.08);
|
||||
border-left: 3px solid #ef4444;
|
||||
border-left: 4px solid #ef4444;
|
||||
}
|
||||
|
||||
.con-item:hover {
|
||||
background: hsl(0 84% 60% / 0.12);
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.con-item::before {
|
||||
@@ -2235,40 +2392,64 @@
|
||||
font-weight: 700;
|
||||
color: #ef4444;
|
||||
flex-shrink: 0;
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #ef4444;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
font-size: 1.25rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* Rounds Navigation */
|
||||
.rounds-nav {
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
gap: 0.5rem;
|
||||
flex-wrap: wrap;
|
||||
padding-bottom: 0.75rem;
|
||||
padding-bottom: 1rem;
|
||||
border-bottom: 1px solid hsl(var(--border));
|
||||
margin-bottom: 1rem;
|
||||
background: hsl(var(--muted) / 0.2);
|
||||
padding: 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.round-item {
|
||||
padding: 0.5rem 0.875rem;
|
||||
background: hsl(var(--muted));
|
||||
padding: 0.5rem 1rem;
|
||||
background: hsl(var(--card));
|
||||
border: 1px solid hsl(var(--border));
|
||||
border-radius: 0.375rem;
|
||||
border-radius: 0.5rem;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 500;
|
||||
color: hsl(var(--muted-foreground));
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.375rem;
|
||||
}
|
||||
|
||||
.round-item:hover {
|
||||
background: hsl(var(--hover));
|
||||
border-color: hsl(var(--purple, 280 60% 50%) / 0.4);
|
||||
border-color: hsl(var(--purple, 280 60% 50%) / 0.5);
|
||||
color: hsl(var(--foreground));
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 2px 8px hsl(var(--purple, 280 60% 50%) / 0.1);
|
||||
}
|
||||
|
||||
.round-item.active {
|
||||
background: hsl(var(--purple, 280 60% 50%));
|
||||
border-color: hsl(var(--purple, 280 60% 50%));
|
||||
color: white;
|
||||
box-shadow: 0 2px 8px hsl(var(--purple, 280 60% 50%) / 0.25);
|
||||
}
|
||||
|
||||
.round-item i {
|
||||
width: 0.875rem;
|
||||
height: 0.875rem;
|
||||
}
|
||||
|
||||
/* Timeline Event Parts */
|
||||
@@ -2350,6 +2531,112 @@
|
||||
color: hsl(var(--primary));
|
||||
}
|
||||
|
||||
/* File Tree List */
|
||||
.file-tree-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
padding: 0.5rem;
|
||||
background: hsl(var(--card));
|
||||
border: 1px solid hsl(var(--border));
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
/* Impact List */
|
||||
.impact-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
padding: 0.5rem;
|
||||
background: hsl(var(--card));
|
||||
border: 1px solid hsl(var(--border));
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
.impact-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.375rem;
|
||||
padding: 0.75rem;
|
||||
background: hsl(var(--muted) / 0.3);
|
||||
border-radius: 0.375rem;
|
||||
border-left: 3px solid hsl(var(--warning));
|
||||
}
|
||||
|
||||
.impact-item.impact-high {
|
||||
border-left-color: hsl(var(--destructive));
|
||||
}
|
||||
|
||||
.impact-item.impact-medium {
|
||||
border-left-color: hsl(var(--warning));
|
||||
}
|
||||
|
||||
.impact-item.impact-low {
|
||||
border-left-color: hsl(var(--success));
|
||||
}
|
||||
|
||||
.impact-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.impact-file {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.85rem;
|
||||
color: hsl(var(--foreground));
|
||||
background: hsl(var(--muted));
|
||||
padding: 0.125rem 0.375rem;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.impact-line {
|
||||
font-size: 0.8rem;
|
||||
color: hsl(var(--muted-foreground));
|
||||
}
|
||||
|
||||
.impact-score {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
padding: 0.125rem 0.5rem;
|
||||
border-radius: 0.25rem;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.impact-score.high {
|
||||
background: hsl(var(--destructive) / 0.15);
|
||||
color: hsl(var(--destructive));
|
||||
}
|
||||
|
||||
.impact-score.medium {
|
||||
background: hsl(var(--warning) / 0.15);
|
||||
color: hsl(var(--warning));
|
||||
}
|
||||
|
||||
.impact-score.low {
|
||||
background: hsl(var(--success) / 0.15);
|
||||
color: hsl(var(--success));
|
||||
}
|
||||
|
||||
.impact-reason {
|
||||
font-size: 0.85rem;
|
||||
color: hsl(var(--muted-foreground));
|
||||
line-height: 1.5;
|
||||
padding-left: 0.25rem;
|
||||
}
|
||||
|
||||
/* Dependencies List */
|
||||
.deps-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
padding: 0.5rem;
|
||||
background: hsl(var(--card));
|
||||
border: 1px solid hsl(var(--border));
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
/* Timeline Connecting Line */
|
||||
.timeline-event::before {
|
||||
content: "";
|
||||
@@ -2366,3 +2653,227 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Round Solutions */
|
||||
.round-solutions {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.round-solutions > strong {
|
||||
display: block;
|
||||
margin-bottom: 0.75rem;
|
||||
font-size: 0.95rem;
|
||||
color: hsl(var(--foreground));
|
||||
}
|
||||
|
||||
.solutions-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
/* Solution Card Styles (extensions to unified .solution-card above) */
|
||||
.solution-number {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
background: hsl(var(--primary));
|
||||
color: hsl(var(--primary-foreground));
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.solution-name {
|
||||
font-weight: 600;
|
||||
font-size: 0.95rem;
|
||||
color: hsl(var(--foreground));
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.solution-meta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.source-clis {
|
||||
display: flex;
|
||||
gap: 0.375rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.cli-badge {
|
||||
display: inline-block;
|
||||
padding: 0.125rem 0.5rem;
|
||||
background: hsl(var(--purple, 280 60% 50%) / 0.15);
|
||||
color: hsl(var(--purple, 280 60% 50%));
|
||||
border: 1px solid hsl(var(--purple, 280 60% 50%) / 0.3);
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.solution-scores {
|
||||
display: flex;
|
||||
gap: 0.375rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.score-badge {
|
||||
display: inline-block;
|
||||
padding: 0.125rem 0.5rem;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.score-badge.feasibility {
|
||||
background: hsl(var(--success) / 0.15);
|
||||
color: hsl(var(--success));
|
||||
border: 1px solid hsl(var(--success) / 0.3);
|
||||
}
|
||||
|
||||
.score-badge.effort-low {
|
||||
background: hsl(var(--success) / 0.15);
|
||||
color: hsl(var(--success));
|
||||
border: 1px solid hsl(var(--success) / 0.3);
|
||||
}
|
||||
|
||||
.score-badge.effort-medium {
|
||||
background: hsl(var(--warning) / 0.15);
|
||||
color: hsl(var(--warning));
|
||||
border: 1px solid hsl(var(--warning) / 0.3);
|
||||
}
|
||||
|
||||
.score-badge.effort-high {
|
||||
background: hsl(var(--destructive) / 0.15);
|
||||
color: hsl(var(--destructive));
|
||||
border: 1px solid hsl(var(--destructive) / 0.3);
|
||||
}
|
||||
|
||||
.score-badge.risk-low {
|
||||
background: hsl(var(--success) / 0.15);
|
||||
color: hsl(var(--success));
|
||||
border: 1px solid hsl(var(--success) / 0.3);
|
||||
}
|
||||
|
||||
.score-badge.risk-medium {
|
||||
background: hsl(var(--warning) / 0.15);
|
||||
color: hsl(var(--warning));
|
||||
border: 1px solid hsl(var(--warning) / 0.3);
|
||||
}
|
||||
|
||||
.score-badge.risk-high {
|
||||
background: hsl(var(--destructive) / 0.15);
|
||||
color: hsl(var(--destructive));
|
||||
border: 1px solid hsl(var(--destructive) / 0.3);
|
||||
}
|
||||
|
||||
.solution-summary {
|
||||
padding: 1rem;
|
||||
font-size: 0.875rem;
|
||||
color: hsl(var(--foreground));
|
||||
line-height: 1.5;
|
||||
border-bottom: 1px solid hsl(var(--border));
|
||||
}
|
||||
|
||||
.solution-approach,
|
||||
.solution-dependencies,
|
||||
.solution-concerns {
|
||||
border-bottom: 1px solid hsl(var(--border));
|
||||
}
|
||||
|
||||
.solution-approach:last-child,
|
||||
.solution-dependencies:last-child,
|
||||
.solution-concerns:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.solution-tasks,
|
||||
.solution-milestones,
|
||||
.internal-deps,
|
||||
.external-deps {
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
|
||||
.solution-tasks > strong,
|
||||
.solution-milestones > strong,
|
||||
.internal-deps > strong,
|
||||
.external-deps > strong {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 0.85rem;
|
||||
color: hsl(var(--foreground));
|
||||
}
|
||||
|
||||
.task-list,
|
||||
.milestone-list,
|
||||
.dep-list,
|
||||
.concern-list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.375rem;
|
||||
}
|
||||
|
||||
.task-item,
|
||||
.milestone-item,
|
||||
.dep-item,
|
||||
.concern-item {
|
||||
padding: 0.375rem 0.5rem;
|
||||
background: hsl(var(--muted) / 0.2);
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.85rem;
|
||||
color: hsl(var(--foreground));
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.task-id {
|
||||
display: inline-block;
|
||||
min-width: 2rem;
|
||||
font-weight: 600;
|
||||
color: hsl(var(--primary));
|
||||
margin-right: 0.5rem;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.task-name {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.task-key-point {
|
||||
display: block;
|
||||
margin-top: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
color: hsl(var(--muted-foreground));
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.execution-flow {
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
|
||||
.execution-flow > strong {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 0.85rem;
|
||||
color: hsl(var(--foreground));
|
||||
}
|
||||
|
||||
.flow-code {
|
||||
display: block;
|
||||
padding: 0.5rem;
|
||||
background: hsl(var(--muted));
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.8rem;
|
||||
font-family: var(--font-mono);
|
||||
color: hsl(var(--foreground));
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
* Real-time streaming output viewer for CLI executions
|
||||
*/
|
||||
|
||||
// ===== Lifecycle Management =====
|
||||
let cliStreamViewerDestroy = null;
|
||||
let streamKeyboardHandler = null;
|
||||
let streamScrollHandler = null; // Track scroll listener
|
||||
let streamStatusTimers = []; // Track status update timers
|
||||
|
||||
// ===== State Management =====
|
||||
let cliStreamExecutions = {}; // { executionId: { tool, mode, output, status, startTime, endTime } }
|
||||
let activeStreamTab = null;
|
||||
@@ -91,7 +97,7 @@ async function syncActiveExecutions() {
|
||||
// ===== Initialization =====
|
||||
function initCliStreamViewer() {
|
||||
// Initialize keyboard shortcuts
|
||||
document.addEventListener('keydown', function(e) {
|
||||
streamKeyboardHandler = function(e) {
|
||||
if (e.key === 'Escape' && isCliStreamViewerOpen) {
|
||||
if (searchFilter) {
|
||||
clearSearch();
|
||||
@@ -108,12 +114,14 @@ function initCliStreamViewer() {
|
||||
searchInput.select();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
document.addEventListener('keydown', streamKeyboardHandler);
|
||||
|
||||
// Initialize scroll detection for auto-scroll
|
||||
const content = document.getElementById('cliStreamContent');
|
||||
if (content) {
|
||||
content.addEventListener('scroll', handleStreamContentScroll);
|
||||
streamScrollHandler = handleStreamContentScroll;
|
||||
content.addEventListener('scroll', streamScrollHandler);
|
||||
}
|
||||
|
||||
// Sync active executions from server (recover state for mid-execution joins)
|
||||
@@ -592,11 +600,12 @@ function renderStreamStatus(executionId) {
|
||||
|
||||
// Update duration periodically for running executions
|
||||
if (exec.status === 'running') {
|
||||
setTimeout(() => {
|
||||
const timerId = setTimeout(() => {
|
||||
if (activeStreamTab === executionId && cliStreamExecutions[executionId]?.status === 'running') {
|
||||
renderStreamStatus(executionId);
|
||||
}
|
||||
}, 1000);
|
||||
streamStatusTimers.push(timerId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -760,6 +769,31 @@ if (document.readyState === 'loading') {
|
||||
initCliStreamViewer();
|
||||
}
|
||||
|
||||
// ===== Lifecycle Functions =====
|
||||
function destroyCliStreamViewer() {
|
||||
// Remove keyboard event listener if exists
|
||||
if (streamKeyboardHandler) {
|
||||
document.removeEventListener('keydown', streamKeyboardHandler);
|
||||
streamKeyboardHandler = null;
|
||||
}
|
||||
|
||||
// Remove scroll event listener if exists
|
||||
if (streamScrollHandler) {
|
||||
const content = document.getElementById('cliStreamContent');
|
||||
if (content) {
|
||||
content.removeEventListener('scroll', streamScrollHandler);
|
||||
}
|
||||
streamScrollHandler = null;
|
||||
}
|
||||
|
||||
// Clear all pending status update timers
|
||||
streamStatusTimers.forEach(timerId => clearTimeout(timerId));
|
||||
streamStatusTimers = [];
|
||||
}
|
||||
|
||||
// Export lifecycle functions
|
||||
window.destroyCliStreamViewer = destroyCliStreamViewer;
|
||||
|
||||
// ===== Global Exposure =====
|
||||
window.toggleCliStreamViewer = toggleCliStreamViewer;
|
||||
window.handleCliStreamStarted = handleCliStreamStarted;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
// Navigation and Routing
|
||||
// Manages navigation events, active state, content title updates, search, and path selector
|
||||
|
||||
// View lifecycle management
|
||||
var currentViewDestroy = null;
|
||||
|
||||
// Path Selector
|
||||
function initPathSelector() {
|
||||
const btn = document.getElementById('pathButton');
|
||||
@@ -54,6 +57,11 @@ function initPathSelector() {
|
||||
|
||||
// Cleanup function for view transitions
|
||||
function cleanupPreviousView() {
|
||||
// Call current view's destroy function if exists
|
||||
if (currentViewDestroy) {
|
||||
currentViewDestroy();
|
||||
currentViewDestroy = null;
|
||||
}
|
||||
// Cleanup graph explorer
|
||||
if (currentView === 'graph-explorer' && typeof window.cleanupGraphExplorer === 'function') {
|
||||
window.cleanupGraphExplorer();
|
||||
@@ -118,9 +126,13 @@ function initNavigation() {
|
||||
} else if (currentView === 'explorer') {
|
||||
renderExplorer();
|
||||
} else if (currentView === 'cli-manager') {
|
||||
renderCliManager();
|
||||
renderClaudeManager();
|
||||
} else if (currentView === 'cli-history') {
|
||||
renderCliHistoryView();
|
||||
// Register destroy function for cli-history view
|
||||
if (typeof window.destroyCliHistoryView === 'function') {
|
||||
currentViewDestroy = window.destroyCliHistoryView;
|
||||
}
|
||||
} else if (currentView === 'hook-manager') {
|
||||
renderHookManager();
|
||||
} else if (currentView === 'memory') {
|
||||
@@ -133,6 +145,10 @@ function initNavigation() {
|
||||
renderRulesManager();
|
||||
} else if (currentView === 'claude-manager') {
|
||||
renderClaudeManager();
|
||||
// Register destroy function for claude-manager view
|
||||
if (typeof window.initClaudeManager === 'function') {
|
||||
window.initClaudeManager();
|
||||
}
|
||||
} else if (currentView === 'graph-explorer') {
|
||||
renderGraphExplorer();
|
||||
} else if (currentView === 'help') {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
// CLAUDE.md Manager View
|
||||
// Three-column layout: File Tree | Viewer/Editor | Metadata & Actions
|
||||
|
||||
// ========== Lifecycle Management ==========
|
||||
var claudeManagerDestroy = null;
|
||||
var createDialogOverlay = null; // Track create dialog overlay for cleanup
|
||||
|
||||
// ========== State Management ==========
|
||||
var claudeFilesData = {
|
||||
user: { main: null },
|
||||
@@ -19,9 +23,15 @@ var fileTreeExpanded = {
|
||||
var searchQuery = '';
|
||||
var freshnessData = {}; // { [filePath]: FreshnessResult }
|
||||
var freshnessSummary = null;
|
||||
var searchKeyboardHandlerAdded = false;
|
||||
|
||||
// ========== Main Render Function ==========
|
||||
async function renderClaudeManager() {
|
||||
// Initialize lifecycle
|
||||
if (typeof initClaudeManager === 'function') {
|
||||
initClaudeManager();
|
||||
}
|
||||
|
||||
var container = document.getElementById('mainContent');
|
||||
if (!container) return;
|
||||
|
||||
@@ -749,9 +759,11 @@ function filterFileTree(query) {
|
||||
renderFileTree();
|
||||
|
||||
// Add keyboard shortcut handler
|
||||
if (query && !window.claudeSearchKeyboardHandlerAdded) {
|
||||
document.addEventListener('keydown', handleSearchKeyboard);
|
||||
window.claudeSearchKeyboardHandlerAdded = true;
|
||||
if (query && !searchKeyboardHandlerAdded) {
|
||||
(function() {
|
||||
document.addEventListener('keydown', handleSearchKeyboard);
|
||||
searchKeyboardHandlerAdded = true;
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -796,6 +808,7 @@ function showCreateFileDialog() {
|
||||
'</div>';
|
||||
|
||||
document.body.insertAdjacentHTML('beforeend', dialog);
|
||||
createDialogOverlay = document.querySelector('.modal-overlay');
|
||||
if (window.lucide) lucide.createIcons();
|
||||
}
|
||||
|
||||
@@ -918,3 +931,31 @@ function updateClaudeBadge() {
|
||||
badge.textContent = total;
|
||||
}
|
||||
}
|
||||
|
||||
// ========== Lifecycle Functions ==========
|
||||
function destroyClaudeManager() {
|
||||
// Remove search keyboard event listener if added
|
||||
if (searchKeyboardHandlerAdded) {
|
||||
document.removeEventListener('keydown', handleSearchKeyboard);
|
||||
searchKeyboardHandlerAdded = false;
|
||||
}
|
||||
|
||||
// Remove create dialog overlay if exists
|
||||
if (createDialogOverlay) {
|
||||
createDialogOverlay.remove();
|
||||
createDialogOverlay = null;
|
||||
}
|
||||
|
||||
// Reset view-specific state
|
||||
selectedFile = null;
|
||||
isEditMode = false;
|
||||
isDirty = false;
|
||||
}
|
||||
|
||||
// Expose init/destroy functions for lifecycle management
|
||||
window.initClaudeManager = function() {
|
||||
claudeManagerDestroy = destroyClaudeManager;
|
||||
};
|
||||
|
||||
// Make destroyClaudeManager accessible globally as well
|
||||
window.destroyClaudeManager = destroyClaudeManager;
|
||||
|
||||
@@ -7,6 +7,9 @@ var isMultiSelectMode = false;
|
||||
|
||||
// ========== Rendering ==========
|
||||
async function renderCliHistoryView() {
|
||||
// Reset view state to prevent stale data persistence
|
||||
resetHistoryViewState();
|
||||
|
||||
var container = document.getElementById('mainContent');
|
||||
if (!container) return;
|
||||
|
||||
@@ -183,6 +186,9 @@ async function renderCliHistoryView() {
|
||||
if (window.lucide) lucide.createIcons();
|
||||
}
|
||||
|
||||
// Export destroy function for lifecycle management
|
||||
window.destroyCliHistoryView = destroyCliHistoryView;
|
||||
|
||||
// ========== Actions ==========
|
||||
async function copyExecutionId(executionId) {
|
||||
try {
|
||||
@@ -218,16 +224,28 @@ async function refreshCliHistoryView() {
|
||||
}
|
||||
|
||||
// ========== Multi-Select Functions ==========
|
||||
var deleteDropdownListenerActive = false;
|
||||
|
||||
function toggleDeleteDropdown(event) {
|
||||
event.stopPropagation();
|
||||
var menu = document.getElementById('deleteDropdownMenu');
|
||||
if (menu) {
|
||||
menu.classList.toggle('show');
|
||||
// Close on outside click
|
||||
if (menu.classList.contains('show')) {
|
||||
setTimeout(function() {
|
||||
document.addEventListener('click', closeDeleteDropdown);
|
||||
}, 0);
|
||||
// Closing: remove listener if active
|
||||
menu.classList.remove('show');
|
||||
if (deleteDropdownListenerActive) {
|
||||
document.removeEventListener('click', closeDeleteDropdown);
|
||||
deleteDropdownListenerActive = false;
|
||||
}
|
||||
} else {
|
||||
// Opening: add listener if not already active
|
||||
menu.classList.add('show');
|
||||
if (!deleteDropdownListenerActive) {
|
||||
setTimeout(function() {
|
||||
document.addEventListener('click', closeDeleteDropdown);
|
||||
deleteDropdownListenerActive = true;
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -235,7 +253,10 @@ function toggleDeleteDropdown(event) {
|
||||
function closeDeleteDropdown() {
|
||||
var menu = document.getElementById('deleteDropdownMenu');
|
||||
if (menu) menu.classList.remove('show');
|
||||
document.removeEventListener('click', closeDeleteDropdown);
|
||||
if (deleteDropdownListenerActive) {
|
||||
document.removeEventListener('click', closeDeleteDropdown);
|
||||
deleteDropdownListenerActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
function enterMultiSelectMode() {
|
||||
@@ -279,6 +300,23 @@ function clearExecutionSelection() {
|
||||
renderCliHistoryView();
|
||||
}
|
||||
|
||||
function resetHistoryViewState() {
|
||||
selectedExecutions.clear();
|
||||
isMultiSelectMode = false;
|
||||
}
|
||||
|
||||
// ========== View Lifecycle ==========
|
||||
function destroyCliHistoryView() {
|
||||
// Clean up dropdown listener if active
|
||||
if (deleteDropdownListenerActive) {
|
||||
document.removeEventListener('click', closeDeleteDropdown);
|
||||
deleteDropdownListenerActive = false;
|
||||
}
|
||||
// Ensure dropdown menu is closed
|
||||
var menu = document.getElementById('deleteDropdownMenu');
|
||||
if (menu) menu.classList.remove('show');
|
||||
}
|
||||
|
||||
// ========== Batch Delete Functions ==========
|
||||
function confirmBatchDelete() {
|
||||
var count = selectedExecutions.size;
|
||||
|
||||
@@ -1117,6 +1117,143 @@ function renderRoundContent(round) {
|
||||
`);
|
||||
}
|
||||
|
||||
// Round solutions
|
||||
if (round.solutions && round.solutions.length > 0) {
|
||||
sections.push(`
|
||||
<div class="round-solutions">
|
||||
<strong>${t('multiCli.solutions') || 'Solutions'} (${round.solutions.length}):</strong>
|
||||
<div class="solutions-list">
|
||||
${round.solutions.map((solution, idx) => `
|
||||
<div class="solution-card">
|
||||
<div class="solution-header">
|
||||
<div class="solution-title">
|
||||
<span class="solution-number">${idx + 1}</span>
|
||||
<span class="solution-name">${escapeHtml(solution.name || `Solution ${idx + 1}`)}</span>
|
||||
</div>
|
||||
<div class="solution-meta">
|
||||
${solution.source_cli?.length ? `
|
||||
<div class="source-clis">
|
||||
${solution.source_cli.map(cli => `<span class="cli-badge">${escapeHtml(cli)}</span>`).join('')}
|
||||
</div>
|
||||
` : ''}
|
||||
<div class="solution-scores">
|
||||
<span class="score-badge feasibility" title="Feasibility">
|
||||
${Math.round((solution.feasibility || 0) * 100)}%
|
||||
</span>
|
||||
<span class="score-badge effort-${solution.effort || 'medium'}" title="Effort">
|
||||
${escapeHtml(solution.effort || 'medium')}
|
||||
</span>
|
||||
<span class="score-badge risk-${solution.risk || 'medium'}" title="Risk">
|
||||
${escapeHtml(solution.risk || 'medium')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
${solution.summary ? `
|
||||
<div class="solution-summary">
|
||||
${escapeHtml(getI18nText(solution.summary))}
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
${solution.implementation_plan?.approach ? `
|
||||
<div class="solution-approach collapsible-section">
|
||||
<div class="collapsible-header">
|
||||
<span class="collapse-icon">►</span>
|
||||
<span class="section-label">${t('multiCli.implementation') || 'Implementation Approach'}</span>
|
||||
</div>
|
||||
<div class="collapsible-content collapsed">
|
||||
<p>${escapeHtml(getI18nText(solution.implementation_plan.approach))}</p>
|
||||
|
||||
${solution.implementation_plan.tasks?.length ? `
|
||||
<div class="solution-tasks">
|
||||
<strong>${t('multiCli.tasks') || 'Tasks'}:</strong>
|
||||
<ul class="task-list">
|
||||
${solution.implementation_plan.tasks.map(task => `
|
||||
<li class="task-item">
|
||||
<span class="task-id">${escapeHtml(task.id || '')}</span>
|
||||
<span class="task-name">${escapeHtml(getI18nText(task.name))}</span>
|
||||
${task.key_point ? `<span class="task-key-point">${escapeHtml(getI18nText(task.key_point))}</span>` : ''}
|
||||
</li>
|
||||
`).join('')}
|
||||
</ul>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
${solution.implementation_plan.execution_flow ? `
|
||||
<div class="execution-flow">
|
||||
<strong>${t('multiCli.executionFlow') || 'Execution Flow'}:</strong>
|
||||
<code class="flow-code">${escapeHtml(solution.implementation_plan.execution_flow)}</code>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
${solution.implementation_plan.milestones?.length ? `
|
||||
<div class="solution-milestones">
|
||||
<strong>${t('multiCli.milestones') || 'Milestones'}:</strong>
|
||||
<ul class="milestone-list">
|
||||
${solution.implementation_plan.milestones.map(milestone => `
|
||||
<li class="milestone-item">${escapeHtml(getI18nText(milestone))}</li>
|
||||
`).join('')}
|
||||
</ul>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
${(solution.dependencies?.internal?.length || solution.dependencies?.external?.length) ? `
|
||||
<div class="solution-dependencies collapsible-section">
|
||||
<div class="collapsible-header">
|
||||
<span class="collapse-icon">►</span>
|
||||
<span class="section-label">${t('multiCli.dependencies') || 'Dependencies'}</span>
|
||||
</div>
|
||||
<div class="collapsible-content collapsed">
|
||||
${solution.dependencies.internal?.length ? `
|
||||
<div class="internal-deps">
|
||||
<strong>${t('multiCli.internalDeps') || 'Internal'}:</strong>
|
||||
<ul class="dep-list">
|
||||
${solution.dependencies.internal.map(dep => `
|
||||
<li class="dep-item">${escapeHtml(getI18nText(dep))}</li>
|
||||
`).join('')}
|
||||
</ul>
|
||||
</div>
|
||||
` : ''}
|
||||
${solution.dependencies.external?.length ? `
|
||||
<div class="external-deps">
|
||||
<strong>${t('multiCli.externalDeps') || 'External'}:</strong>
|
||||
<ul class="dep-list">
|
||||
${solution.dependencies.external.map(dep => `
|
||||
<li class="dep-item">${escapeHtml(getI18nText(dep))}</li>
|
||||
`).join('')}
|
||||
</ul>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
${solution.technical_concerns?.length ? `
|
||||
<div class="solution-concerns collapsible-section">
|
||||
<div class="collapsible-header">
|
||||
<span class="collapse-icon">►</span>
|
||||
<span class="section-label">${t('multiCli.technicalConcerns') || 'Technical Concerns'}</span>
|
||||
</div>
|
||||
<div class="collapsible-content collapsed">
|
||||
<ul class="concern-list">
|
||||
${solution.technical_concerns.map(concern => `
|
||||
<li class="concern-item">${escapeHtml(getI18nText(concern))}</li>
|
||||
`).join('')}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
`).join('')}
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
|
||||
return sections.join('');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user