103 lines
4.1 KiB
HTML
103 lines
4.1 KiB
HTML
<!--
|
|
SPDX-FileCopyrightText: 2025-2026 Lucio Lelii <lucio.lelii@isti.cnr.it> - ISTI-CNR
|
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
|
Attribution term under AGPL-3.0 section 7(b): see LICENSE-ADDENDUM.
|
|
-->
|
|
|
|
<div class="tasks-executor-shell flex flex-col flex-1 h-full">
|
|
<div class="flex flex-row flex-1 overflow-hidden gap-2">
|
|
<div class="tasks-executor-rail w-[360px] shrink-0 flex flex-col gap-2 overflow-hidden">
|
|
<app-tasks-executions-list
|
|
class="tasks-executor-rail-list"
|
|
[groups]="groups()"
|
|
[selectedExecutionId]="selectedExecutionId()"
|
|
(executionSelected)="selectExecution($event)"
|
|
(executionDeleteRequested)="removeExecution($event)"
|
|
(executionRerunRequested)="rerunExecution($event)"
|
|
(compareRequested)="openComparison($event)">
|
|
</app-tasks-executions-list>
|
|
|
|
@if (selectedExecution(); as run) {
|
|
@if (executionTreeAvailable()) {
|
|
<!-- Only rendered for a run that has a subtree, so nothing inside needs to handle its absence. -->
|
|
<section class="tasks-executor-tree-panel"
|
|
[class.tasks-executor-tree-panel-collapsed]="!executionTreeOpen()"
|
|
[class.tasks-executor-tree-panel-floating]="treeFloating()">
|
|
<button
|
|
type="button"
|
|
class="tasks-executor-tree-toggle"
|
|
[attr.aria-expanded]="executionTreeOpen()"
|
|
(click)="toggleExecutionTree()">
|
|
<span>Execution tree</span>
|
|
<span class="tasks-executor-tree-toggle-icon" [class.tasks-executor-tree-toggle-icon-open]="executionTreeOpen()">⌃</span>
|
|
</button>
|
|
|
|
@if (executionTreeOpen()) {
|
|
<app-execution-tree
|
|
class="tasks-executor-rail-tree"
|
|
[rootExecution]="run"
|
|
[selectedExecutionId]="displayedExecution()?.id ?? null"
|
|
(executionSelected)="selectTreeExecution($event)">
|
|
</app-execution-tree>
|
|
}
|
|
</section>
|
|
}
|
|
}
|
|
</div>
|
|
|
|
<mat-card class="tasks-executor-viewer flex w-full flex-col overflow-hidden !rounded-md !bg-gray-100">
|
|
@if (showExecutionCreationLoader()) {
|
|
<div class="tasks-executor-loader">
|
|
<div class="tasks-executor-loader-card">
|
|
<span class="tasks-executor-spinner" aria-hidden="true"></span>
|
|
<div class="tasks-executor-loader-title">Creating execution...</div>
|
|
<div class="tasks-executor-loader-text">The task view is ready. Waiting for the new execution to appear.</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
@if (interactiveSubflowTargets().length > 1) {
|
|
<div class="interactive-subflow-switcher">
|
|
<span>Interactive containers waiting:</span>
|
|
@for (target of interactiveSubflowTargets(); track target.childExecutionId) {
|
|
<button
|
|
type="button"
|
|
[class.interactive-subflow-switcher-active]="target.childExecutionId === selectedChildExecutionId()"
|
|
(click)="selectInteractiveSubflow(target.childExecutionId)">
|
|
{{ target.containerName }}
|
|
@if (target.iterationIndex !== null) {
|
|
· iteration {{ target.iterationIndex }}
|
|
}
|
|
</button>
|
|
}
|
|
</div>
|
|
}
|
|
@if (childExecutionLoading()) {
|
|
<div class="tasks-executor-loader">
|
|
<div class="tasks-executor-loader-card">
|
|
<span class="tasks-executor-spinner" aria-hidden="true"></span>
|
|
<div class="tasks-executor-loader-title">Opening interactive subflow…</div>
|
|
<div class="tasks-executor-loader-text">Loading the active child execution.</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
@if (childExecutionError(); as childError) {
|
|
<div class="interactive-subflow-error">{{ childError }}</div>
|
|
}
|
|
@if (comparing()) {
|
|
<app-execution-compare-view
|
|
[left]="compareLeft()"
|
|
[right]="compareRight()"
|
|
(closed)="closeComparison()">
|
|
</app-execution-compare-view>
|
|
} @else {
|
|
<app-task-execution-viewer
|
|
[execution]="displayedExecution()"
|
|
[parentExecution]="displayedParentExecution()"
|
|
[parentContainerStep]="displayedParentContainerStep()"
|
|
[(isFullscreen)]="viewerFullscreen">
|
|
</app-task-execution-viewer>
|
|
}
|
|
</mat-card>
|
|
</div>
|
|
</div>
|