diff --git a/superset-frontend/src/explore/components/DataTablesPane.tsx b/superset-frontend/src/explore/components/DataTablesPane.tsx index f4a7b1bf5a66..24ddf14709f2 100644 --- a/superset-frontend/src/explore/components/DataTablesPane.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane.tsx @@ -24,6 +24,10 @@ import Loading from 'src/components/Loading'; import TableView, { EmptyWrapperType } from 'src/components/TableView'; import { getChartDataRequest } from 'src/chart/chartAction'; import { getClientErrorObject } from 'src/utils/getClientErrorObject'; +import { + getFromLocalStorage, + setInLocalStorage, +} from 'src/utils/localStorageHelpers'; import { CopyToClipboardButton, FilterInput, @@ -44,6 +48,12 @@ const NULLISH_RESULTS_STATE = { const DATA_TABLE_PAGE_SIZE = 50; +const STORAGE_KEYS = { + isOpen: 'is_datapanel_open', +}; + +const DATAPANEL_KEY = 'data'; + const TableControlsWrapper = styled.div` display: flex; align-items: center; @@ -98,7 +108,9 @@ export const DataTablesPane = ({ [RESULT_TYPES.results]?: boolean; [RESULT_TYPES.samples]?: boolean; }>(NULLISH_RESULTS_STATE); - const [panelOpen, setPanelOpen] = useState(false); + const [panelOpen, setPanelOpen] = useState( + getFromLocalStorage(STORAGE_KEYS.isOpen, false), + ); const getData = useCallback( (resultType: string) => { @@ -140,6 +152,10 @@ export const DataTablesPane = ({ [queryFormData], ); + useEffect(() => { + setInLocalStorage(STORAGE_KEYS.isOpen, panelOpen); + }, [panelOpen]); + useEffect(() => { setIsRequestPending(prevState => ({ ...prevState, @@ -244,11 +260,12 @@ export const DataTablesPane = ({ - + { refreshMode: 'debounce', refreshRate: 300, }); - const [splitSizes, setSplitSizes] = useState(INITIAL_SIZES); + const [splitSizes, setSplitSizes] = useState( + getFromLocalStorage(STORAGE_KEYS.sizes, INITIAL_SIZES), + ); const calcSectionHeight = useCallback( percent => { @@ -149,6 +159,10 @@ const ExploreChartPanel = props => { recalcPanelSizes(splitSizes); }, [recalcPanelSizes, splitSizes]); + useEffect(() => { + setInLocalStorage(STORAGE_KEYS.sizes, splitSizes); + }, [splitSizes]); + const onDragEnd = sizes => { setSplitSizes(sizes); }; diff --git a/superset-frontend/src/explore/components/ExploreViewContainer.jsx b/superset-frontend/src/explore/components/ExploreViewContainer.jsx index 990373ac5ac9..11be78b005d7 100644 --- a/superset-frontend/src/explore/components/ExploreViewContainer.jsx +++ b/superset-frontend/src/explore/components/ExploreViewContainer.jsx @@ -30,6 +30,10 @@ import { Global } from '@emotion/core'; import { Tooltip } from 'src/common/components/Tooltip'; import { usePrevious } from 'src/common/hooks/usePrevious'; import Icon from 'src/components/Icon'; +import { + getFromLocalStorage, + setInLocalStorage, +} from 'src/utils/localStorageHelpers'; import ExploreChartPanel from './ExploreChartPanel'; import ConnectedControlPanelsContainer from './ControlPanelsContainer'; import SaveModal from './SaveModal'; @@ -379,20 +383,12 @@ function ExploreViewContainer(props) { } function getSidebarWidths(key) { - try { - return localStorage.getItem(key) || defaultSidebarsWidth[key]; - } catch { - return defaultSidebarsWidth[key]; - } + return getFromLocalStorage(key, defaultSidebarsWidth[key]); } function setSidebarWidths(key, dimension) { - try { - const newDimension = Number(getSidebarWidths(key)) + dimension.width; - localStorage.setItem(key, newDimension); - } catch { - // Catch in case localStorage is unavailable - } + const newDimension = Number(getSidebarWidths(key)) + dimension.width; + setInLocalStorage(key, newDimension); } if (props.standalone) { diff --git a/superset-frontend/src/utils/localStorageHelpers.ts b/superset-frontend/src/utils/localStorageHelpers.ts new file mode 100644 index 000000000000..28f5dfcbaef7 --- /dev/null +++ b/superset-frontend/src/utils/localStorageHelpers.ts @@ -0,0 +1,35 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const getFromLocalStorage = (key: string, defaultValue: any) => { + try { + const value = localStorage.getItem(key); + return JSON.parse(value || 'null') || defaultValue; + } catch { + return defaultValue; + } +}; + +export const setInLocalStorage = (key: string, value: any) => { + try { + localStorage.setItem(key, JSON.stringify(value)); + } catch { + // Catch in case localStorage is unavailable + } +};