#load "../../lib/app.uce" ONCE(Request& context) { ?>" /> " /> = 1024.0 || value <= -1024.0) && unit_index < units.size() - 1) { value /= 1024.0; unit_index += 1; } u32 decimals = disk ? (unit_index >= 4 ? 2 : (unit_index >= 1 ? 1 : 0)) : (unit_index == 0 ? 0 : 1); char buf[64]; snprintf(buf, sizeof(buf), ("%." + std::to_string(decimals) + "f").c_str(), value); return(String(buf) + " " + units[unit_index]); } DTree data_format_value(DTree value, DTree row, DTree column) { DTree result; String format = column["format"].to_string(); String raw = value.to_string(); String sort_value = raw; String display_value = raw; if(format == "number") { display_value = raw; } else if(format == "bytes") { display_value = data_format_bytes(raw, false); } else if(format == "disk-bytes") { display_value = data_format_bytes(raw, true); } else if(format == "percent") { display_value = raw + "%"; } else if(format == "duration-ms") { f64 number = atof(raw.c_str()); if(number >= 1000.0) { char buf[64]; snprintf(buf, sizeof(buf), number >= 10000.0 ? "%.0f s" : "%.1f s", number / 1000.0); display_value = buf; } else { char buf[64]; snprintf(buf, sizeof(buf), number >= 100.0 ? "%.0f ms" : "%.1f ms", number); display_value = buf; } } else if(format == "bool") { bool on = raw == "1" || to_lower(raw) == "true" || to_lower(raw) == "yes"; display_value = on ? "Yes" : "No"; sort_value = on ? "1" : "0"; } result["display"] = display_value; result["sort"] = sort_value; return(result); } COMPONENT:SUMMARY_METRICS(Request& context) { String title = context.props["title"].to_string(); String subtitle = context.props["subtitle"].to_string(); <>

< class="dashboard-stat-card tone-">
>
} COMPONENT:TIMESERIES_CHART(Request& context) { String chart_id = first(context.props["id"].to_string(), "ts-chart-" + std::to_string((u64)time())); String canvas_id = chart_id + "-canvas"; String title = context.props["title"].to_string(); String subtitle = context.props["subtitle"].to_string(); s32 height = std::max(180, (s32)int_val(first(context.props["height"].to_string(), "320"))); String x_axis_label = first(context.props["x_axis_label"].to_string(), "Time"); String y_axis_left_label = first(context.props["y_axis_left_label"].to_string(), "Value"); String y_axis_right_label = context.props["y_axis_right_label"].to_string(); String y_axis_left_format = first(context.props["y_axis_left_format"].to_string(), "number"); String y_axis_right_format = first(context.props["y_axis_right_format"].to_string(), "number"); <>

} COMPONENT:SORTABLE_TABLE(Request& context) { String table_id = first(context.props["id"].to_string(), "sortable-table-" + std::to_string((u64)time())); String title = context.props["title"].to_string(); String subtitle = context.props["subtitle"].to_string(); String empty_label = first(context.props["empty_label"].to_string(), "No data available"); DTree init_options; init_options["storageKey"] = first(context.props["storage_key"].to_string(), "starter.sort." + table_id); if(context.props["sort"]["column"].to_string() != "") { init_options["initialSort"]["column"] = context.props["sort"]["column"]; init_options["initialSort"]["direction"] = first(context.props["sort"]["direction"].to_string(), "asc"); } <>

>
" class="muted">
" data-sort-value="">
} COMPONENT:DATA_TABLE(Request& context) { String table_id = first(context.props["id"].to_string(), "data-grid-" + std::to_string((u64)time())); DTree columns = context.props["columns"]; if(columns.get_type_name() != "array") columns.set_array(); bool has_explicit_columns = columns.is_list() && columns._map.size() > 0 && columns._map.find("0") != columns._map.end() && columns["0"]["field"].to_string() != ""; if(!has_explicit_columns && context.props["items"]["0"].get_type_name() == "array") { context.props["items"]["0"].each([&](DTree value, String key) { DTree col; col["field"] = key; col["headerName"] = key; col["sortable"].set_bool(true); col["filter"].set_bool(true); col["resizable"].set_bool(true); columns.push(col); }); } if(!columns.is_list()) { DTree normalized_columns; normalized_columns.set_array(); columns.each([&](DTree column, String key) { if(column.get_type_name() == "array") normalized_columns.push(column); }); columns = normalized_columns; } DTree row_data = context.props["items"]; if(row_data.get_type_name() != "array") row_data.set_array(); if(!row_data.is_list()) { DTree normalized_rows; normalized_rows.set_array(); row_data.each([&](DTree row, String key) { if(row.get_type_name() == "array") normalized_rows.push(row); }); row_data = normalized_rows; } DTree grid_options; grid_options["pagination"].set_bool(true); grid_options["paginationPageSize"] = first(context.props["options"]["paginationPageSize"].to_string(), "20"); grid_options["paginationPageSizeSelector"].set_bool(false); grid_options["suppressMenuHide"].set_bool(true); grid_options["animateRows"].set_bool(true); grid_options["columnDefs"] = columns; grid_options["rowData"] = row_data; <>
rows
; width: 100%; border: 1px solid var(--border); border-radius: 0 0 0.5rem 0.5rem; overflow: hidden;">
}