Comments (4)
To fix the issue where the location filter displays locations from both the previous and current accounts when switching accounts, you need to ensure that the filters are reset or cleared when an account switch occurs. This can be done by updating the state of the filters to their default values upon account change.
Here is an example of how you might implement this:
- Reset Filters on Account Switch: Ensure that the filters are reset to their default state when an account switch is detected.
import { nativeFilters, dataMaskWith2Filters, singleNativeFiltersState, dataMaskWith1Filter } from './path/to/mockNativeFilters';
// Function to reset filters to their default state
function resetFilters() {
Object.keys(nativeFilters.filters).forEach(filterId => {
nativeFilters.filters[filterId].defaultDataMask.filterState.value = null;
});
}
// Function to handle account switch
function handleAccountSwitch() {
// Reset filters
resetFilters();
// Additional logic for handling account switch
// ...
}
// Example usage: Call handleAccountSwitch when an account switch is detected
handleAccountSwitch();
- Update Filter State: Ensure that the filter state is updated correctly in the application state management (e.g., Redux, Context API).
import { useDispatch } from 'react-redux';
import { setDataMask } from '@superset-ui/core';
const dispatch = useDispatch();
function resetFilters() {
Object.keys(nativeFilters.filters).forEach(filterId => {
dispatch(setDataMask({
filterId,
filterState: {
value: null,
},
}));
});
}
function handleAccountSwitch() {
// Reset filters
resetFilters();
// Additional logic for handling account switch
// ...
}
// Example usage: Call handleAccountSwitch when an account switch is detected
handleAccountSwitch();
By resetting the filters to their default state when an account switch occurs, you can ensure that the location filter does not display locations from both the previous and current accounts [1].
To continue talking to Dosu, mention @dosu.
from superset.
To resolve the issue of the location filter retaining locations from the previous account when switching accounts in Superset version 3.1.1 (Docker image), you need to ensure that the data masks are cleared when switching accounts. Here is a potential solution:
- Add a new effect to listen for account changes.
- Clear the data masks when the account changes.
You can modify the FilterBar
component as follows:
import React, {
useEffect,
useState,
useCallback,
createContext,
useRef,
} from 'react';
import { useDispatch, useSelector } from 'react-redux';
import {
DataMaskStateWithId,
DataMaskWithId,
Filter,
DataMask,
SLOW_DEBOUNCE,
isNativeFilter,
usePrevious,
styled,
} from '@superset-ui/core';
import { useHistory } from 'react-router-dom';
import { updateDataMask, clearDataMask } from 'src/dataMask/actions';
import { useImmer } from 'use-immer';
import { isEmpty, isEqual, debounce } from 'lodash';
import { getInitialDataMask } from 'src/dataMask/reducer';
import { URL_PARAMS } from 'src/constants';
import { getUrlParam } from 'src/utils/urlUtils';
import { useTabId } from 'src/hooks/useTabId';
import { logEvent } from 'src/logger/actions';
import { LOG_ACTIONS_CHANGE_DASHBOARD_FILTER } from 'src/logger/LogUtils';
import { FilterBarOrientation, RootState } from 'src/dashboard/types';
import { UserWithPermissionsAndRoles } from 'src/types/bootstrapTypes';
import { checkIsApplyDisabled } from './utils';
import { FiltersBarProps } from './types';
import {
useNativeFiltersDataMask,
useFilters,
useFilterUpdates,
useInitialization,
} from './state';
import { createFilterKey, updateFilterKey } from './keyValue';
import ActionButtons from './ActionButtons';
import Horizontal from './Horizontal';
import Vertical from './Vertical';
import { useSelectFiltersInScope } from '../state';
const HiddenFilterBar = styled.div`
display: none;
`;
const EXCLUDED_URL_PARAMS: string[] = [
URL_PARAMS.nativeFilters.name,
URL_PARAMS.permalinkKey.name,
];
const publishDataMask = debounce(
async (
history,
dashboardId,
updateKey,
dataMaskSelected: DataMaskStateWithId,
tabId,
) => {
const { location } = history;
const { search } = location;
const previousParams = new URLSearchParams(search);
const newParams = new URLSearchParams();
let dataMaskKey: string | null;
previousParams.forEach((value, key) => {
if (!EXCLUDED_URL_PARAMS.includes(key)) {
newParams.append(key, value);
}
});
const nativeFiltersCacheKey = getUrlParam(URL_PARAMS.nativeFiltersKey);
const dataMask = JSON.stringify(dataMaskSelected);
if (
updateKey &&
nativeFiltersCacheKey &&
(await updateFilterKey(
dashboardId,
dataMask,
nativeFiltersCacheKey,
tabId,
))
) {
dataMaskKey = nativeFiltersCacheKey;
} else {
dataMaskKey = await createFilterKey(dashboardId, dataMask, tabId);
}
if (dataMaskKey) {
newParams.set(URL_PARAMS.nativeFiltersKey.name, dataMaskKey);
}
if (window.location.pathname.includes('/superset/dashboard')) {
history.location.pathname = window.location.pathname;
history.replace({
search: newParams.toString(),
});
}
},
SLOW_DEBOUNCE,
);
export const FilterBarScrollContext = createContext(false);
const FilterBar: React.FC<FiltersBarProps> = ({
orientation = FilterBarOrientation.Vertical,
verticalConfig,
hidden = false,
}) => {
const history = useHistory();
const dataMaskApplied: DataMaskStateWithId = useNativeFiltersDataMask();
const [dataMaskSelected, setDataMaskSelected] =
useImmer<DataMaskStateWithId>(dataMaskApplied);
const dispatch = useDispatch();
const [updateKey, setUpdateKey] = useState(0);
const tabId = useTabId();
const filters = useFilters();
const previousFilters = usePrevious(filters);
const filterValues = Object.values(filters);
const nativeFilterValues = filterValues.filter(isNativeFilter);
const dashboardId = useSelector<any, number>(
({ dashboardInfo }) => dashboardInfo?.id,
);
const previousDashboardId = usePrevious(dashboardId);
const canEdit = useSelector<RootState, boolean>(
({ dashboardInfo }) => dashboardInfo.dash_edit_perm,
);
const user: UserWithPermissionsAndRoles = useSelector<
RootState,
UserWithPermissionsAndRoles
>(state => state.user);
const [filtersInScope] = useSelectFiltersInScope(nativeFilterValues);
const dataMaskSelectedRef = useRef(dataMaskSelected);
dataMaskSelectedRef.current = dataMaskSelected;
const handleFilterSelectionChange = useCallback(
(
filter: Pick<Filter, 'id'> & Partial<Filter>,
dataMask: Partial<DataMask>,
) => {
setDataMaskSelected(draft => {
if (
dataMask.filterState?.value !== undefined &&
dataMaskSelectedRef.current[filter.id]?.filterState?.value ===
undefined &&
filter.requiredFirst
) {
dispatch(updateDataMask(filter.id, dataMask));
}
draft[filter.id] = {
...(getInitialDataMask(filter.id) as DataMaskWithId),
...dataMask,
};
});
},
[dispatch, setDataMaskSelected],
);
useEffect(() => {
if (previousFilters && dashboardId === previousDashboardId) {
const updates = {};
Object.values(filters).forEach(currentFilter => {
const previousFilter = previousFilters?.[currentFilter.id];
if (!previousFilter) {
return;
}
const currentType = currentFilter.filterType;
const currentTargets = currentFilter.targets;
const currentDataMask = currentFilter.defaultDataMask;
const previousType = previousFilter?.filterType;
const previousTargets = previousFilter?.targets;
const previousDataMask = previousFilter?.defaultDataMask;
const typeChanged = currentType !== previousType;
const targetsChanged = !isEqual(currentTargets, previousTargets);
const dataMaskChanged = !isEqual(currentDataMask, previousDataMask);
if (typeChanged || targetsChanged || dataMaskChanged) {
updates[currentFilter.id] = getInitialDataMask(currentFilter.id);
}
});
if (!isEmpty(updates)) {
setDataMaskSelected(draft => ({ ...draft, ...updates }));
Object.keys(updates).forEach(key => dispatch(clearDataMask(key)));
}
}
}, [
JSON.stringify(filters),
JSON.stringify(previousFilters),
previousDashboardId,
]);
const dataMaskAppliedText = JSON.stringify(dataMaskApplied);
useEffect(() => {
setDataMaskSelected(() => dataMaskApplied);
}, [dataMaskAppliedText, setDataMaskSelected]);
useEffect(() => {
if (user?.userId) {
publishDataMask(history, dashboardId, updateKey, dataMaskApplied, tabId);
}
}, [dashboardId, dataMaskAppliedText, history, updateKey, tabId]);
// New effect to handle account switching
useEffect(() => {
const handleAccountSwitch = () => {
Object.keys(dataMaskSelected).forEach(filterId => {
dispatch(clearDataMask(filterId));
});
setDataMaskSelected({});
};
// Assuming `user` object changes when account switches
handleAccountSwitch();
}, [user, dispatch, setDataMaskSelected]);
const handleApply = useCallback(() => {
dispatch(logEvent(LOG_ACTIONS_CHANGE_DASHBOARD_FILTER, {}));
const filterIds = Object.keys(dataMaskSelected);
setUpdateKey(1);
filterIds.forEach(filterId => {
if (dataMaskSelected[filterId]) {
dispatch(updateDataMask(filterId, dataMaskSelected[filterId]));
}
});
}, [dataMaskSelected, dispatch]);
const handleClearAll = useCallback(() => {
const clearDataMaskIds: string[] = [];
let dispatchAllowed = false;
filtersInScope.filter(isNativeFilter).forEach(filter => {
const { id } = filter;
if (dataMaskSelected[id]) {
if (filter.controlValues?.enableEmptyFilter) {
dispatchAllowed = false;
}
clearDataMaskIds.push(id);
setDataMaskSelected(draft => {
if (draft[id].filterState?.value !== undefined) {
draft[id].filterState!.value = undefined;
}
});
}
});
if (dispatchAllowed) {
clearDataMaskIds.forEach(id => dispatch(clearDataMask(id)));
}
}, [dataMaskSelected, dispatch, filtersInScope, setDataMaskSelected]);
useFilterUpdates(dataMaskSelected, setDataMaskSelected);
const isApplyDisabled = checkIsApplyDisabled(
dataMaskSelected,
dataMaskApplied,
filtersInScope.filter(isNativeFilter),
);
const isInitialized = useInitialization();
const actions = (
<ActionButtons
filterBarOrientation={orientation}
width={verticalConfig?.width}
onApply={handleApply}
onClearAll={handleClearAll}
dataMaskSelected={dataMaskSelected}
dataMaskApplied={dataMaskApplied}
isApplyDisabled={isApplyDisabled}
/>
);
const filterBarComponent =
orientation === FilterBarOrientation.Horizontal ? (
<Horizontal
actions={actions}
canEdit={canEdit}
dashboardId={dashboardId}
dataMaskSelected={dataMaskSelected}
filterValues={filterValues}
isInitialized={isInitialized}
onSelectionChange={handleFilterSelectionChange}
/>
) : verticalConfig ? (
<Vertical
actions={actions}
canEdit={canEdit}
dataMaskSelected={dataMaskSelected}
filtersOpen={verticalConfig.filtersOpen}
filterValues={filterValues}
isInitialized={isInitialized}
height={verticalConfig.height}
offset={verticalConfig.offset}
onSelectionChange={handleFilterSelectionChange}
toggleFiltersBar={verticalConfig.toggleFiltersBar}
width={verticalConfig.width}
/>
) : null;
return hidden ? (
<HiddenFilterBar>{filterBarComponent}</HiddenFilterBar>
) : (
filterBarComponent
);
};
export default React.memo(FilterBar);
This code adds a new useEffect
that listens for changes in the user
object, which is assumed to change when the account switches. When the account changes, it clears all data masks and resets the dataMaskSelected
state [1].
To continue talking to Dosu, mention @dosu.
from superset.
@dosu We are not maintaining the codebase. We are using the 3.1.1 Docker image
from superset.
Something went wrong with the video upload, so I can't see it... but perhaps this'll help:
I'm assuming you have an account
column and a location
column, and have a top level filter for each.
If certain accounts
have certain locations
associated, you might want to use a "dependent filter" as seen here:
![Pasted_Image_6_25_24__9_23 AM](https://private-user-images.githubusercontent.com/812905/342793491-f12dbc43-c1e4-44c9-96cc-e2b7511d9b02.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjE3OTAzODksIm5iZiI6MTcyMTc5MDA4OSwicGF0aCI6Ii84MTI5MDUvMzQyNzkzNDkxLWYxMmRiYzQzLWMxZTQtNDRjOS05NmNjLWUyYjc1MTFkOWIwMi5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwNzI0JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDcyNFQwMzAxMjlaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1kMjllMjUxM2Y4ODcxNzdmM2EwODYwZTYxZDYxNDJmYmM2MzdlOTExNzExNzI0ZmRmM2QxYzI3OTFlMTc4N2ExJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.oDDEPaKYlsfNbUfa4enOBuqywZSlNkkvJ_crsT5HyT4)
By design, changing one filter should not nuke another filter. That would be infuriating.
from superset.
Related Issues (20)
- Compose file './docker-compose.yml' invalid HOT 6
- Custom chart plugins not working in Kubernetes deployment HOT 2
- Remove or make less prominent legacy contributing guide HOT 3
- Request for neo4j driver HOT 1
- SQL Lab Error 'str' object has no attribute 'set' HOT 4
- No module named 'superset.translations.utils' HOT 3
- subquery calculated columns not supported as dimensions with sql_mode=only_full_group_by HOT 4
- SECRET KEY ERROR HOT 7
- When a user wants to delete a dataset , the confirmation message could be more shaped HOT 2
- A report not yet executed is marked like a success HOT 1
- On Country Map, Cross-Filtering is not operational as a source HOT 2
- ModuleNotFoundError: No module named 'pkg_resources' HOT 1
- Report fails to generate if dashboard doesn't contain a chart HOT 1
- Mixed chart doesn't support forced categorical x-axis HOT 1
- Error: `prophet` package not installed HOT 3
- Very very slow Apache Superset dashboard HOT 3
- Superset 4.0.2 : Table Chart - Column Based Total Calculation HOT 2
- Handlebars chart - pagination support HOT 2
- superset_node build failure @nx/nx-linux-x64-gnu missing module HOT 6
- Mixed chart x-axes overlap for time period of last quarter HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from superset.