humainflow-web/src/app/layouts/tasks-executor/tasks-executor.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>