Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions apps/gust_web/assets/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,55 @@
.run-status__filter-form {
@apply flex h-8 shrink-0 items-center [&_.fieldset]:mb-0 [&_.fieldset]:h-8;
}

.task-status-progress {
@apply h-1.5 w-full overflow-hidden;
}

.task-status-progress__bar {
@apply h-full w-full;
}

.status-running,
.task-grid-cell--running {
background-image: repeating-linear-gradient(
135deg,
var(--color-sky-600) 0,
var(--color-sky-600) 0.75rem,
var(--color-sky-300) 0.75rem,
var(--color-sky-300) 1.5rem
);
background-size: 2.125rem 2.125rem;
animation: task-running-stripes 0.8s linear infinite;
}

.status-retrying,
.task-grid-cell--retrying {
background-image: repeating-linear-gradient(
135deg,
var(--color-amber-600) 0,
var(--color-amber-600) 0.75rem,
var(--color-amber-300) 0.75rem,
var(--color-amber-300) 1.5rem
);
background-size: 2.125rem 2.125rem;
animation: task-running-stripes 0.8s linear infinite;
}
}

@keyframes task-running-stripes {
to {
background-position: 2.125rem 0;
}
}

@media (prefers-reduced-motion: reduce) {
.status-running,
.status-retrying,
.task-grid-cell--running,
.task-grid-cell--retrying {
animation: none;
}
}

@layer components {
Expand Down
19 changes: 7 additions & 12 deletions apps/gust_web/lib/gust_web/components/dag_run_components.ex
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,18 @@ defmodule GustWeb.DagRunComponents do

attr :id, :string, required: true
attr :selected, :boolean, default: false
attr :status, :atom
attr :status, :atom, default: nil

def task_cell(assigns) do
assigns =
assign_new(assigns, :classes, fn ->
base_classes =
if assigns[:status], do: ["status-#{assigns[:status]}", "active"], else: ["status-none"]

classes = base_classes ++ if assigns[:selected], do: ["selected"], else: []

Enum.join(classes, " ")
end)

~H"""
<div
id={"#{@id}"}
class={"task-grid-cell border rounded #{@classes}"}
class={[
"task-grid-cell border rounded",
if(@status, do: "status-#{@status} active", else: "status-none"),
@selected && "selected",
@status && "task-grid-cell--#{@status}"
]}
Comment thread
Copilot marked this conversation as resolved.
>
</div>
"""
Expand Down
16 changes: 15 additions & 1 deletion apps/gust_web/lib/gust_web/live/dag_live/dashboard.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,17 @@
</div>
</section>

<div
:if={@item_status}
id="task-status-progress"
class={["task-status-progress", "status-#{@item_status}"]}
role="progressbar"
aria-label={"Status: #{@item_status}"}
aria-valuetext={to_string(@item_status)}
>
<div class="task-status-progress__bar"></div>
</div>
Comment thread
marciok marked this conversation as resolved.

<section class="dag-card__meta">
<div :if={@item_inserted_at} class="dag-card__meta-item">
<div class="dag-card__meta-label">Started</div>
Expand Down Expand Up @@ -195,7 +206,10 @@
</div>
</section>

<section :if={@item_error && map_size(@item_error) > 0} class="dag-card__body">
<section
:if={@item_error && map_size(@item_error) > 0 && @item_status != :running}
class="dag-card__body"
>
<div
id="task-error"
role="alert"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ defmodule GustWeb.DagRunComponentsTest do
assert [_cell] =
LazyHTML.query(
document,
"#load_data-at-run-42.task-grid-cell.status-running.active.selected"
"#load_data-at-run-42.task-grid-cell.status-running.active.selected.task-grid-cell--running"
)
|> LazyHTML.to_tree()
end
Expand Down
75 changes: 75 additions & 0 deletions apps/gust_web/test/gust_web/live/dag_live_dashboard_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,60 @@ defmodule GustWeb.DagLiveDashboardTest do
refute has_element?(dashboard_live, "#task-error-stacktrace")
end

test "does not display a persisted task error while the task is running", %{
conn: conn,
dag: dag,
run: run,
task: task
} do
error = %{
type: "RuntimeError",
value: "running-task",
message: "stale error"
}

{:ok, task} = Flows.update_task_error(task, error)
{:ok, _task} = Flows.update_task_status(task, :running)

{:ok, dashboard_live, _html} =
live(conn, ~g"/dags/#{dag.name}/dashboard?run_id=#{run.id}&task_name=#{task.name}")

refute has_element?(dashboard_live, "#task-error")

assert has_element?(
dashboard_live,
"#task-status-progress[role='progressbar']"
)

assert has_element?(dashboard_live, "#task-status-progress .task-status-progress__bar")
end

test "hides a displayed task error when the task starts running", %{
conn: conn,
dag: dag,
run: run,
task: task
} do
error = %{
type: "RuntimeError",
value: "starting-task",
message: "previous attempt failed"
}

{:ok, task} = Flows.update_task_error(task, error)

{:ok, dashboard_live, _html} =
live(conn, ~g"/dags/#{dag.name}/dashboard?run_id=#{run.id}&task_name=#{task.name}")

assert has_element?(dashboard_live, "#task-error")

{:ok, _task} = Flows.update_task_status(task, :running)
Gust.PubSub.broadcast_run_status(run.id, :running, task.id)

refute has_element?(dashboard_live, "#task-error")
assert has_element?(dashboard_live, "#task-status-progress")
end

test "display task error stacktrace", %{
conn: conn,
dag: dag,
Expand Down Expand Up @@ -464,13 +518,24 @@ defmodule GustWeb.DagLiveDashboardTest do
live(conn, ~g"/dags/#{dag.name}/dashboard?run_id=#{run.id}")

assert mermaid_source(dashboard_live) =~ "class #{task.name} status-running"

assert has_element?(
dashboard_live,
"##{task.name}-at-run-#{run.id}.task-grid-cell--running"
)

refute mermaid_source(dashboard_live) =~ "selected-task"

{:ok, _task} = Flows.update_task_status(task, :succeeded)
Gust.PubSub.broadcast_run_status(run.id, :running, task.id)

assert mermaid_source(dashboard_live) =~ "class #{task.name} status-succeeded"
refute mermaid_source(dashboard_live) =~ "class #{task.name} status-running"

refute has_element?(
dashboard_live,
"##{task.name}-at-run-#{run.id}.task-grid-cell--running"
)
end

test "marks the selected task on the mermaid graph", %{
Expand Down Expand Up @@ -522,11 +587,21 @@ defmodule GustWeb.DagLiveDashboardTest do
{:ok, _task} = Gust.Flows.update_task_status(task, :running)
{:ok, dashboard_live, _html} = live(conn, ~g"/dags/#{dag.name}/dashboard")

assert has_element?(
dashboard_live,
"#run-status-cell-#{run.id}.task-grid-cell--running"
)

Flows.update_run_status(run, :succeeded)

Gust.PubSub.broadcast_run_status(run.id, :succeeded)

assert has_element?(dashboard_live, "#run-status-cell-#{run.id}.status-succeeded")

refute has_element?(
dashboard_live,
"#run-status-cell-#{run.id}.task-grid-cell--running"
)
end

test "selected run details are reloaded when its status changes", %{
Expand Down
15 changes: 10 additions & 5 deletions apps/gust_web/test/gust_web/live/run_live_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -214,19 +214,24 @@ defmodule GustWeb.RunLiveTest do
refute has_element?(index_live, "#runs-#{newer_match.id}")
end

test "list runs paged", %{conn: conn, dag: dag, run: _first_run} do
test "list runs paged", %{conn: conn, dag: dag, run: first_run} do
page_size = 3
now = DateTime.utc_now() |> DateTime.truncate(:second)

run_fixture(%{dag_id: dag.id, inserted_at: DateTime.add(now, 60)})

run_fixture(%{dag_id: dag.id})
prev_page_run = run_fixture(%{dag_id: dag.id})
prev_page_run =
run_fixture(%{dag_id: dag.id, inserted_at: DateTime.add(now, 120)})

current_page_run = run_fixture(%{dag_id: dag.id})
current_page_run =
run_fixture(%{dag_id: dag.id, inserted_at: DateTime.add(now, 180)})

{:ok, index_live, _html} =
live(conn, ~g"/dags/#{dag.name}/runs?page_size=#{page_size}&page=2")

assert index_live |> has_element?("#runs-#{current_page_run.id}")
assert index_live |> has_element?("#runs-#{first_run.id}")
refute index_live |> has_element?("#runs-#{prev_page_run.id}")
refute index_live |> has_element?("#runs-#{current_page_run.id}")

assert index_live |> has_element?("#runs-table-container + #runs-pagination")
assert index_live |> has_element?("#run-page-2.btn-active[aria-current='page']")
Expand Down
Loading