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
3 changes: 0 additions & 3 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,2 @@
engine-strict=true
node-linker=hoisted
@cropwatchdevelopment:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}
always-auth=true
11 changes: 11 additions & 0 deletions messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,10 @@
"traffic_calendar_auth_required": "Calendar data requires an authenticated session.",
"traffic_calendar_fetch_subtitle": "{monthLabel} calendar fetch",
"traffic_calendar_total": "Traffic Total: {count}",
"traffic_chart_hourly_subtitle": "Today, stacked by detection class",
"traffic_chart_hourly_title": "Hourly Traffic Volume",
"traffic_class_breakdown": "Class Breakdown",
"traffic_class_breakdown_subtitle": "Share of today's total",
"traffic_current_hour_today": "Current hour today",
"traffic_current_hour_total": "Current Hour Total",
"traffic_daily_traffic_weather": "Daily Traffic & Weather",
Expand All @@ -933,14 +937,18 @@
"traffic_no_data_this_month": "No traffic recorded for this month",
"traffic_no_data_today": "No traffic data is available for today.",
"traffic_no_traffic_today": "No traffic today",
"traffic_peak_hour": "Peak Hour",
"traffic_precip_summary": "{value} mm precip",
"traffic_preparing_csv": "Preparing CSV...",
"traffic_raw_records_count": "{count} raw records",
"traffic_samples": "Samples",
"traffic_samples_count": "{count} samples",
"traffic_selected_period": "Selected Period",
"traffic_share_of_total": "{value}% of total",
"traffic_today_only": "Today only",
"traffic_today_total": "Today's Total",
"traffic_today_via_coordinates": "Today via device coordinates",
"traffic_top_class": "Top Class",
"traffic_total_traffic": "Total Traffic",
"traffic_tracked_hours_count": "{count} tracked hour(s)",
"traffic_unavailable": "Unavailable",
Expand Down Expand Up @@ -1111,6 +1119,9 @@
"cwui_chart_last_sensor": "At least one sensor must stay visible",
"cwui_chart_hide_series": "Hide {label}",
"cwui_chart_show_series": "Show {label}",
"cwui_stacked_bar_aria": "Stacked bar chart",
"cwui_stacked_bar_total": "Total",
"cwui_stacked_bar_bar": "{label}: {total}",
"cwui_donut_aria": "Donut chart",
"cwui_donut_total": "Total",
"cwui_donut_of_total": "of {total}",
Expand Down
11 changes: 11 additions & 0 deletions messages/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -927,6 +927,10 @@
"traffic_calendar_auth_required": "カレンダーデータの表示には認証済みセッションが必要です。",
"traffic_calendar_fetch_subtitle": "{monthLabel} のカレンダー取得",
"traffic_calendar_total": "交通合計: {count}",
"traffic_chart_hourly_subtitle": "本日・検出クラス別",
"traffic_chart_hourly_title": "時間別交通量",
"traffic_class_breakdown": "クラス別内訳",
"traffic_class_breakdown_subtitle": "本日の合計に対する割合",
"traffic_current_hour_today": "今日の現在時間帯",
"traffic_current_hour_total": "現在時間帯の合計",
"traffic_daily_traffic_weather": "日別交通量と天気",
Expand All @@ -949,14 +953,18 @@
"traffic_no_data_this_month": "この月の交通データは記録されていません",
"traffic_no_data_today": "今日の交通データはありません。",
"traffic_no_traffic_today": "今日は交通データがありません",
"traffic_peak_hour": "ピーク時間",
"traffic_precip_summary": "降水量 {value} mm",
"traffic_preparing_csv": "CSV を準備中...",
"traffic_raw_records_count": "生レコード {count} 件",
"traffic_samples": "サンプル",
"traffic_samples_count": "サンプル {count} 件",
"traffic_selected_period": "選択期間",
"traffic_share_of_total": "全体の{value}%",
"traffic_today_only": "今日のみ",
"traffic_today_total": "本日の合計",
"traffic_today_via_coordinates": "デバイス座標に基づく今日の天気",
"traffic_top_class": "最多クラス",
"traffic_total_traffic": "交通量合計",
"traffic_tracked_hours_count": "追跡時間 {count} 件",
"traffic_unavailable": "利用不可",
Expand Down Expand Up @@ -1111,6 +1119,9 @@
"cwui_chart_last_sensor": "少なくとも 1 つのセンサーを表示する必要があります",
"cwui_chart_hide_series": "{label} を非表示",
"cwui_chart_show_series": "{label} を表示",
"cwui_stacked_bar_aria": "積み上げ棒グラフ",
"cwui_stacked_bar_total": "合計",
"cwui_stacked_bar_bar": "{label}: {total}",
"cwui_donut_aria": "ドーナツチャート",
"cwui_donut_total": "合計",
"cwui_donut_of_total": "/ {total}",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
}
},
"dependencies": {
"@cropwatchdevelopment/cwui": "0.1.110",
"@cropwatchdevelopment/cwui": "0.1.113",
"@supabase/supabase-js": "^2.108.2",
"jwt-decode": "^4.0.0"
}
Expand Down
10 changes: 5 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 20 additions & 2 deletions src/lib/components/dashboard/DashboardCards.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import type { DashboardLocationGroup, DashboardRow } from '$lib/api/api.dtos';
import { getAppContext } from '$lib/appContext.svelte';
import { isDisplayableColumn, labelFor } from '$lib/sensor-labels';
import { formatDateTime } from '$lib/i18n/format';
import { formatSensorMeasurement } from '$lib/units';
import { m } from '$lib/paraglide/messages.js';
import { goto } from '$app/navigation';
Expand Down Expand Up @@ -253,18 +254,34 @@
return Object.entries(details)
.filter(([col, value]) => isDisplayableColumn(col) && value !== null && value !== undefined)
.map(([col, value]) => {
// traffic_hour is the hourly bucket start timestamp — render it as a
// localized date+hour instead of letting the number formatter see NaN.
if (col === 'traffic_hour') {
const valueDisplay = formatDateTime(
String(value),
{ month: 'short', day: 'numeric', hour: 'numeric' },
String(value)
);
return { col, def: labelFor(col), valueDisplay, unit: '' };
}
const fm = formatSensorMeasurement(col, value, app.preferences);
return { col, def: labelFor(col), valueDisplay: fm.valueDisplay, unit: fm.unit };
});
}

// Unit-bearing numeric metrics come back converted to the user's preference;
// booleans render as an On/Off label, unmapped columns keep their canonical unit.
// Integer metrics pass their formatted text as the label so the card doesn't
// re-format them with its 2-decimal number formatter ("0.00" for counts).
function readingProps(col: string, raw: unknown) {
const fm = formatSensorMeasurement(col, raw, app.preferences);
if (labelFor(col).format === 'boolean') {
const format = labelFor(col).format;
if (format === 'boolean') {
return { value: null, unit: '', label: fm.valueDisplay };
}
if (format === 'integer' && fm.value !== null && fm.value !== undefined) {
return { value: fm.value, unit: fm.unit, label: fm.valueDisplay };
}
return { value: fm.value, unit: fm.unit, label: undefined };
}

Expand Down Expand Up @@ -379,6 +396,7 @@
row.device_type.default_upload_interval ??
60}
storageKey={`dashboard:${row.dev_eui}`}
detailsHeading={m.common_details()}
onExpand={() => loadDetails(row.dev_eui)}
>
{#if details === undefined || details === 'loading'}
Expand All @@ -388,7 +406,7 @@
{:else}
<dl class="dashboard-cards__details-list">
{#each detailRows as { col, def, valueDisplay, unit } (col)}
{#if def.label() != 'created_at'}
{#if col !== 'created_at'}
<div class="dashboard-cards__details-row">
<dt>{def.label()}</dt>
<dd>
Expand Down
Loading
Loading