Put a copy button next to every value, not only in the full view

The full view opens only when a preview leaves something out, so a short
output or input had no way to be copied. Every value in the Output,
Intermediate and Rounds tabs now has its own copy button, beside the
view button when there is one. The full view's button just says Copy:
it copies any value, JSON or not.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Lucio Lelii 2026-09-25 14:35:08 +02:00
parent 90a04dc480
commit 7477027319
2 changed files with 69 additions and 31 deletions

View File

@ -1005,3 +1005,11 @@
height: 16px;
font-size: 16px;
}
/* Copy is there for every value; view, only when the preview leaves something out. */
.execution-value-actions {
display: inline-flex;
flex: 0 0 auto;
align-items: center;
gap: 4px;
}

View File

@ -443,15 +443,25 @@
}
</div>
</div>
@if (input.isLong) {
<button
type="button"
class="execution-output-view-btn"
aria-label="View full intermediate input"
(click)="openIntermediateInputPreview(input, $event)">
<i class="bi bi-eye"></i>
</button>
}
<div class="execution-value-actions">
<button
type="button"
class="execution-output-view-btn"
[matTooltip]="copiedValueKey() === input.key ? 'Copied' : 'Copy'"
[attr.aria-label]="'Copy ' + input.inputName"
(click)="copyValue(input.key, input.json, input.value, $event)">
<i class="bi" [class.bi-check2]="copiedValueKey() === input.key" [class.bi-copy]="copiedValueKey() !== input.key"></i>
</button>
@if (input.isLong) {
<button
type="button"
class="execution-output-view-btn"
aria-label="View full intermediate input"
(click)="openIntermediateInputPreview(input, $event)">
<i class="bi bi-eye"></i>
</button>
}
</div>
</div>
@if (input.json) {
<app-json-viewer class="execution-json-preview" [value]="input.json" [expandDepth]="1" [maxEntries]="jsonPreviewEntries" />
@ -499,15 +509,25 @@
<div class="execution-round-input">
<div class="execution-round-input-head">
<span class="execution-intermediate-item-name">{{ input.inputName }}{{ input.itemLabel ? ' · ' + input.itemLabel : '' }}</span>
@if (input.isLong) {
<button
type="button"
class="execution-output-view-btn"
[attr.aria-label]="'View all of ' + input.inputName + ' in round ' + round.iteration"
(click)="openIntermediateInputPreview(input, $event)">
<i class="bi bi-eye"></i>
</button>
}
<div class="execution-value-actions">
<button
type="button"
class="execution-output-view-btn"
[matTooltip]="copiedValueKey() === input.key ? 'Copied' : 'Copy'"
[attr.aria-label]="'Copy ' + input.inputName"
(click)="copyValue(input.key, input.json, input.value, $event)">
<i class="bi" [class.bi-check2]="copiedValueKey() === input.key" [class.bi-copy]="copiedValueKey() !== input.key"></i>
</button>
@if (input.isLong) {
<button
type="button"
class="execution-output-view-btn"
[attr.aria-label]="'View all of ' + input.inputName + ' in round ' + round.iteration"
(click)="openIntermediateInputPreview(input, $event)">
<i class="bi bi-eye"></i>
</button>
}
</div>
</div>
@if (input.json) {
<app-json-viewer class="execution-json-preview" [value]="input.json" [expandDepth]="1" [maxEntries]="jsonPreviewEntries" />
@ -622,15 +642,25 @@
<div class="text-[11px] text-slate-500">{{ output.itemLabel }}</div>
}
</div>
@if (output.isLong) {
<button
type="button"
class="execution-output-view-btn"
aria-label="View full output"
(click)="openOutputPreview(output, $event)">
<i class="bi bi-eye"></i>
</button>
}
<div class="execution-value-actions">
<button
type="button"
class="execution-output-view-btn"
[matTooltip]="copiedValueKey() === output.key ? 'Copied' : 'Copy'"
[attr.aria-label]="'Copy ' + output.outputName"
(click)="copyValue(output.key, output.json, output.value, $event)">
<i class="bi" [class.bi-check2]="copiedValueKey() === output.key" [class.bi-copy]="copiedValueKey() !== output.key"></i>
</button>
@if (output.isLong) {
<button
type="button"
class="execution-output-view-btn"
aria-label="View full output"
(click)="openOutputPreview(output, $event)">
<i class="bi bi-eye"></i>
</button>
}
</div>
</div>
@if (output.json) {
<app-json-viewer class="execution-json-preview" [value]="output.json" [expandDepth]="1" [maxEntries]="jsonPreviewEntries" />
@ -672,10 +702,10 @@
<button
type="button"
mat-stroked-button
[attr.aria-label]="outputModal.json ? 'Copy the JSON' : 'Copy the text'"
aria-label="Copy the value"
(click)="copyValue(outputModal.key, outputModal.json, outputModal.value, $event)">
<mat-icon [fontIcon]="copiedValueKey() === outputModal.key ? 'check' : 'content_copy'"></mat-icon>
<span>{{ copiedValueKey() === outputModal.key ? 'Copied' : (outputModal.json ? 'Copy JSON' : 'Copy') }}</span>
<span>{{ copiedValueKey() === outputModal.key ? 'Copied' : 'Copy' }}</span>
</button>
<button type="button" mat-stroked-button (click)="closeOutputPreview($event)">Close</button>
</div>
@ -704,10 +734,10 @@
<button
type="button"
mat-stroked-button
[attr.aria-label]="inputModal.json ? 'Copy the JSON' : 'Copy the text'"
aria-label="Copy the value"
(click)="copyValue(inputModal.key, inputModal.json, inputModal.value, $event)">
<mat-icon [fontIcon]="copiedValueKey() === inputModal.key ? 'check' : 'content_copy'"></mat-icon>
<span>{{ copiedValueKey() === inputModal.key ? 'Copied' : (inputModal.json ? 'Copy JSON' : 'Copy') }}</span>
<span>{{ copiedValueKey() === inputModal.key ? 'Copied' : 'Copy' }}</span>
</button>
<button type="button" mat-stroked-button (click)="closeIntermediateInputPreview($event)">Close</button>
</div>