Skip to content

Commit

Permalink
support metadata from backend
Browse files Browse the repository at this point in the history
  • Loading branch information
zbigg committed Sep 12, 2023
1 parent 00dc8b4 commit f6dd1b3
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const FORMAT_DATE_BY_STEP_SIZE_FOR_TIME_WINDOW = {

function TimeSeriesWidgetUI({
data,
categories,
stepSize,
chartType,
tooltip,
Expand Down Expand Up @@ -80,6 +81,7 @@ function TimeSeriesWidgetUI({
>
<TimeSeriesWidgetUIContent
data={data}
categories={categories}
stepSize={stepSize}
chartType={chartType}
tooltip={tooltip}
Expand All @@ -105,6 +107,7 @@ TimeSeriesWidgetUI.propTypes = {
category: PropTypes.string
})
).isRequired,
categories: PropTypes.arrayOf(PropTypes.string),
stepSize: PropTypes.oneOf(Object.values(GroupDateTypes)).isRequired,
chartType: PropTypes.oneOf(Object.values(CHART_TYPES)),
tooltip: PropTypes.bool,
Expand Down Expand Up @@ -149,6 +152,7 @@ export default TimeSeriesWidgetUI;
// component to be able to use context
function TimeSeriesWidgetUIContent({
data,
categories,
stepSize,
chartType,
tooltip,
Expand All @@ -168,44 +172,29 @@ function TimeSeriesWidgetUIContent({
const { isPlaying, isPaused, timeWindow, timelinePosition, stop } =
useTimeSeriesContext();

const { series, categories } = useMemo(() => {
const series = [];

const categories = [];
const series = useMemo(() => {
const colorMapping = {};
const series = categories
? categories.map((category) => ({
category,
data: [],
color: getColorByCategory(category, {
palette,
fallbackColor,
colorMapping
})
}))
: [{ data: [], color: theme.palette.secondary.main }];

for (const { name, value, category } of data) {
let dataSeriesIndex = category ? categories.indexOf(category) : 0;
if (dataSeriesIndex === -1) {
dataSeriesIndex = categories.length;
categories.push(category);
}
if (!series[dataSeriesIndex]) {
series[dataSeriesIndex] = {
category,
data: []
};
}
series[dataSeriesIndex].data.push([name, value]);
}
// }

const hasMultipleSeries = data[0]?.category || series.length > 1;

if (hasMultipleSeries) {
series.forEach(({ category }, i) => {
series[i].color = getColorByCategory(category, {
palette,
fallbackColor,
colorMapping
});
});
} else {
series[0].color = theme.palette.secondary.main;
const categoryIndex = categories && category ? categories.indexOf(category) : 0;
if (categoryIndex === -1) continue;

series[categoryIndex].data.push([name, value]);
}

return { series, categories };
}, [data, palette, fallbackColor, theme.palette.secondary.main]);
return series;
}, [categories, data, palette, fallbackColor, theme.palette.secondary.main]);

const currentDate = useMemo(() => {
if (!data.length) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ export default function TimeSeriesChart({

const handleClick = useCallback(
(params) => {
if (onCategoryClick) {
if (categories && onCategoryClick) {
const category = categories[params.seriesIndex];
onCategoryClick(category);
}
Expand Down
57 changes: 32 additions & 25 deletions packages/react-widgets/src/models/TimeSeriesModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,38 @@ import { Methods, executeTask } from '@carto/react-workers';
import { normalizeObjectKeys, wrapModelCall } from './utils';
import { AggregationTypes } from '@carto/react-core';

export async function getTimeSeries(props) {
export function getTimeSeries(props) {
if (props.series) {
const { series, ...propsNoSeries } = props;
const rawSeriesData = await Promise.all(
series.map(async ({ operation, operationColumn }) => {
const category = getCategory({ operation, operationColumn, series });
return {
data: await wrapModelCall(
{ ...propsNoSeries, operation, operationColumn },
fromLocal,
fromRemote
),
category
};
})
);
let aggregatedData = [];
for (const { data, category } of rawSeriesData) {
for (const { name, value } of data) {
aggregatedData.push({ name, value, category });
}
}
return aggregatedData;
return getMultipleSeries(props);
} else {
return wrapModelCall(props, fromLocal, fromRemote);
}
}

async function getMultipleSeries(props) {
const { series, ...propsNoSeries } = props;

const categories = series.map(({ operation, operationColumn }) =>
getCategoryForAggregationOperation({ operation, operationColumn, series })
);
const rowsByCategory = await Promise.all(
series.map(async (serie, index) => ({
data: await getTimeSeries({ ...propsNoSeries, ...serie }),
category: categories[index]
}))
);
const rows = [];
for (const { data, category } of rowsByCategory) {
for (const { name, value } of data) {
rows.push({ name, value, category });
}
}
return {
rows,
categories
};
}

// From local
function fromLocal({
source,
Expand Down Expand Up @@ -90,10 +94,13 @@ function fromRemote(props) {
splitByCategoryValues
},
opts: { abortController }
}).then((res) => normalizeObjectKeys(res.rows));
}).then((res) => ({
rows: normalizeObjectKeys(res.rows),
categories: res.metadata?.categories
}));
}

function getCategory({ operation, operationColumn, series }) {
function getCategoryForAggregationOperation({ operation, operationColumn, series }) {
if (operation === AggregationTypes.COUNT) {
return `count of records`;
}
Expand All @@ -103,6 +110,6 @@ function getCategory({ operation, operationColumn, series }) {
if (countColumnUsed < 2) {
return operationColumn;
} else {
return `${operation} of ${operationColumn}`; // todo translate maybe ?
return `${operation} of ${operationColumn}`;
}
}
16 changes: 11 additions & 5 deletions packages/react-widgets/src/widgets/TimeSeriesWidget.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ function TimeSeriesWidget({
}, [stepSize]);

const {
data: unsafeData = [],
data: result = [],
isLoading,
warning,
remoteCalculation
Expand All @@ -186,6 +186,11 @@ function TimeSeriesWidget({
attemptRemoteCalculation: _hasFeatureFlag(_FeatureFlags.REMOTE_WIDGETS)
});

const { data: unsafeData, categories } = Array.isArray(result)
? { data: result, categories: undefined }
: { data: result.rows, categories: result.categories };

// filter nulls, TODO remove when backend already fixes this
const data = useMemo(() => unsafeData.filter((row) => row.name !== null), [unsafeData]);

const handleTimeWindowUpdate = useCallback(
Expand Down Expand Up @@ -238,16 +243,16 @@ function TimeSeriesWidget({
);

const handleSelectedCategoriesChange = useCallback(
(categories) => {
if (!splitByCategory || !categories) return;
(newSelectedCategories) => {
if (!splitByCategory || !newSelectedCategories) return;

if (categories.length) {
if (newSelectedCategories.length) {
dispatch(
addFilter({
id: dataSource,
column: splitByCategory,
type: FilterTypes.IN,
values: categories,
values: newSelectedCategories,
owner: id
})
);
Expand Down Expand Up @@ -324,6 +329,7 @@ function TimeSeriesWidget({
{(!!data.length || isLoading) && (
<TimeSeriesWidgetUI
data={data}
categories={categories}
stepSize={selectedStepSize}
chartType={chartType}
tooltip={tooltip}
Expand Down

0 comments on commit f6dd1b3

Please sign in to comment.