Class: Clowk::Phlex::Charts::Card

Inherits:
Clowk::Phlex::Component show all
Defined in:
lib/clowk/phlex/charts/card.rb

Overview

Components::Metrics::ChartCard — header (label + current value + min/avg/max strip + maximize button) + a Components::Metrics::Chart underneath. 2x2 grid layout on /metrics renders four of these per resource and per HTTP scope.

Visual:

┌───────────────────────────────────────────────────────────┐
│ CPU  25%        min 21.9  avg 30.8  max 39.8  ⛶           │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ chart …                                               │ │
│ └───────────────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────┘

Maximize (⛶) opens a SHARED modal (see Components::Metrics::ChartModal) rendered once at the bottom of Views::Metrics::Index. The button is just an anchor with data-turbo-stream="true"; clicking it sends an Accept: text/vnd.turbo-stream.html GET to /metrics/chart, whose response targets the modal's slots (#chart-modal-title + #chart-modal-body) and invokes the custom chart_modal_open Turbo Stream action. No per-card overlay, no Stimulus controller for open/close — server drives the whole lifecycle via turbo_stream actions.

Instance Method Summary collapse

Constructor Details

#initialize(label:, color:, unit:, range_ms:, points: [], current: nil, expand_url: nil, metric: nil, section: nil, default_visible: true, capacity_label: nil, capacity_pct: nil, chart_type: "area", percent: true, series: nil, resizable: true, gauge_bars: nil) ⇒ Card

current — the unaggregated "right now" value from MetricsPageData (server-side latest field). When nil, falls back to series.last's bucket-aggregated value. The fallback only kicks in for cold-boot when the API hasn't shipped a latest yet; otherwise the headline tracks the literal latest sample and stays stable across range pills.

expand_url: STRING → enables the maximize button. Caller (Views::Metrics::Index#render_chart_cards) builds the URL via metrics_chart_path with metric/source/scale baked in. Pass nil (or omit) to render a maximize-less card — used historically by call sites that don't have access to the full single-chart context; safe default. metric: STRING — the metric key (e.g. "cpu_percent"). When given, the root div gains data-metrics-display-target="card" + data-metric-key="" so MetricsDisplayController can hide/ show this card based on the operator's display settings. Pass nil (or omit) to opt out of the display-filter system (e.g. standalone chart cards outside the main grid).

section: STRING — "resource" or "http". When "http", a small inline [http] badge renders next to the metric label, giving operators a visual cue that the card is HTTP-derived. (The divider-style HTTP section header was removed in favor of this inline tag — fewer hard breaks in the grid, same signal.)

default_visible: BOOLEAN — when false, the card emits data-default-visible="false". The metrics-display controller reads this on first connect for a kind that has no saved display settings yet and hides the card by default. Operator can un-hide it via the Settings drawer's Latency / Errors picker groups. capacity_label: STRING — "39 GB" / "512 MB" / etc. When given, the headline grows a "/ <capacity_label> · NN%" suffix so the card reads "21.9 GB / 39 GB · 56%" — mirrors the Overview's Memory/Disk cards. Pass nil for metrics with no natural total (CPU %, HTTP counts, network rates). capacity_pct: NUMBER — integer percentage paired with the label. Always renders alongside capacity_label; nil when the current sample is missing (we omit the "· NN%" trail in that case). chart_type: STRING — "area" (default, the time-series line+fill), "gauge_radial" (semicircle dial), or "gauge_linear" (capacity bar). Gauges need a ceiling (a percent metric, or a capacity_pct); when that's missing the card silently falls back to the area chart so a gauge panel on a limitless metric never renders blank. resizable: renders the column-resize grab handles (metrics-display#startResize). Only meaningful inside a metrics-display dashboard grid; pass false when the card lives in a plain grid (no drag-resize controller) so no dead affordance.



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/clowk/phlex/charts/card.rb', line 75

def initialize(label:, color:, unit:, range_ms:, points: [], current: nil, expand_url: nil, metric: nil, section: nil, default_visible: true, capacity_label: nil, capacity_pct: nil, chart_type: "area", percent: true, series: nil, resizable: true, gauge_bars: nil)
  @resizable = resizable
  # gauge_bars — MULTI linear gauge: [{label:, pct:, value_label:, capacity_label:, color:}]
  # stacked one row per pod (chart_type "gauge_linear"). See render_body.
  @gauge_bars = gauge_bars.is_a?(Array) ? gauge_bars : nil
  @label = label
  @color = color
  @unit = unit
  @points = Array(points)
  # series — OPTIONAL multi-series (pilot: Line): one line per pod. When
  # present the card renders a multi Chart + a legend instead of the single
  # headline/stat strip. See Components::Metrics::Chart#series.
  @series = series.is_a?(Array) ? series : nil
  @range_ms = range_ms
  @current = current
  @expand_url = expand_url
  @metric = metric
  @section = section
  @default_visible = default_visible
  @capacity_label = capacity_label
  @capacity_pct = capacity_pct
  @chart_type = chart_type
  # percent — false makes gauges read the raw value in the center instead of
  # the fill "%" (a count has no natural ceiling → "% of peak" confuses).
  @percent = percent
end

Instance Method Details

#view_templateObject



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/clowk/phlex/charts/card.rb', line 102

def view_template
  root_data = {}

  if @metric
    root_data[:metrics_display_target] = "card"
    root_data[:metric_key] = @metric
  end

  root_data[:section] = @section if @section
  root_data[:default_visible] = "false" unless @default_visible

  div(
    class: "relative bg-clowk-surface border border-clowk-border p-3.5 flex flex-col gap-2 min-w-0",
    data: root_data
  ) do
    card_header
    render_body
    stat_footer
    if @metric && @resizable
      resize_handle("left")
      resize_handle("right")
    end
  end
end