Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ type ConfirmBookingProps = ViewProps<typeof confirmBookingSchema>;
}
`,
styles: [`
.cb { border: 1px solid var(--tplane-chat-separator, #e5e7eb); border-radius: 12px; padding: 16px; max-width: 360px; }
.cb { border: 1px solid var(--ds-border, #e5e7eb); border-radius: 12px; padding: 16px; max-width: 360px; background: var(--ds-surface); color: var(--ds-text-primary); }
.cb__summary { margin: 0 0 12px; }
.cb--resolved .cb__summary { margin: 0; opacity: 0.85; }
.cb--resolved .cb__summary { margin: 0; color: var(--ds-text-secondary); }
.cb__actions { display: flex; gap: 8px; }
.cb__btn { padding: 6px 14px; border-radius: 8px; border: 1px solid var(--tplane-chat-separator, #e5e7eb); background: transparent; color: inherit; cursor: pointer; }
.cb__btn--primary { background: var(--tplane-chat-accent, #2563eb); color: #fff; border-color: transparent; }
.cb__btn { padding: 6px 14px; border-radius: 8px; border: 1px solid var(--ds-border, #e5e7eb); background: var(--ds-surface-dim); color: var(--ds-text-secondary); cursor: pointer; }
.cb__btn--primary { background: var(--ds-accent, #64C3FD); color: #08243a; border-color: transparent; font-weight: 600; }
`],
})
export class ConfirmBookingComponent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ type WeatherCardProps = ViewProps<typeof weatherCardSchema>;
</div>
`,
styles: [`
.wc { border: 1px solid var(--tplane-chat-separator, #e5e7eb); border-radius: 12px; padding: 16px; max-width: 320px; }
.wc { border: 1px solid var(--ds-border, #e5e7eb); border-radius: 12px; padding: 16px; max-width: 320px; background: var(--ds-surface); color: var(--ds-text-primary); }
.wc__head { display: flex; align-items: center; justify-content: space-between; }
.wc__loc { font-weight: 600; }
.wc__badge { font-size: 12px; opacity: 0.7; }
.wc__badge { font-size: 12px; color: var(--ds-text-muted); }
.wc__temp { font-size: 32px; font-weight: 700; margin-top: 8px; }
.wc__cond { opacity: 0.8; }
.wc__cond { color: var(--ds-text-secondary); }
.wc__meta { display: flex; gap: 24px; margin: 12px 0 0; }
.wc__meta dt { font-size: 11px; text-transform: uppercase; opacity: 0.6; }
.wc__meta dt { font-size: 11px; text-transform: uppercase; color: var(--ds-text-muted); }
.wc__meta dd { margin: 0; font-weight: 600; }
`],
})
Expand Down
1 change: 1 addition & 0 deletions cockpit/langgraph/client-tools/angular/tsconfig.app.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
},
"files": ["src/main.ts"],
"include": ["src/**/*.ts"],
"exclude": ["src/**/*.spec.ts", "src/**/*.test.ts"],
"references": [
{
"path": "../../../../libs/cockpit-telemetry"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,53 +37,149 @@ const STEP_LABELS: Record<string, string> = {
selector: 'app-durable-execution',
standalone: true,
imports: [ChatComponent, ExampleChatLayoutComponent],
styles: `
:host {
--st-done: #2ea567;
--st-active: #e0a850;
--st-error: #e0645a;
}
.panel {
padding: 1rem;
Comment on lines +41 to +47

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--st-error is defined here (and in step-pipeline.component.ts) but is never consumed — PipelineStep.status is 'pending' | 'active' | 'complete' with no error state, and neither template has an error branch. The variable is harmless dead code, but it's misleading (it implies an error state that doesn't exist in the durable-execution graph). Safe to remove from both files unless an error status is planned.

background: var(--ds-surface, #1c1c1c);
color: var(--ds-text-primary, #f5f5f5);
height: 100%;
}
.cap {
margin-bottom: 1.5rem;
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--ds-text-muted, #a0a0a0);
}
.steps {
display: flex;
flex-direction: column;
}
.step {
display: flex;
align-items: flex-start;
gap: 0.75rem;
}
.step__col {
display: flex;
flex-direction: column;
align-items: center;
}
.circle {
width: 28px;
height: 28px;
border-radius: 999px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.circle--complete {
background: var(--st-done);
}
.circle--complete svg {
width: 16px;
height: 16px;
color: #fff;
}
.circle--active {
border: 2px solid var(--st-active);
animation: dx-spin 1.2s linear infinite;
}
.circle--pending {
border: 2px solid var(--ds-border, #2d2d2d);
}
.dot {
width: 8px;
height: 8px;
border-radius: 999px;
}
.dot--active {
background: var(--st-active);
}
.dot--pending {
background: var(--ds-text-muted, #a0a0a0);
}
@keyframes dx-spin {
to {
transform: rotate(360deg);
}
}
.line {
width: 2px;
height: 2rem;
}
.line--done {
background: var(--st-done);
}
.line--pending {
background: var(--ds-border, #2d2d2d);
}
.label {
font-size: 13px;
padding-top: 4px;
}
.label--active {
font-weight: 600;
color: var(--st-active);
}
.label--complete {
color: var(--st-done);
}
.label--pending {
color: var(--ds-text-muted, #a0a0a0);
}
`,
template: `
<example-chat-layout sidebarWidth="w-64">
<example-chat-layout sidebarWidth="16rem">
<chat main [agent]="agent" [views]="ui" [store]="uiStore" class="flex-1 min-w-0" />
<div sidebar class="p-4"
style="background: var(--tplane-chat-bg); color: var(--tplane-chat-text);">
<h3 class="text-xs font-semibold uppercase tracking-wide mb-6"
style="color: var(--tplane-chat-text-muted);">Pipeline</h3>
<div sidebar class="panel">
<h3 class="cap">Pipeline</h3>

<div class="space-y-0">
<div class="steps">
@for (step of steps(); track step.id; let last = $last) {
<div class="flex items-start gap-3">
<div class="step">
<!-- Step indicator column -->
<div class="flex flex-col items-center">
<div class="step__col">
<!-- Circle / icon -->
@switch (step.status) {
@case ('complete') {
<div class="w-7 h-7 rounded-full bg-green-600 flex items-center justify-center">
<svg class="w-4 h-4 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="3">
<div class="circle circle--complete">
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="3">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>
</div>
}
@case ('active') {
<div class="w-7 h-7 rounded-full border-2 border-amber-500 flex items-center justify-center animate-spin"
style="animation-duration: 1.2s;">
<div class="w-2 h-2 rounded-full bg-amber-500"></div>
<div class="circle circle--active">
<div class="dot dot--active"></div>
</div>
}
@default {
<div class="w-7 h-7 rounded-full border-2 flex items-center justify-center"
style="border-color: var(--tplane-chat-text-muted);">
<div class="w-2 h-2 rounded-full" style="background: var(--tplane-chat-text-muted);"></div>
<div class="circle circle--pending">
<div class="dot dot--pending"></div>
</div>
}
}
<!-- Connecting line -->
@if (!last) {
<div class="w-0.5 h-8"
[style.background]="step.status === 'complete' ? '#16a34a' : 'var(--tplane-chat-text-muted)'">
</div>
<div class="line" [class.line--done]="step.status === 'complete'" [class.line--pending]="step.status !== 'complete'"></div>
}
</div>

<!-- Label -->
<span class="text-sm pt-1"
[class]="step.status === 'active' ? 'font-semibold text-amber-400' : step.status === 'complete' ? 'text-green-400' : ''"
[style.color]="step.status === 'pending' ? 'var(--tplane-chat-text-muted)' : ''">
<span
class="label"
[class.label--active]="step.status === 'active'"
[class.label--complete]="step.status === 'complete'"
[class.label--pending]="step.status === 'pending'"
>
{{ step.label }}
</span>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,54 +8,139 @@ interface PipelineStep {
@Component({
selector: 'step-pipeline',
standalone: true,
styles: `
:host {
--st-done: #2ea567;
--st-active: #e0a850;
--st-error: #e0645a;
}
.pipeline {
border: 1px solid var(--ds-border, #2d2d2d);
border-radius: var(--ds-radius-xl, 18px);
padding: 1rem;
margin: 0.5rem 0;
background: var(--ds-surface, #1c1c1c);
overflow-x: auto;
}
.row {
display: flex;
align-items: center;
gap: 0;
min-width: max-content;
}
.node {
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
}
.circle {
width: 32px;
height: 32px;
border-radius: 999px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.circle--complete {
background: var(--st-done);
}
.circle--complete svg {
width: 16px;
height: 16px;
color: #fff;
}
.circle--active {
border: 2px solid var(--st-active);
animation: sp-spin 1.2s linear infinite;
}
.circle--pending {
border: 2px solid var(--ds-border, #2d2d2d);
}
.dot {
width: 8px;
height: 8px;
border-radius: 999px;
}
.dot--active {
background: var(--st-active);
}
.dot--pending {
background: var(--ds-text-muted, #a0a0a0);
}
@keyframes sp-spin {
to {
transform: rotate(360deg);
}
}
.label {
font-size: 12px;
white-space: nowrap;
}
.label--active {
font-weight: 600;
color: var(--st-active);
}
.label--complete {
color: var(--st-done);
}
.label--pending {
color: var(--ds-text-muted, #a0a0a0);
}
.line {
width: 2.5rem;
height: 2px;
margin: 0 4px;
margin-top: -20px;
}
.line--done {
background: var(--st-done);
}
.line--pending {
background: var(--ds-border, #2d2d2d);
}
`,
template: `
<div class="border rounded-xl p-4 my-2 overflow-x-auto" style="border-color: var(--tplane-chat-separator); background: var(--tplane-chat-surface-alt);">
<div class="flex items-center gap-0 min-w-max">
<div class="pipeline">
<div class="row">
@for (step of steps(); track step.label; let i = $index; let last = $last) {
<!-- Step node -->
<div class="flex flex-col items-center gap-1.5">
<div class="node">
<!-- Status circle -->
@switch (step.status) {
@case ('complete') {
<div class="w-8 h-8 rounded-full flex items-center justify-center"
style="background: var(--tplane-chat-success, #16a34a);">
<svg class="w-4 h-4 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="3">
<div class="circle circle--complete">
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="3">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>
</div>
}
@case ('active') {
<div class="w-8 h-8 rounded-full border-2 flex items-center justify-center animate-spin"
style="border-color: var(--tplane-chat-warning-text, #f59e0b); animation-duration: 1.2s;">
<div class="w-2 h-2 rounded-full" style="background: var(--tplane-chat-warning-text, #f59e0b);"></div>
<div class="circle circle--active">
<div class="dot dot--active"></div>
</div>
}
@default {
<div class="w-8 h-8 rounded-full border-2 flex items-center justify-center"
style="border-color: var(--tplane-chat-text-muted, #555);">
<div class="w-2 h-2 rounded-full" style="background: var(--tplane-chat-text-muted, #555);"></div>
<div class="circle circle--pending">
<div class="dot dot--pending"></div>
</div>
}
}
<!-- Label -->
<span class="text-xs whitespace-nowrap"
[style.color]="step.status === 'active'
? 'var(--tplane-chat-warning-text, #f59e0b)'
: step.status === 'complete'
? 'var(--tplane-chat-success, #16a34a)'
: 'var(--tplane-chat-text-muted, #777)'"
[class.font-semibold]="step.status === 'active'">
<span
class="label"
[class.label--active]="step.status === 'active'"
[class.label--complete]="step.status === 'complete'"
[class.label--pending]="step.status === 'pending'"
>
{{ step.label }}
</span>
</div>

<!-- Connecting line -->
@if (!last) {
<div class="w-10 h-0.5 -mt-5 mx-1"
[style.background]="step.status === 'complete'
? 'var(--tplane-chat-success, #16a34a)'
: 'var(--tplane-chat-text-muted, #555)'">
</div>
<div class="line" [class.line--done]="step.status === 'complete'" [class.line--pending]="step.status !== 'complete'"></div>
}
}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
},
"files": ["src/main.ts"],
"include": ["src/**/*.ts"],
"exclude": ["src/**/*.spec.ts", "src/**/*.test.ts"],
"references": [
{
"path": "../../../../libs/cockpit-telemetry"
Expand Down
Loading
Loading