diff --git a/web/app/api/charts/route.ts b/web/app/api/charts/route.ts index 167bf0f..670a2cf 100644 --- a/web/app/api/charts/route.ts +++ b/web/app/api/charts/route.ts @@ -16,7 +16,7 @@ export const POST = withAuth(async (req: NextRequest) => { filter_combinators = null, filter_items = null, filter_items_exclude = null, filter_items_regex = false, y_min = null, y_max = null, y_scale = 'linear', - series_limit = 20, order_by = 'time', + series_limit = 20, order_by = 'value_asc', } = body; if (!title) return NextResponse.json({ error: 'title required' }, { status: 400 }); diff --git a/web/app/api/signals/route.ts b/web/app/api/signals/route.ts index 196f9d5..7adf374 100644 --- a/web/app/api/signals/route.ts +++ b/web/app/api/signals/route.ts @@ -13,7 +13,7 @@ export const GET = withAuth(async (req: NextRequest) => { const from = p.get('from'); const to = p.get('to'); const useRegex = p.get('regex') === 'true'; - const orderBy = p.get('order_by') ?? 'time'; + const orderBy = p.get('order_by') ?? 'value_asc'; const limit = p.get('limit') ? parseInt(p.get('limit')!, 10) : null; const conditions: string[] = []; @@ -147,8 +147,11 @@ export const GET = withAuth(async (req: NextRequest) => { `(combinator = $${i + idx * 2} AND item_key = $${i + idx * 2 + 1})`, ); const fullWhere = `${where ? where + ' AND' : 'WHERE'} (${seriesConditions.join(' OR ')})`; + const orderCase = top.map((_, idx) => + `WHEN combinator = $${i + idx * 2} AND item_key = $${i + idx * 2 + 1} THEN ${idx}`, + ).join(' '); const result = await pool.query( - `SELECT ${selectCols} FROM signals ${fullWhere} ORDER BY real_time ASC`, + `SELECT ${selectCols} FROM signals ${fullWhere} ORDER BY CASE ${orderCase} ELSE ${top.length} END, real_time ASC`, [...values, ...top.flatMap(r => [r.combinator, r.item_key])], ); return NextResponse.json(result.rows); @@ -175,8 +178,11 @@ export const GET = withAuth(async (req: NextRequest) => { `(combinator = $${i + idx * 2} AND item_key = $${i + idx * 2 + 1})`, ); const fullWhere = `${where ? where + ' AND' : 'WHERE'} (${seriesConditions.join(' OR ')})`; + const orderCase = top.map((_, idx) => + `WHEN combinator = $${i + idx * 2} AND item_key = $${i + idx * 2 + 1} THEN ${idx}`, + ).join(' '); const result = await pool.query( - `SELECT ${selectCols} FROM signals ${fullWhere} ORDER BY real_time ASC`, + `SELECT ${selectCols} FROM signals ${fullWhere} ORDER BY CASE ${orderCase} ELSE ${top.length} END, real_time ASC`, [...values, ...top.flatMap(r => [r.combinator, r.item_key])], ); return NextResponse.json(result.rows); diff --git a/web/components/ChartEditor.tsx b/web/components/ChartEditor.tsx index db526c1..e167ae5 100644 --- a/web/components/ChartEditor.tsx +++ b/web/components/ChartEditor.tsx @@ -37,7 +37,7 @@ export default function ChartEditor({ initial, onSave, onClose }: Props) { const [whitelist, setWhitelist] = useState((initial?.filter_items ?? []).join(', ')); const [blacklist, setBlacklist] = useState((initial?.filter_items_exclude ?? []).join(', ')); const [useRegex, setUseRegex] = useState(initial?.filter_items_regex ?? false); - const [orderBy, setOrderBy] = useState(initial?.order_by ?? 'time'); + const [orderBy, setOrderBy] = useState(initial?.order_by ?? 'value_asc'); const [seriesLimit, setSeriesLimit] = useState(initial?.series_limit ?? 20); const [yMin, setYMin] = useState(initial?.y_min?.toString() ?? ''); const [yMax, setYMax] = useState(initial?.y_max?.toString() ?? ''); @@ -123,7 +123,6 @@ export default function ChartEditor({ initial, onSave, onClose }: Props) {