Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Freeze widgets during time-series animation #804

Merged
merged 18 commits into from
Dec 21, 2023
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Not released

- Freeze widgets during time-series animation [#804](https://github.com/CartoDB/carto-react/pull/804)
- Show widget skeleton only once [#811](https://github.com/CartoDB/carto-react/pull/811)
- Added filterable prop to TimeSeriesWidget [#808](https://github.com/CartoDB/carto-react/pull/808)
- Fix dataSources store type [#807](https://github.com/CartoDB/carto-react/pull/807)
Expand Down
2 changes: 1 addition & 1 deletion packages/react-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,4 @@
"react-redux": "^7.2.2 || 8.x",
"redux": "^4.0.5"
}
}
}
2 changes: 1 addition & 1 deletion packages/react-auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,4 @@
"react": "17.x || 18.x",
"react-dom": "17.x || 18.x"
}
}
}
2 changes: 1 addition & 1 deletion packages/react-basemaps/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,4 @@
"react": "17.x || 18.x",
"react-dom": "17.x || 18.x"
}
}
}
2 changes: 1 addition & 1 deletion packages/react-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,4 @@
"h3-js": "^3.7.2",
"quadbin": "^0.1.9"
}
}
}
2 changes: 1 addition & 1 deletion packages/react-core/src/filters/FilterQueryBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const getApplicableFilters = (filters = {}, owner) => {
Object.entries(filters).forEach(([column, filter]) => {
const filterCopy = {};
Object.keys(filter)
.filter((operator) => filter[operator].owner !== owner)
.filter((operator) => filter[operator].owner !== owner && !filter[operator].ignore)
.forEach((operator) => (filterCopy[operator] = { ...filter[operator] }));

if (Object.keys(filterCopy).length) {
Expand Down
2 changes: 1 addition & 1 deletion packages/react-redux/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,4 @@
"@deck.gl/core": "^8.9.18",
"@reduxjs/toolkit": "^1.5.0"
}
}
}
1 change: 1 addition & 0 deletions packages/react-redux/src/slices/cartoSlice.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type FilterBasic = {
values: FilterValues;
owner?: string;
params?: Record<string, unknown>;
ignore?: boolean;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this flag has very specific use case, maybe more verbose name would be better like ignoreByNonOwners or onlyApplyToOwner or noCrossWidgetFiltering ?

ignore seems too broad and misleading (it's still taken into account, but only by owner widget)

};

type FilterCommonProps = {
Expand Down
9 changes: 5 additions & 4 deletions packages/react-redux/src/slices/cartoSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export const createCartoSlice = (initialState) => {
}
},
addFilter: (state, action) => {
const { id, column, type, values, owner, params } = action.payload;
const { id, column, type, values, owner, params, ignore } = action.payload;
const source = state.dataSources[id];

if (source) {
Expand All @@ -148,7 +148,7 @@ export const createCartoSlice = (initialState) => {
source.filters[column] = {};
}

source.filters[column][type] = { values, owner, params };
source.filters[column][type] = { values, owner, params, ignore };
}
},
removeFilter: (state, action) => {
Expand Down Expand Up @@ -326,10 +326,11 @@ export const removeSpatialFilter = (sourceId) => ({
* @param {array} data.values - values for the filter (eg: ['a', 'b'] for IN or [10, 20] for BETWEEN).
* @param {string} data.owner - (optional) id of the widget triggering the filter (to be excluded).
* @param {object=} data.params - (optional) additional filter parameters.
* * @param {string} data.ignore - (optional) boolean indicating that it should be ignored by other widgets.
*/
export const addFilter = ({ id, column, type, values, owner, params }) => ({
export const addFilter = ({ id, column, type, values, owner, params, ignore }) => ({
type: 'carto/addFilter',
payload: { id, column, type, values, owner, params }
payload: { id, column, type, values, owner, params, ignore }
});

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/react-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,4 @@
"react-dom": "17.x || 18.x",
"react-intl": "^6.5.0"
}
}
}
2 changes: 1 addition & 1 deletion packages/react-widgets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,4 @@
"react-redux": "^7.2.2 || 8.x",
"redux": "^4.0.5"
}
}
}
65 changes: 54 additions & 11 deletions packages/react-widgets/src/widgets/TimeSeriesWidget.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import {
AggregationTypes,
_FilterTypes as FilterTypes,
_hasFeatureFlag,
_FeatureFlags
_FeatureFlags,
debounce
} from '@carto/react-core';
import { capitalize, Menu, MenuItem, SvgIcon } from '@mui/material';
import { PropTypes } from 'prop-types';
Expand Down Expand Up @@ -48,6 +49,8 @@ function calculateNextStep(time, stepType, stepMultiplier = 1) {

const EMPTY_ARRAY = [];

const debounceTimeout = 250;

/**
* Renders a <TimeSeriesWidget /> component
* @param {object} props
Expand Down Expand Up @@ -145,6 +148,7 @@ function TimeSeriesWidget({
const dispatch = useDispatch();

const [selectedStepSize, setSelectedStepSize] = useState(stepSize);
const [isRunningAnimation, setIsRunningAnimation] = useState(false);
zbigg marked this conversation as resolved.
Show resolved Hide resolved

const selectedCategories =
useWidgetFilterValues({
Expand Down Expand Up @@ -249,7 +253,8 @@ function TimeSeriesWidget({
type: FilterTypes.TIME,
values: [timeWindow.map((date) => date.getTime?.() || date)],
params: { offsetBy: minTime },
owner: id
owner: id,
...(isRunningAnimation && { ignore: true })
})
);
} else {
Expand All @@ -264,7 +269,21 @@ function TimeSeriesWidget({

if (onTimeWindowUpdate) onTimeWindowUpdate(timeWindow);
},
[isLoading, dispatch, dataSource, column, minTime, id, onTimeWindowUpdate]
[
isLoading,
onTimeWindowUpdate,
dispatch,
dataSource,
column,
minTime,
id,
isRunningAnimation
]
);

const handleTimeWindowUpdateDebounced = useMemo(
() => debounce(handleTimeWindowUpdate, debounceTimeout),
[handleTimeWindowUpdate]
);

const handleTimelineUpdate = useCallback(
Expand All @@ -284,7 +303,8 @@ function TimeSeriesWidget({
[moment, calculateNextStep(moment, selectedStepSize, stepMultiplier) - 1]
],
params: { offsetBy: minTime },
owner: id
owner: id,
...(isRunningAnimation && { ignore: true })
})
);
} else {
Expand All @@ -302,17 +322,23 @@ function TimeSeriesWidget({
[
isLoading,
data,
onTimelineUpdate,
dispatch,
dataSource,
column,
selectedStepSize,
stepMultiplier,
minTime,
id,
onTimelineUpdate
isRunningAnimation
]
);

const handleTimelineUpdateDebounced = useMemo(
() => debounce(handleTimelineUpdate, debounceTimeout),
[handleTimelineUpdate]
);

const handleSelectedCategoriesChange = useCallback(
(newSelectedCategories) => {
if (!splitByCategory || !newSelectedCategories) return;
Expand Down Expand Up @@ -341,17 +367,28 @@ function TimeSeriesWidget({
);

const handleStop = useCallback(() => {
setIsRunningAnimation(false);
// The onStop must be executed before the removeFilter to avoid repeated Maps API calls in Builder
if (onStop) onStop();
dispatch(
removeFilter({
id: dataSource,
column,
owner: id
})
);

if (onStop) onStop();
}, [column, dataSource, id, dispatch, onStop]);

const handlePlay = () => {
setIsRunningAnimation(true);
if (onPlay) onPlay();
};

const handlePause = () => {
setIsRunningAnimation(false);
if (onPause) onPause();
};

const [anchorEl, setAnchorEl] = useState(null);

const handleOpenStepSizeMenu = (e) => {
Expand Down Expand Up @@ -415,13 +452,19 @@ function TimeSeriesWidget({
animation={animation}
filterable={filterable}
isPlaying={isPlaying}
onPlay={onPlay}
onPlay={handlePlay}
isPaused={isPaused}
onPause={onPause}
onPause={handlePause}
onStop={handleStop}
onTimelineUpdate={handleTimelineUpdate}
onTimelineUpdate={
isRunningAnimation ? handleTimelineUpdate : handleTimelineUpdateDebounced
}
timeWindow={timeWindow}
onTimeWindowUpdate={handleTimeWindowUpdate}
onTimeWindowUpdate={
isRunningAnimation
? handleTimeWindowUpdate
: handleTimeWindowUpdateDebounced
}
selectedCategories={selectedCategories}
onSelectedCategoriesChange={
splitByCategory ? handleSelectedCategoriesChange : undefined
Expand Down
2 changes: 1 addition & 1 deletion packages/react-workers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,4 @@
"@turf/intersect": "^6.3.0",
"thenby": "^1.3.4"
}
}
}