mirror of
https://github.com/apache/superset.git
synced 2024-09-06 22:07:34 -04:00
parent
d8117f7e37
commit
0bcc21bc45
@ -140,25 +140,27 @@ export function sliceUpdated(slice: Slice) {
|
||||
return { type: SLICE_UPDATED, slice };
|
||||
}
|
||||
|
||||
export const SET_TIME_FORMATTED_COLUMN = 'SET_TIME_FORMATTED_COLUMN';
|
||||
export function setTimeFormattedColumn(
|
||||
export const SET_ORIGINAL_FORMATTED_TIME_COLUMN =
|
||||
'SET_ORIGINAL_FORMATTED_TIME_COLUMN';
|
||||
export function setOriginalFormattedTimeColumn(
|
||||
datasourceId: string,
|
||||
columnName: string,
|
||||
) {
|
||||
return {
|
||||
type: SET_TIME_FORMATTED_COLUMN,
|
||||
type: SET_ORIGINAL_FORMATTED_TIME_COLUMN,
|
||||
datasourceId,
|
||||
columnName,
|
||||
};
|
||||
}
|
||||
|
||||
export const UNSET_TIME_FORMATTED_COLUMN = 'UNSET_TIME_FORMATTED_COLUMN';
|
||||
export function unsetTimeFormattedColumn(
|
||||
export const UNSET_ORIGINAL_FORMATTED_TIME_COLUMN =
|
||||
'UNSET_ORIGINAL_FORMATTED_TIME_COLUMN';
|
||||
export function unsetOriginalFormattedTimeColumn(
|
||||
datasourceId: string,
|
||||
columnIndex: number,
|
||||
) {
|
||||
return {
|
||||
type: UNSET_TIME_FORMATTED_COLUMN,
|
||||
type: UNSET_ORIGINAL_FORMATTED_TIME_COLUMN,
|
||||
datasourceId,
|
||||
columnIndex,
|
||||
};
|
||||
@ -187,8 +189,8 @@ export const exploreActions = {
|
||||
updateChartTitle,
|
||||
createNewSlice,
|
||||
sliceUpdated,
|
||||
setTimeFormattedColumn,
|
||||
unsetTimeFormattedColumn,
|
||||
setOriginalFormattedTimeColumn,
|
||||
unsetOriginalFormattedTimeColumn,
|
||||
setForceQuery,
|
||||
};
|
||||
|
||||
|
@ -35,8 +35,8 @@ import { Input } from 'src/components/Input';
|
||||
import {
|
||||
BOOL_FALSE_DISPLAY,
|
||||
BOOL_TRUE_DISPLAY,
|
||||
SLOW_DEBOUNCE,
|
||||
NULL_DISPLAY,
|
||||
SLOW_DEBOUNCE,
|
||||
} from 'src/constants';
|
||||
import { Radio } from 'src/components/Radio';
|
||||
import Icons from 'src/components/Icons';
|
||||
@ -46,8 +46,8 @@ import { prepareCopyToClipboardTabularData } from 'src/utils/common';
|
||||
import CopyToClipboard from 'src/components/CopyToClipboard';
|
||||
import RowCountLabel from 'src/explore/components/RowCountLabel';
|
||||
import {
|
||||
setTimeFormattedColumn,
|
||||
unsetTimeFormattedColumn,
|
||||
setOriginalFormattedTimeColumn,
|
||||
unsetOriginalFormattedTimeColumn,
|
||||
} from 'src/explore/actions/exploreActions';
|
||||
|
||||
export const CellNull = styled('span')`
|
||||
@ -143,8 +143,8 @@ const FormatPicker = ({
|
||||
}) => (
|
||||
<Radio.Group value={value} onChange={onChange}>
|
||||
<Space direction="vertical">
|
||||
<Radio value={FormatPickerValue.Original}>{t('Original value')}</Radio>
|
||||
<Radio value={FormatPickerValue.Formatted}>{t('Formatted date')}</Radio>
|
||||
<Radio value={FormatPickerValue.Original}>{t('Original value')}</Radio>
|
||||
</Space>
|
||||
</Radio.Group>
|
||||
);
|
||||
@ -166,15 +166,15 @@ const FormatPickerLabel = styled.span`
|
||||
const DataTableTemporalHeaderCell = ({
|
||||
columnName,
|
||||
datasourceId,
|
||||
timeFormattedColumnIndex,
|
||||
originalFormattedTimeColumnIndex,
|
||||
}: {
|
||||
columnName: string;
|
||||
datasourceId?: string;
|
||||
timeFormattedColumnIndex: number;
|
||||
originalFormattedTimeColumnIndex: number;
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const dispatch = useDispatch();
|
||||
const isColumnTimeFormatted = timeFormattedColumnIndex > -1;
|
||||
const isTimeColumnOriginalFormatted = originalFormattedTimeColumnIndex > -1;
|
||||
|
||||
const onChange = useCallback(
|
||||
e => {
|
||||
@ -183,24 +183,27 @@ const DataTableTemporalHeaderCell = ({
|
||||
}
|
||||
if (
|
||||
e.target.value === FormatPickerValue.Original &&
|
||||
isColumnTimeFormatted
|
||||
!isTimeColumnOriginalFormatted
|
||||
) {
|
||||
dispatch(
|
||||
unsetTimeFormattedColumn(datasourceId, timeFormattedColumnIndex),
|
||||
);
|
||||
dispatch(setOriginalFormattedTimeColumn(datasourceId, columnName));
|
||||
} else if (
|
||||
e.target.value === FormatPickerValue.Formatted &&
|
||||
!isColumnTimeFormatted
|
||||
isTimeColumnOriginalFormatted
|
||||
) {
|
||||
dispatch(setTimeFormattedColumn(datasourceId, columnName));
|
||||
dispatch(
|
||||
unsetOriginalFormattedTimeColumn(
|
||||
datasourceId,
|
||||
originalFormattedTimeColumnIndex,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
[
|
||||
timeFormattedColumnIndex,
|
||||
originalFormattedTimeColumnIndex,
|
||||
columnName,
|
||||
datasourceId,
|
||||
dispatch,
|
||||
isColumnTimeFormatted,
|
||||
isTimeColumnOriginalFormatted,
|
||||
],
|
||||
);
|
||||
const overlayContent = useMemo(
|
||||
@ -219,14 +222,14 @@ const DataTableTemporalHeaderCell = ({
|
||||
<FormatPicker
|
||||
onChange={onChange}
|
||||
value={
|
||||
isColumnTimeFormatted
|
||||
? FormatPickerValue.Formatted
|
||||
: FormatPickerValue.Original
|
||||
isTimeColumnOriginalFormatted
|
||||
? FormatPickerValue.Original
|
||||
: FormatPickerValue.Formatted
|
||||
}
|
||||
/>
|
||||
</FormatPickerContainer>
|
||||
) : null,
|
||||
[datasourceId, isColumnTimeFormatted, onChange],
|
||||
[datasourceId, isTimeColumnOriginalFormatted, onChange],
|
||||
);
|
||||
|
||||
return datasourceId ? (
|
||||
@ -285,7 +288,7 @@ export const useTableColumns = (
|
||||
coltypes?: GenericDataType[],
|
||||
data?: Record<string, any>[],
|
||||
datasourceId?: string,
|
||||
timeFormattedColumns: string[] = [],
|
||||
originalFormattedTimeColumns: string[] = [],
|
||||
moreConfigs?: { [key: string]: Partial<Column> },
|
||||
) =>
|
||||
useMemo(
|
||||
@ -294,20 +297,25 @@ export const useTableColumns = (
|
||||
? colnames
|
||||
.filter((column: string) => Object.keys(data[0]).includes(column))
|
||||
.map((key, index) => {
|
||||
const timeFormattedColumnIndex =
|
||||
coltypes?.[index] === GenericDataType.TEMPORAL
|
||||
? timeFormattedColumns.indexOf(key)
|
||||
const colType = coltypes?.[index];
|
||||
const firstValue = data[0][key];
|
||||
const originalFormattedTimeColumnIndex =
|
||||
colType === GenericDataType.TEMPORAL
|
||||
? originalFormattedTimeColumns.indexOf(key)
|
||||
: -1;
|
||||
return {
|
||||
id: key,
|
||||
accessor: row => row[key],
|
||||
// When the key is empty, have to give a string of length greater than 0
|
||||
Header:
|
||||
coltypes?.[index] === GenericDataType.TEMPORAL ? (
|
||||
colType === GenericDataType.TEMPORAL &&
|
||||
typeof firstValue !== 'string' ? (
|
||||
<DataTableTemporalHeaderCell
|
||||
columnName={key}
|
||||
datasourceId={datasourceId}
|
||||
timeFormattedColumnIndex={timeFormattedColumnIndex}
|
||||
originalFormattedTimeColumnIndex={
|
||||
originalFormattedTimeColumnIndex
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
key
|
||||
@ -322,7 +330,11 @@ export const useTableColumns = (
|
||||
if (value === null) {
|
||||
return <CellNull>{NULL_DISPLAY}</CellNull>;
|
||||
}
|
||||
if (timeFormattedColumnIndex > -1) {
|
||||
if (
|
||||
colType === GenericDataType.TEMPORAL &&
|
||||
originalFormattedTimeColumnIndex === -1 &&
|
||||
typeof value === 'number'
|
||||
) {
|
||||
return timeFormatter(value);
|
||||
}
|
||||
return String(value);
|
||||
@ -331,5 +343,12 @@ export const useTableColumns = (
|
||||
} as Column;
|
||||
})
|
||||
: [],
|
||||
[colnames, data, coltypes, datasourceId, moreConfigs, timeFormattedColumns],
|
||||
[
|
||||
colnames,
|
||||
data,
|
||||
coltypes,
|
||||
datasourceId,
|
||||
moreConfigs,
|
||||
originalFormattedTimeColumns,
|
||||
],
|
||||
);
|
||||
|
@ -28,31 +28,53 @@ const asciiChars = [];
|
||||
for (let i = 32; i < 127; i += 1) {
|
||||
asciiChars.push(String.fromCharCode(i));
|
||||
}
|
||||
const asciiKey = asciiChars.join('');
|
||||
const unicodeKey = '你好. 吃了吗?';
|
||||
const ASCII_KEY = asciiChars.join('');
|
||||
const UNICODE_KEY = '你好. 吃了吗?';
|
||||
const NUMTIME_KEY = 'numtime';
|
||||
const STRTIME_KEY = 'strtime';
|
||||
const NUMTIME_VALUE = 1640995200000;
|
||||
const NUMTIME_FORMATTED_VALUE = '2022-01-01 00:00:00';
|
||||
const STRTIME_VALUE = '2022-01-01';
|
||||
|
||||
const data = [
|
||||
{ col01: true, col02: false, [asciiKey]: asciiKey, [unicodeKey]: unicodeKey },
|
||||
{ col01: true, col02: false, [asciiKey]: asciiKey, [unicodeKey]: unicodeKey },
|
||||
{ col01: true, col02: false, [asciiKey]: asciiKey, [unicodeKey]: unicodeKey },
|
||||
{
|
||||
col01: true,
|
||||
col02: false,
|
||||
col03: 'secret',
|
||||
[asciiKey]: asciiKey,
|
||||
[unicodeKey]: unicodeKey,
|
||||
},
|
||||
const colnames = [
|
||||
'col01',
|
||||
'col02',
|
||||
ASCII_KEY,
|
||||
UNICODE_KEY,
|
||||
NUMTIME_KEY,
|
||||
STRTIME_KEY,
|
||||
];
|
||||
const all_columns = ['col01', 'col02', 'col03', asciiKey, unicodeKey];
|
||||
const coltypes = [
|
||||
GenericDataType.BOOLEAN,
|
||||
GenericDataType.BOOLEAN,
|
||||
GenericDataType.STRING,
|
||||
GenericDataType.STRING,
|
||||
GenericDataType.TEMPORAL,
|
||||
GenericDataType.TEMPORAL,
|
||||
];
|
||||
|
||||
const cellValues = {
|
||||
col01: true,
|
||||
col02: false,
|
||||
[ASCII_KEY]: ASCII_KEY,
|
||||
[UNICODE_KEY]: UNICODE_KEY,
|
||||
[NUMTIME_KEY]: NUMTIME_VALUE,
|
||||
[STRTIME_KEY]: STRTIME_VALUE,
|
||||
};
|
||||
|
||||
const data = [cellValues, cellValues, cellValues, cellValues];
|
||||
|
||||
const expectedDisplayValues = {
|
||||
col01: BOOL_TRUE_DISPLAY,
|
||||
col02: BOOL_FALSE_DISPLAY,
|
||||
[ASCII_KEY]: ASCII_KEY,
|
||||
[UNICODE_KEY]: UNICODE_KEY,
|
||||
[NUMTIME_KEY]: NUMTIME_FORMATTED_VALUE,
|
||||
[STRTIME_KEY]: STRTIME_VALUE,
|
||||
};
|
||||
|
||||
test('useTableColumns with no options', () => {
|
||||
const hook = renderHook(() => useTableColumns(all_columns, coltypes, data));
|
||||
const hook = renderHook(() => useTableColumns(colnames, coltypes, data));
|
||||
expect(hook.result.current).toEqual([
|
||||
{
|
||||
Cell: expect.any(Function),
|
||||
@ -68,102 +90,61 @@ test('useTableColumns with no options', () => {
|
||||
},
|
||||
{
|
||||
Cell: expect.any(Function),
|
||||
Header: asciiKey,
|
||||
Header: ASCII_KEY,
|
||||
accessor: expect.any(Function),
|
||||
id: asciiKey,
|
||||
id: ASCII_KEY,
|
||||
},
|
||||
{
|
||||
Cell: expect.any(Function),
|
||||
Header: unicodeKey,
|
||||
Header: UNICODE_KEY,
|
||||
accessor: expect.any(Function),
|
||||
id: unicodeKey,
|
||||
id: UNICODE_KEY,
|
||||
},
|
||||
{
|
||||
Cell: expect.any(Function),
|
||||
Header: expect.objectContaining({
|
||||
type: expect.objectContaining({
|
||||
name: 'DataTableTemporalHeaderCell',
|
||||
}),
|
||||
props: expect.objectContaining({
|
||||
originalFormattedTimeColumnIndex: -1,
|
||||
}),
|
||||
}),
|
||||
accessor: expect.any(Function),
|
||||
id: NUMTIME_KEY,
|
||||
},
|
||||
{
|
||||
Cell: expect.any(Function),
|
||||
Header: STRTIME_KEY,
|
||||
accessor: expect.any(Function),
|
||||
id: STRTIME_KEY,
|
||||
},
|
||||
]);
|
||||
hook.result.current.forEach((col: JsonObject) => {
|
||||
expect(col.accessor(data[0])).toBe(data[0][col.Header]);
|
||||
expect(col.accessor(data[0])).toBe(data[0][col.id]);
|
||||
});
|
||||
|
||||
hook.result.current.forEach((col: JsonObject) => {
|
||||
data.forEach(row => {
|
||||
expect(col.Cell({ value: row.col01 })).toBe(BOOL_TRUE_DISPLAY);
|
||||
expect(col.Cell({ value: row.col02 })).toBe(BOOL_FALSE_DISPLAY);
|
||||
expect(col.Cell({ value: row[asciiKey] })).toBe(asciiKey);
|
||||
expect(col.Cell({ value: row[unicodeKey] })).toBe(unicodeKey);
|
||||
expect(col.Cell({ value: row[col.id] })).toBe(
|
||||
expectedDisplayValues[col.id],
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('use only the first record columns', () => {
|
||||
const newData = [data[3], data[0]];
|
||||
const hook = renderHook(() =>
|
||||
useTableColumns(all_columns, coltypes, newData),
|
||||
);
|
||||
expect(hook.result.current).toEqual([
|
||||
{
|
||||
Cell: expect.any(Function),
|
||||
Header: 'col01',
|
||||
accessor: expect.any(Function),
|
||||
id: 'col01',
|
||||
},
|
||||
{
|
||||
Cell: expect.any(Function),
|
||||
Header: 'col02',
|
||||
accessor: expect.any(Function),
|
||||
id: 'col02',
|
||||
},
|
||||
{
|
||||
Cell: expect.any(Function),
|
||||
Header: 'col03',
|
||||
accessor: expect.any(Function),
|
||||
id: 'col03',
|
||||
},
|
||||
{
|
||||
Cell: expect.any(Function),
|
||||
Header: asciiKey,
|
||||
accessor: expect.any(Function),
|
||||
id: asciiKey,
|
||||
},
|
||||
{
|
||||
Cell: expect.any(Function),
|
||||
Header: unicodeKey,
|
||||
accessor: expect.any(Function),
|
||||
id: unicodeKey,
|
||||
},
|
||||
]);
|
||||
|
||||
hook.result.current.forEach((col: JsonObject) => {
|
||||
expect(col.accessor(newData[0])).toBe(newData[0][col.Header]);
|
||||
});
|
||||
|
||||
hook.result.current.forEach((col: JsonObject) => {
|
||||
expect(col.Cell({ value: newData[0].col01 })).toBe(BOOL_TRUE_DISPLAY);
|
||||
expect(col.Cell({ value: newData[0].col02 })).toBe(BOOL_FALSE_DISPLAY);
|
||||
expect(col.Cell({ value: newData[0].col03 })).toBe('secret');
|
||||
expect(col.Cell({ value: newData[0][asciiKey] })).toBe(asciiKey);
|
||||
expect(col.Cell({ value: newData[0][unicodeKey] })).toBe(unicodeKey);
|
||||
});
|
||||
|
||||
hook.result.current.forEach((col: JsonObject) => {
|
||||
expect(col.Cell({ value: newData[1].col01 })).toBe(BOOL_TRUE_DISPLAY);
|
||||
expect(col.Cell({ value: newData[1].col02 })).toBe(BOOL_FALSE_DISPLAY);
|
||||
expect(col.Cell({ value: newData[1].col03 })).toBe('undefined');
|
||||
expect(col.Cell({ value: newData[1][asciiKey] })).toBe(asciiKey);
|
||||
expect(col.Cell({ value: newData[1][unicodeKey] })).toBe(unicodeKey);
|
||||
});
|
||||
});
|
||||
|
||||
test('useTableColumns with options', () => {
|
||||
const hook = renderHook(() =>
|
||||
useTableColumns(all_columns, coltypes, data, undefined, [], {
|
||||
col01: { id: 'ID' },
|
||||
useTableColumns(colnames, coltypes, data, undefined, [], {
|
||||
col01: { Header: 'Header' },
|
||||
}),
|
||||
);
|
||||
expect(hook.result.current).toEqual([
|
||||
{
|
||||
Cell: expect.any(Function),
|
||||
Header: 'col01',
|
||||
Header: 'Header',
|
||||
accessor: expect.any(Function),
|
||||
id: 'ID',
|
||||
id: 'col01',
|
||||
},
|
||||
{
|
||||
Cell: expect.any(Function),
|
||||
@ -173,27 +154,45 @@ test('useTableColumns with options', () => {
|
||||
},
|
||||
{
|
||||
Cell: expect.any(Function),
|
||||
Header: asciiKey,
|
||||
Header: ASCII_KEY,
|
||||
accessor: expect.any(Function),
|
||||
id: asciiKey,
|
||||
id: ASCII_KEY,
|
||||
},
|
||||
{
|
||||
Cell: expect.any(Function),
|
||||
Header: unicodeKey,
|
||||
Header: UNICODE_KEY,
|
||||
accessor: expect.any(Function),
|
||||
id: unicodeKey,
|
||||
id: UNICODE_KEY,
|
||||
},
|
||||
{
|
||||
Cell: expect.any(Function),
|
||||
Header: expect.objectContaining({
|
||||
type: expect.objectContaining({
|
||||
name: 'DataTableTemporalHeaderCell',
|
||||
}),
|
||||
props: expect.objectContaining({
|
||||
originalFormattedTimeColumnIndex: -1,
|
||||
}),
|
||||
}),
|
||||
accessor: expect.any(Function),
|
||||
id: NUMTIME_KEY,
|
||||
},
|
||||
{
|
||||
Cell: expect.any(Function),
|
||||
Header: STRTIME_KEY,
|
||||
accessor: expect.any(Function),
|
||||
id: STRTIME_KEY,
|
||||
},
|
||||
]);
|
||||
hook.result.current.forEach((col: JsonObject) => {
|
||||
expect(col.accessor(data[0])).toBe(data[0][col.Header]);
|
||||
expect(col.accessor(data[0])).toBe(data[0][col.id]);
|
||||
});
|
||||
|
||||
hook.result.current.forEach((col: JsonObject) => {
|
||||
data.forEach(row => {
|
||||
expect(col.Cell({ value: row.col01 })).toBe(BOOL_TRUE_DISPLAY);
|
||||
expect(col.Cell({ value: row.col02 })).toBe(BOOL_FALSE_DISPLAY);
|
||||
expect(col.Cell({ value: row[asciiKey] })).toBe(asciiKey);
|
||||
expect(col.Cell({ value: row[unicodeKey] })).toBe(unicodeKey);
|
||||
expect(col.Cell({ value: row[col.id] })).toBe(
|
||||
expectedDisplayValues[col.id],
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -151,7 +151,7 @@ describe('DataTablesPane', () => {
|
||||
useRedux: true,
|
||||
initialState: {
|
||||
explore: {
|
||||
timeFormattedColumns: {
|
||||
originalFormattedTimeColumns: {
|
||||
'34__table': ['__timestamp'],
|
||||
},
|
||||
},
|
||||
@ -203,7 +203,7 @@ describe('DataTablesPane', () => {
|
||||
useRedux: true,
|
||||
initialState: {
|
||||
explore: {
|
||||
timeFormattedColumns: {
|
||||
originalFormattedTimeColumns: {
|
||||
'34__table': ['__timestamp'],
|
||||
},
|
||||
},
|
||||
|
@ -52,7 +52,7 @@ import {
|
||||
useTableColumns,
|
||||
} from 'src/explore/components/DataTableControl';
|
||||
import { applyFormattingToTabularData } from 'src/utils/common';
|
||||
import { useTimeFormattedColumns } from '../useTimeFormattedColumns';
|
||||
import { useOriginalFormattedTimeColumns } from '../useOriginalFormattedTimeColumns';
|
||||
|
||||
const RESULT_TYPES = {
|
||||
results: 'results' as const,
|
||||
@ -147,7 +147,8 @@ const DataTable = ({
|
||||
errorMessage,
|
||||
type,
|
||||
}: DataTableProps) => {
|
||||
const timeFormattedColumns = useTimeFormattedColumns(datasource);
|
||||
const originalFormattedTimeColumns =
|
||||
useOriginalFormattedTimeColumns(datasource);
|
||||
// this is to preserve the order of the columns, even if there are integer values,
|
||||
// while also only grabbing the first column's keys
|
||||
const columns = useTableColumns(
|
||||
@ -155,7 +156,7 @@ const DataTable = ({
|
||||
columnTypes,
|
||||
data,
|
||||
datasource,
|
||||
timeFormattedColumns,
|
||||
originalFormattedTimeColumns,
|
||||
);
|
||||
const filteredData = useFilteredTableData(filterText, data);
|
||||
|
||||
@ -210,10 +211,11 @@ const TableControls = ({
|
||||
columnNames: string[];
|
||||
isLoading: boolean;
|
||||
}) => {
|
||||
const timeFormattedColumns = useTimeFormattedColumns(datasourceId);
|
||||
const originalFormattedTimeColumns =
|
||||
useOriginalFormattedTimeColumns(datasourceId);
|
||||
const formattedData = useMemo(
|
||||
() => applyFormattingToTabularData(data, timeFormattedColumns),
|
||||
[data, timeFormattedColumns],
|
||||
() => applyFormattingToTabularData(data, originalFormattedTimeColumns),
|
||||
[data, originalFormattedTimeColumns],
|
||||
);
|
||||
return (
|
||||
<TableControlsWrapper>
|
||||
|
@ -19,9 +19,9 @@
|
||||
import { useSelector } from 'react-redux';
|
||||
import { ExplorePageState } from '../reducers/getInitialState';
|
||||
|
||||
export const useTimeFormattedColumns = (datasourceId?: string) =>
|
||||
export const useOriginalFormattedTimeColumns = (datasourceId?: string) =>
|
||||
useSelector<ExplorePageState, string[]>(state =>
|
||||
datasourceId
|
||||
? state.explore.timeFormattedColumns?.[datasourceId] ?? []
|
||||
? state.explore.originalFormattedTimeColumns?.[datasourceId] ?? []
|
||||
: [],
|
||||
);
|
@ -265,41 +265,51 @@ export default function exploreReducer(state = {}, action) {
|
||||
sliceName: action.slice.slice_name ?? state.sliceName,
|
||||
};
|
||||
},
|
||||
[actions.SET_TIME_FORMATTED_COLUMN]() {
|
||||
[actions.SET_ORIGINAL_FORMATTED_TIME_COLUMN]() {
|
||||
const { datasourceId, columnName } = action;
|
||||
const newTimeFormattedColumns = { ...state.timeFormattedColumns };
|
||||
const newTimeFormattedColumnsForDatasource = ensureIsArray(
|
||||
newTimeFormattedColumns[datasourceId],
|
||||
const newOriginalFormattedColumns = {
|
||||
...state.originalFormattedTimeColumns,
|
||||
};
|
||||
const newOriginalFormattedColumnsForDatasource = ensureIsArray(
|
||||
newOriginalFormattedColumns[datasourceId],
|
||||
).slice();
|
||||
|
||||
newTimeFormattedColumnsForDatasource.push(columnName);
|
||||
newTimeFormattedColumns[datasourceId] =
|
||||
newTimeFormattedColumnsForDatasource;
|
||||
newOriginalFormattedColumnsForDatasource.push(columnName);
|
||||
newOriginalFormattedColumns[datasourceId] =
|
||||
newOriginalFormattedColumnsForDatasource;
|
||||
setItem(
|
||||
LocalStorageKeys.explore__data_table_time_formatted_columns,
|
||||
newTimeFormattedColumns,
|
||||
LocalStorageKeys.explore__data_table_original_formatted_time_columns,
|
||||
newOriginalFormattedColumns,
|
||||
);
|
||||
return { ...state, timeFormattedColumns: newTimeFormattedColumns };
|
||||
return {
|
||||
...state,
|
||||
originalFormattedTimeColumns: newOriginalFormattedColumns,
|
||||
};
|
||||
},
|
||||
[actions.UNSET_TIME_FORMATTED_COLUMN]() {
|
||||
[actions.UNSET_ORIGINAL_FORMATTED_TIME_COLUMN]() {
|
||||
const { datasourceId, columnIndex } = action;
|
||||
const newTimeFormattedColumns = { ...state.timeFormattedColumns };
|
||||
const newTimeFormattedColumnsForDatasource = ensureIsArray(
|
||||
newTimeFormattedColumns[datasourceId],
|
||||
const newOriginalFormattedColumns = {
|
||||
...state.originalFormattedTimeColumns,
|
||||
};
|
||||
const newOriginalFormattedColumnsForDatasource = ensureIsArray(
|
||||
newOriginalFormattedColumns[datasourceId],
|
||||
).slice();
|
||||
|
||||
newTimeFormattedColumnsForDatasource.splice(columnIndex, 1);
|
||||
newTimeFormattedColumns[datasourceId] =
|
||||
newTimeFormattedColumnsForDatasource;
|
||||
newOriginalFormattedColumnsForDatasource.splice(columnIndex, 1);
|
||||
newOriginalFormattedColumns[datasourceId] =
|
||||
newOriginalFormattedColumnsForDatasource;
|
||||
|
||||
if (newTimeFormattedColumnsForDatasource.length === 0) {
|
||||
delete newTimeFormattedColumns[datasourceId];
|
||||
if (newOriginalFormattedColumnsForDatasource.length === 0) {
|
||||
delete newOriginalFormattedColumns[datasourceId];
|
||||
}
|
||||
setItem(
|
||||
LocalStorageKeys.explore__data_table_time_formatted_columns,
|
||||
newTimeFormattedColumns,
|
||||
LocalStorageKeys.explore__data_table_original_formatted_time_columns,
|
||||
newOriginalFormattedColumns,
|
||||
);
|
||||
return { ...state, timeFormattedColumns: newTimeFormattedColumns };
|
||||
return {
|
||||
...state,
|
||||
originalFormattedTimeColumns: newOriginalFormattedColumns,
|
||||
};
|
||||
},
|
||||
[actions.SET_FORCE_QUERY]() {
|
||||
return {
|
||||
|
@ -78,8 +78,8 @@ export default function getInitialState(
|
||||
initialFormData,
|
||||
) as ControlStateMapping,
|
||||
controlsTransferred: [],
|
||||
timeFormattedColumns: getItem(
|
||||
LocalStorageKeys.explore__data_table_time_formatted_columns,
|
||||
originalFormattedTimeColumns: getItem(
|
||||
LocalStorageKeys.explore__data_table_original_formatted_time_columns,
|
||||
{},
|
||||
),
|
||||
};
|
||||
|
@ -49,7 +49,7 @@ export enum LocalStorageKeys {
|
||||
* sqllab__is_autocomplete_enabled
|
||||
*/
|
||||
sqllab__is_autocomplete_enabled = 'sqllab__is_autocomplete_enabled',
|
||||
explore__data_table_time_formatted_columns = 'explore__data_table_time_formatted_columns',
|
||||
explore__data_table_original_formatted_time_columns = 'explore__data_table_original_formatted_time_columns',
|
||||
}
|
||||
|
||||
export type LocalStorageValues = {
|
||||
@ -63,7 +63,7 @@ export type LocalStorageValues = {
|
||||
homepage_collapse_state: string[];
|
||||
homepage_activity_filter: SetTabType | null;
|
||||
sqllab__is_autocomplete_enabled: boolean;
|
||||
explore__data_table_time_formatted_columns: Record<string, string[]>;
|
||||
explore__data_table_original_formatted_time_columns: Record<string, string[]>;
|
||||
};
|
||||
|
||||
export function getItem<K extends LocalStorageKeys>(
|
||||
|
Loading…
Reference in New Issue
Block a user