diff --git a/statushistorychart/schemas/migrate/migrate.cue b/statushistorychart/schemas/migrate/migrate.cue index 75ef2791..27b20b14 100644 --- a/statushistorychart/schemas/migrate/migrate.cue +++ b/statushistorychart/schemas/migrate/migrate.cue @@ -32,6 +32,7 @@ import "list" kind: "StatusHistoryChart" spec: { + sorting: "asc" #showLegend: *#panel.options.legend.showLegend | true if #showLegend { legend: { diff --git a/statushistorychart/schemas/migrate/tests/mappings/expected.json b/statushistorychart/schemas/migrate/tests/mappings/expected.json index 0a4f4076..91444843 100644 --- a/statushistorychart/schemas/migrate/tests/mappings/expected.json +++ b/statushistorychart/schemas/migrate/tests/mappings/expected.json @@ -5,6 +5,7 @@ "mode": "list", "position": "bottom" }, + "sorting": "asc", "mappings": [ { "kind": "Value", @@ -56,4 +57,4 @@ } ] } -} \ No newline at end of file +} diff --git a/statushistorychart/schemas/status-history.cue b/statushistorychart/schemas/status-history.cue index 67fe6b36..6c3a9fe0 100644 --- a/statushistorychart/schemas/status-history.cue +++ b/statushistorychart/schemas/status-history.cue @@ -21,4 +21,5 @@ kind: "StatusHistoryChart" spec: close({ legend?: common.#legend mappings?: [...common.#mappings] + sorting?: "asc" | "desc" }) diff --git a/statushistorychart/schemas/tests/valid/status-history.json b/statushistorychart/schemas/tests/valid/status-history.json index 98138486..f948d2c9 100644 --- a/statushistorychart/schemas/tests/valid/status-history.json +++ b/statushistorychart/schemas/tests/valid/status-history.json @@ -3,6 +3,7 @@ "spec": { "legend": { "position": "bottom" - } + }, + "sorting": "asc" } } \ No newline at end of file diff --git a/statushistorychart/src/StatusHistoryChartOptionsEditorSettings.tsx b/statushistorychart/src/StatusHistoryChartOptionsEditorSettings.tsx index 1e9d42f9..89bee6f7 100644 --- a/statushistorychart/src/StatusHistoryChartOptionsEditorSettings.tsx +++ b/statushistorychart/src/StatusHistoryChartOptionsEditorSettings.tsx @@ -13,7 +13,14 @@ import { LegendOptionsEditor, LegendOptionsEditorProps } from '@perses-dev/plugin-system'; import { produce } from 'immer'; -import { OptionsEditorGroup, OptionsEditorGrid, OptionsEditorColumn } from '@perses-dev/components'; +import { + OptionsEditorGroup, + OptionsEditorGrid, + OptionsEditorColumn, + SortSelector, + SortOption, + SortSelectorProps, +} from '@perses-dev/components'; import { Button } from '@mui/material'; import { ReactElement } from 'react'; import { StatusHistoryChartOptions, StatusHistroyChartEditorProps } from './status-history-model.js'; @@ -30,6 +37,14 @@ export function StatusHistoryChartOptionsEditorSettings(props: StatusHistroyChar ); }; + const handleSortChange: SortSelectorProps['onChange'] = (newSort: SortOption) => { + onChange( + produce(value, (draft: StatusHistoryChartOptions) => { + draft.sorting = newSort; + }) + ); + }; + return ( @@ -39,6 +54,7 @@ export function StatusHistoryChartOptionsEditorSettings(props: StatusHistroyChar value={value.legend} onChange={handleLegendChange} /> + diff --git a/statushistorychart/src/status-history-model.ts b/statushistorychart/src/status-history-model.ts index 00124a03..b63d5bbd 100644 --- a/statushistorychart/src/status-history-model.ts +++ b/statushistorychart/src/status-history-model.ts @@ -21,6 +21,9 @@ export function createInitialStatusHistoryChartOptions(): Record; diff --git a/statushistorychart/src/utils/data-transform.ts b/statushistorychart/src/utils/data-transform.ts index b9ae4ab9..97072116 100644 --- a/statushistorychart/src/utils/data-transform.ts +++ b/statushistorychart/src/utils/data-transform.ts @@ -60,6 +60,25 @@ export function useStatusHistoryDataModel( }; } + const allSeries = queryResults.reduce((acc, { data }) => { + if (data && data.series) { + acc.push(...data.series); + } + return acc; + }, []); + + if (spec.sorting) { + allSeries.sort((a, b) => { + const nameA = a.formattedName || ''; + const nameB = b.formattedName || ''; + if (spec.sorting === 'asc') { + return nameA.localeCompare(nameA); + } else { + return nameB.localeCompare(nameB); + } + }); + } + const timeScale = getCommonTimeScaleForQueries(queryResults); const statusHistoryData: StatusHistoryDataItem[] = []; const yAxisCategories: string[] = []; @@ -68,33 +87,24 @@ export function useStatusHistoryDataModel( const xAxisCategories = generateCompleteTimestamps(timeScale); - queryResults.forEach(({ data }) => { - if (!data) { - return; - } - - data.series.forEach((item) => { - const instance = item.formattedName || ''; - - yAxisCategories.push(instance); - - const yIndex = yAxisCategories.length - 1; - - item.values.forEach(([time, value]) => { - const itemIndexOnXaxis = xAxisCategories.findIndex((v) => v === time); - if (value !== null && itemIndexOnXaxis !== -1) { - let itemLabel: string | number = value; - if (hasValueMappings) { - const mappedValue = applyValueMapping(value, spec.mappings); - itemLabel = mappedValue.value; - } - legendSet.add(value); - statusHistoryData.push({ - value: [itemIndexOnXaxis, yIndex, value], - label: String(itemLabel), - }); + allSeries.forEach((item) => { + const instance = item.formattedName || ''; + yAxisCategories.push(instance); + const yIndex = yAxisCategories.length - 1; + item.values.forEach(([time, value]) => { + const itemIndexOnXaxis = xAxisCategories.findIndex((v) => v === time); + if (value !== null && itemIndexOnXaxis !== -1) { + let itemLabel: string | number = value; + if (hasValueMappings) { + const mappedValue = applyValueMapping(value, spec.mappings); + itemLabel = mappedValue.value; } - }); + legendSet.add(value); + statusHistoryData.push({ + value: [itemIndexOnXaxis, yIndex, value], + label: String(itemLabel), + }); + } }); }); @@ -141,5 +151,5 @@ export function useStatusHistoryDataModel( timeScale, colors, }; - }, [queryResults, spec.mappings, themeColors]); + }, [queryResults, themeColors, spec]); }