From 57311c7fc1c25680c601b58859f7b3bc0005c879 Mon Sep 17 00:00:00 2001 From: "tri.quan" Date: Tue, 23 Apr 2024 21:36:00 +0700 Subject: [PATCH] Remove unused code --- .../src/katalon/DataTable/TableChart.tsx | 209 +++++++ .../katalon/DataTable/TestRunDecorators.tsx | 249 ++++++++ .../src => DataTable}/images/Table.jpg | Bin .../src => DataTable}/images/Table2.jpg | Bin .../src => DataTable}/images/Table3.jpg | Bin .../src => DataTable}/images/thumbnail.png | Bin .../images/thumbnailLarge.png | Bin .../{chart-table/src => DataTable}/index.ts | 4 - .../src => DataTable}/transformProps.ts | 0 .../{chart-table/src => DataTable}/types.ts | 0 .../utils/DateWithFormatter.ts | 0 .../src => DataTable}/utils/extent.ts | 0 .../src => }/DataTable/utils/externalAPIs.ts | 0 .../src => DataTable}/utils/formatValue.ts | 0 .../src => DataTable}/utils/isEqualColumns.ts | 0 .../chart-table/src/DataTable/DataTable.tsx | 397 ------------- .../chart-table/src/DataTable/README.md | 25 - .../src/DataTable/components/GlobalFilter.tsx | 82 --- .../src/DataTable/components/Pagination.tsx | 121 ---- .../DataTable/components/SelectPageSize.tsx | 100 ---- .../src/DataTable/hooks/useSticky.tsx | 421 ------------- .../chart-table/src/DataTable/index.tsx | 25 - .../src/DataTable/types/react-table.d.ts | 116 ---- .../src/DataTable/utils/getScrollBarSize.ts | 48 -- .../src/DataTable/utils/needScrollBar.ts | 39 -- .../utils/sortAlphanumericCaseInsensitive.ts | 37 -- .../src/DataTable/utils/useAsyncState.ts | 51 -- .../src/DataTable/utils/useMountedMemo.ts | 40 -- .../src/katalon/chart-table/src/Styles.tsx | 115 ---- .../katalon/chart-table/src/TableChart.tsx | 429 -------------- .../src/katalon/chart-table/src/buildQuery.ts | 227 ------- .../src/katalon/chart-table/src/consts.ts | 32 - .../katalon/chart-table/src/controlPanel.tsx | 557 ------------------ .../src/katalon/chart-table/src/i18n.ts | 66 --- .../chart-table/test/TableChart.test.tsx | 304 ---------- .../chart-table/test/buildQuery.test.ts | 125 ---- .../src/katalon/chart-table/test/enzyme.tsx | 67 --- .../sortAlphanumericCaseInsensitive.test.ts | 243 -------- .../src/katalon/chart-table/test/testData.ts | 230 -------- .../katalon/chart-table/test/tsconfig.json | 19 - .../katalon/chart-table/types/external.d.ts | 22 - .../src/visualizations/presets/MainPreset.js | 2 +- 42 files changed, 459 insertions(+), 3943 deletions(-) create mode 100644 superset-frontend/src/katalon/DataTable/TableChart.tsx create mode 100644 superset-frontend/src/katalon/DataTable/TestRunDecorators.tsx rename superset-frontend/src/katalon/{chart-table/src => DataTable}/images/Table.jpg (100%) rename superset-frontend/src/katalon/{chart-table/src => DataTable}/images/Table2.jpg (100%) rename superset-frontend/src/katalon/{chart-table/src => DataTable}/images/Table3.jpg (100%) rename superset-frontend/src/katalon/{chart-table/src => DataTable}/images/thumbnail.png (100%) rename superset-frontend/src/katalon/{chart-table/src => DataTable}/images/thumbnailLarge.png (100%) rename superset-frontend/src/katalon/{chart-table/src => DataTable}/index.ts (94%) rename superset-frontend/src/katalon/{chart-table/src => DataTable}/transformProps.ts (100%) rename superset-frontend/src/katalon/{chart-table/src => DataTable}/types.ts (100%) rename superset-frontend/src/katalon/{chart-table/src => DataTable}/utils/DateWithFormatter.ts (100%) rename superset-frontend/src/katalon/{chart-table/src => DataTable}/utils/extent.ts (100%) rename superset-frontend/src/katalon/{chart-table/src => }/DataTable/utils/externalAPIs.ts (100%) rename superset-frontend/src/katalon/{chart-table/src => DataTable}/utils/formatValue.ts (100%) rename superset-frontend/src/katalon/{chart-table/src => DataTable}/utils/isEqualColumns.ts (100%) delete mode 100644 superset-frontend/src/katalon/chart-table/src/DataTable/DataTable.tsx delete mode 100644 superset-frontend/src/katalon/chart-table/src/DataTable/README.md delete mode 100644 superset-frontend/src/katalon/chart-table/src/DataTable/components/GlobalFilter.tsx delete mode 100644 superset-frontend/src/katalon/chart-table/src/DataTable/components/Pagination.tsx delete mode 100644 superset-frontend/src/katalon/chart-table/src/DataTable/components/SelectPageSize.tsx delete mode 100644 superset-frontend/src/katalon/chart-table/src/DataTable/hooks/useSticky.tsx delete mode 100644 superset-frontend/src/katalon/chart-table/src/DataTable/index.tsx delete mode 100644 superset-frontend/src/katalon/chart-table/src/DataTable/types/react-table.d.ts delete mode 100644 superset-frontend/src/katalon/chart-table/src/DataTable/utils/getScrollBarSize.ts delete mode 100644 superset-frontend/src/katalon/chart-table/src/DataTable/utils/needScrollBar.ts delete mode 100644 superset-frontend/src/katalon/chart-table/src/DataTable/utils/sortAlphanumericCaseInsensitive.ts delete mode 100644 superset-frontend/src/katalon/chart-table/src/DataTable/utils/useAsyncState.ts delete mode 100644 superset-frontend/src/katalon/chart-table/src/DataTable/utils/useMountedMemo.ts delete mode 100644 superset-frontend/src/katalon/chart-table/src/Styles.tsx delete mode 100644 superset-frontend/src/katalon/chart-table/src/TableChart.tsx delete mode 100644 superset-frontend/src/katalon/chart-table/src/buildQuery.ts delete mode 100644 superset-frontend/src/katalon/chart-table/src/consts.ts delete mode 100644 superset-frontend/src/katalon/chart-table/src/controlPanel.tsx delete mode 100644 superset-frontend/src/katalon/chart-table/src/i18n.ts delete mode 100644 superset-frontend/src/katalon/chart-table/test/TableChart.test.tsx delete mode 100644 superset-frontend/src/katalon/chart-table/test/buildQuery.test.ts delete mode 100644 superset-frontend/src/katalon/chart-table/test/enzyme.tsx delete mode 100644 superset-frontend/src/katalon/chart-table/test/sortAlphanumericCaseInsensitive.test.ts delete mode 100644 superset-frontend/src/katalon/chart-table/test/testData.ts delete mode 100644 superset-frontend/src/katalon/chart-table/test/tsconfig.json delete mode 100644 superset-frontend/src/katalon/chart-table/types/external.d.ts diff --git a/superset-frontend/src/katalon/DataTable/TableChart.tsx b/superset-frontend/src/katalon/DataTable/TableChart.tsx new file mode 100644 index 0000000000000..265548ab5cc33 --- /dev/null +++ b/superset-frontend/src/katalon/DataTable/TableChart.tsx @@ -0,0 +1,209 @@ +/* eslint-disable theme-colors/no-literal-colors */ + +import React from 'react'; +import { DataRecord } from '@superset-ui/core'; +import { makeStyles } from '@mui/styles'; +import { DataGrid, GridColDef } from '@katalon-studio/katalon-ui/v2'; +import { TableChartTransformedProps } from './types'; +import { + statusDecorator, + IDDecorator, + nameDecorator, + profileDecorator, + durationDecorator, + environmentDecorator, + timeStartedDecorator, + testResultStatusDecorator, + configurationDecorator, + executorDecorator, +} from './TestRunDecorators'; + +const useStyles = makeStyles(() => ({ + tableHeader: { + backgroundColor: '#f7f9fb', + '& .MuiDataGrid-columnHeaderTitle': { + color: '#46474d', + fontSize: '11px', + fontWeight: 700, + }, + }, + firstColumnHeader: { + backgroundColor: '#f7f9fb', + '& .MuiDataGrid-columnHeaderTitle': { + color: '#46474d', + fontSize: '11px', + fontWeight: 700, + paddingLeft: '16px', + }, + }, + lastColumnHeader: { + backgroundColor: '#f7f9fb', + '& .MuiDataGrid-columnHeaderTitle': { + color: '#46474d', + fontSize: '11px', + fontWeight: 700, + paddingRight: '16px', + }, + }, +})); + +const PAGE_SIZE = 10; + +const formatData = (data: any) => + data.map((row: any) => { + const { + configuration, + profile, + environment, + executor, + test_result_status, + run_configuration_name, + test_suite_collection_name, + test_suite_name, + ...rest + } = row; + + const parseJSON = (value: any) => { + try { + return JSON.parse(value); + } catch (error) { + console.error(error); + return value; + } + }; + + const parsedConfiguration = parseJSON(configuration); + const parsedProfile = parseJSON(profile); + const parsedEnvironment = parseJSON(environment); + const parsedExecutor = parseJSON(executor); + const parsedTestResultStatus = parseJSON(test_result_status); + + let name: string[] = []; + if (run_configuration_name) { + name = parseJSON(run_configuration_name); + } else if (test_suite_collection_name) { + name = parseJSON(test_suite_collection_name); + } else if (test_suite_name) { + name = parseJSON(test_suite_name); + } + + return { + ...rest, + configuration: parsedConfiguration, + profile: parsedProfile, + environment: parsedEnvironment, + name, + executor: parsedExecutor, + test_result_status: parsedTestResultStatus, + }; + }); + +export default function TableChart( + props: TableChartTransformedProps, +) { + // TODO: Only use the decorators for test_run_data_table_dataset dataset + + const classes = useStyles(); + + const { data } = props; + console.log('data', data); + + const formattedData = formatData(data); + console.log('FORMATTED DATA', formattedData); + + const tableColumns: GridColDef[] = [ + { + field: 'status', + headerName: 'STATUS', + flex: 0.2, + headerAlign: 'center', + headerClassName: classes.tableHeader, + renderCell: cell => statusDecorator(cell.value), + }, + { + field: 'id', + headerName: 'ID', + flex: 0.3, + headerClassName: classes.firstColumnHeader, + renderCell: cell => IDDecorator(cell.value), + }, + { + field: 'name', + headerName: 'NAME', + flex: 1.3, + headerClassName: classes.tableHeader, + renderCell: cell => nameDecorator(cell.value), + }, + { + field: 'profile', + headerName: 'PROFILE', + flex: 0.5, + headerClassName: classes.tableHeader, + renderCell: cell => profileDecorator(cell.value), + }, + { + field: 'duration', + headerName: 'DURATION', + flex: 0.5, + headerClassName: classes.tableHeader, + renderCell: cell => durationDecorator(cell.value), + }, + { + field: 'environment', + headerName: 'ENVIRONMENT', + flex: 0.5, + headerClassName: classes.tableHeader, + renderCell: cell => environmentDecorator(cell.value), + }, + { + field: 'time_started', + headerName: 'TIME STARTED', + flex: 0.5, + headerClassName: classes.tableHeader, + renderCell: cell => timeStartedDecorator(cell.value), + }, + { + field: 'test_result_status', + headerName: 'TEST RESULT STATUS', + flex: 0.7, + headerClassName: classes.tableHeader, + renderCell: cell => testResultStatusDecorator(cell.value), + }, + { + field: 'configuration', + headerName: 'CONFIGURATION', + flex: 0.6, + headerClassName: classes.tableHeader, + renderCell: cell => configurationDecorator(cell.value), + }, + { + field: 'executor', + headerName: 'EXECUTOR', + flex: 0.5, + headerClassName: classes.lastColumnHeader, + renderCell: cell => executorDecorator(cell.value), + }, + ]; + + return ( + + ); +} diff --git a/superset-frontend/src/katalon/DataTable/TestRunDecorators.tsx b/superset-frontend/src/katalon/DataTable/TestRunDecorators.tsx new file mode 100644 index 0000000000000..30e7a2b2f38e4 --- /dev/null +++ b/superset-frontend/src/katalon/DataTable/TestRunDecorators.tsx @@ -0,0 +1,249 @@ +/* eslint-disable theme-colors/no-literal-colors */ + +import React from 'react'; +import { getUrlParam } from 'src/utils/urlUtils'; +import { URL_PARAMS } from 'src/constants'; +import moment from 'moment'; +import Config from '../../../config'; + +const statusIconMapper = { + PASSED: '/static/assets/images/katalon/status-passed.svg', + FAILED: '/static/assets/images/katalon/status-failed.svg', + INCOMPLETE: '/static/assets/images/katalon/status-incomplete.svg', + ERROR: '/static/assets/images/katalon/status-error.svg', +}; + +const osIconMapper = (name: string) => { + if (name.toLowerCase().includes('win')) { + return '/static/assets/images/katalon/windows.svg'; + } + if (name.toLowerCase().includes('mac')) { + return '/static/assets/images/katalon/macos.svg'; + } + if (name.toLowerCase().includes('linux')) { + return '/static/assets/images/katalon/linux.svg'; + } + if (name.toLowerCase().includes('android')) { + return '/static/assets/images/katalon/macos.svg'; // TODO: icon for Android + } + if (name.toLowerCase().includes('ios')) { + return '/static/assets/images/katalon/macos.svg'; // TODO: icon for IOS + } + return ''; +}; + +const browserIconMapper = (name: string) => { + if (name.toLowerCase().includes('chrome')) { + return '/static/assets/images/katalon/chrome.svg'; + } + if (name.toLowerCase().includes('firefox')) { + return '/static/assets/images/katalon/firefox.svg'; + } + if (name.toLowerCase().includes('edge')) { + return '/static/assets/images/katalon/edge.svg'; + } + if (name.toLowerCase().includes('safari')) { + return '/static/assets/images/katalon/edge.svg'; // TODO: icon for Safari + } + return ''; +}; + +const statusDecorator = (value: string) => ( +
+ icon +
+); + +const IDDecorator = (id: string) => { + const projectId = getUrlParam(URL_PARAMS.projectId); + const masterAppHost = Config.masterApp; + + return ( + + {id} + + ); +}; + +const nameDecorator = (nameList: string[]) => { + if (!nameList || nameList.length === 0) return null; + + return ( + + {nameList[0]} + + ); +}; + +const profileDecorator = (profiles: string[]) => { + if (!profiles || profiles.length === 0) return null; + + const decoratedProfiles = profiles.join(', '); + return ( +
+ icon + {decoratedProfiles} +
+ ); +}; + +const durationDecorator = (milliseconds: number) => { + let decoratedDuration = moment.utc(milliseconds).format('HH[h] mm[m] ss[s]'); + decoratedDuration = decoratedDuration.replace(/00[hms]/g, '').trim(); + + return {decoratedDuration}; +}; + +const environmentDecorator = (environmentList: any[]) => { + // if (!environmentList || environmentList.length === 0) return null; + + const list = [ + { os: 'Windows', browser: 'Edge' }, + { os: 'Windows', browser: 'Chrome' }, + { os: 'MacOS', browser: 'Chrome' }, + ]; + + return ( +
+ {list.slice(0, 2).map((environment, index) => ( +
+ {index === 1 && |} + icon + icon +
+ ))} + {list.length > 2 && +{list.length - 2}} +
+ ); +}; + +const timeStartedDecorator = (date: Date) => { + const formattedDate = moment(date).format('DD/MM/YYYY HH:mm'); + return {formattedDate}; +}; + +const testResultStatusDecorator = (testResultStatus: any) => { + const { + totalPassed, + totalFailed, + totalError, + totalIncomplete, + totalSkipped, + } = testResultStatus; + return ( +
+ + {totalPassed} / {totalFailed} / {totalError} / {totalIncomplete} /{' '} + {totalSkipped} + +
+ ); +}; + +const configurationDecorator = (configurationList: string[]) => { + if (!configurationList || configurationList.length === 0) return null; + + const hashedNumbers: string = configurationList + .map(configuration => `#${configuration}`) + .join(', '); + return {hashedNumbers}; +}; + +const executorDecorator = (executor: any) => { + if (!executor) return null; + + const { name, avatar } = executor; + const executorAvatar = avatar + ? `https://katalon-testops-qa-testops-bucket.s3.amazonaws.com/${avatar}` // TODO: Update the URL based on environment + : 'https://katalon-testops.s3.amazonaws.com/image/icon/defaultAvatar.png'; + + return ( +
+ avatar + {name} +
+ ); +}; + +export { + statusDecorator, + IDDecorator, + nameDecorator, + profileDecorator, + durationDecorator, + environmentDecorator, + timeStartedDecorator, + testResultStatusDecorator, + configurationDecorator, + executorDecorator, +}; diff --git a/superset-frontend/src/katalon/chart-table/src/images/Table.jpg b/superset-frontend/src/katalon/DataTable/images/Table.jpg similarity index 100% rename from superset-frontend/src/katalon/chart-table/src/images/Table.jpg rename to superset-frontend/src/katalon/DataTable/images/Table.jpg diff --git a/superset-frontend/src/katalon/chart-table/src/images/Table2.jpg b/superset-frontend/src/katalon/DataTable/images/Table2.jpg similarity index 100% rename from superset-frontend/src/katalon/chart-table/src/images/Table2.jpg rename to superset-frontend/src/katalon/DataTable/images/Table2.jpg diff --git a/superset-frontend/src/katalon/chart-table/src/images/Table3.jpg b/superset-frontend/src/katalon/DataTable/images/Table3.jpg similarity index 100% rename from superset-frontend/src/katalon/chart-table/src/images/Table3.jpg rename to superset-frontend/src/katalon/DataTable/images/Table3.jpg diff --git a/superset-frontend/src/katalon/chart-table/src/images/thumbnail.png b/superset-frontend/src/katalon/DataTable/images/thumbnail.png similarity index 100% rename from superset-frontend/src/katalon/chart-table/src/images/thumbnail.png rename to superset-frontend/src/katalon/DataTable/images/thumbnail.png diff --git a/superset-frontend/src/katalon/chart-table/src/images/thumbnailLarge.png b/superset-frontend/src/katalon/DataTable/images/thumbnailLarge.png similarity index 100% rename from superset-frontend/src/katalon/chart-table/src/images/thumbnailLarge.png rename to superset-frontend/src/katalon/DataTable/images/thumbnailLarge.png diff --git a/superset-frontend/src/katalon/chart-table/src/index.ts b/superset-frontend/src/katalon/DataTable/index.ts similarity index 94% rename from superset-frontend/src/katalon/chart-table/src/index.ts rename to superset-frontend/src/katalon/DataTable/index.ts index 3d7b1dcea7906..6fe92d98b8883 100644 --- a/superset-frontend/src/katalon/chart-table/src/index.ts +++ b/superset-frontend/src/katalon/DataTable/index.ts @@ -22,8 +22,6 @@ import thumbnail from './images/thumbnail.png'; import example1 from './images/Table.jpg'; import example2 from './images/Table2.jpg'; import example3 from './images/Table3.jpg'; -import controlPanel from './controlPanel'; -import buildQuery from './buildQuery'; import { TableChartFormData, TableChartProps } from './types'; // must export something for the module to be exist in dev mode @@ -65,8 +63,6 @@ export default class TableChartPlugin extends ChartPlugin< loadChart: () => import('./TableChart'), metadata, transformProps, - controlPanel, - buildQuery, }); } } diff --git a/superset-frontend/src/katalon/chart-table/src/transformProps.ts b/superset-frontend/src/katalon/DataTable/transformProps.ts similarity index 100% rename from superset-frontend/src/katalon/chart-table/src/transformProps.ts rename to superset-frontend/src/katalon/DataTable/transformProps.ts diff --git a/superset-frontend/src/katalon/chart-table/src/types.ts b/superset-frontend/src/katalon/DataTable/types.ts similarity index 100% rename from superset-frontend/src/katalon/chart-table/src/types.ts rename to superset-frontend/src/katalon/DataTable/types.ts diff --git a/superset-frontend/src/katalon/chart-table/src/utils/DateWithFormatter.ts b/superset-frontend/src/katalon/DataTable/utils/DateWithFormatter.ts similarity index 100% rename from superset-frontend/src/katalon/chart-table/src/utils/DateWithFormatter.ts rename to superset-frontend/src/katalon/DataTable/utils/DateWithFormatter.ts diff --git a/superset-frontend/src/katalon/chart-table/src/utils/extent.ts b/superset-frontend/src/katalon/DataTable/utils/extent.ts similarity index 100% rename from superset-frontend/src/katalon/chart-table/src/utils/extent.ts rename to superset-frontend/src/katalon/DataTable/utils/extent.ts diff --git a/superset-frontend/src/katalon/chart-table/src/DataTable/utils/externalAPIs.ts b/superset-frontend/src/katalon/DataTable/utils/externalAPIs.ts similarity index 100% rename from superset-frontend/src/katalon/chart-table/src/DataTable/utils/externalAPIs.ts rename to superset-frontend/src/katalon/DataTable/utils/externalAPIs.ts diff --git a/superset-frontend/src/katalon/chart-table/src/utils/formatValue.ts b/superset-frontend/src/katalon/DataTable/utils/formatValue.ts similarity index 100% rename from superset-frontend/src/katalon/chart-table/src/utils/formatValue.ts rename to superset-frontend/src/katalon/DataTable/utils/formatValue.ts diff --git a/superset-frontend/src/katalon/chart-table/src/utils/isEqualColumns.ts b/superset-frontend/src/katalon/DataTable/utils/isEqualColumns.ts similarity index 100% rename from superset-frontend/src/katalon/chart-table/src/utils/isEqualColumns.ts rename to superset-frontend/src/katalon/DataTable/utils/isEqualColumns.ts diff --git a/superset-frontend/src/katalon/chart-table/src/DataTable/DataTable.tsx b/superset-frontend/src/katalon/chart-table/src/DataTable/DataTable.tsx deleted file mode 100644 index 6c5123806f94d..0000000000000 --- a/superset-frontend/src/katalon/chart-table/src/DataTable/DataTable.tsx +++ /dev/null @@ -1,397 +0,0 @@ -/** - * 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. - */ -import React, { - useCallback, - useRef, - ReactNode, - HTMLProps, - MutableRefObject, - CSSProperties, -} from 'react'; -import { - useTable, - usePagination, - useSortBy, - useGlobalFilter, - useColumnOrder, - PluginHook, - TableOptions, - FilterType, - IdType, - Row, -} from 'react-table'; -import { matchSorter, rankings } from 'match-sorter'; -import { typedMemo, usePrevious } from '@superset-ui/core'; -import { isEqual } from 'lodash'; -import GlobalFilter, { GlobalFilterProps } from './components/GlobalFilter'; -import SelectPageSize, { - SelectPageSizeProps, - SizeOption, -} from './components/SelectPageSize'; -import SimplePagination from './components/Pagination'; -import useSticky from './hooks/useSticky'; -import { PAGE_SIZE_OPTIONS } from '../consts'; -import { sortAlphanumericCaseInsensitive } from './utils/sortAlphanumericCaseInsensitive'; - -export interface DataTableProps extends TableOptions { - tableClassName?: string; - searchInput?: boolean | GlobalFilterProps['searchInput']; - selectPageSize?: boolean | SelectPageSizeProps['selectRenderer']; - pageSizeOptions?: SizeOption[]; // available page size options - maxPageItemCount?: number; - hooks?: PluginHook[]; // any additional hooks - width?: string | number; - height?: string | number; - serverPagination?: boolean; - onServerPaginationChange: (pageNumber: number, pageSize: number) => void; - serverPaginationData: { pageSize?: number; currentPage?: number }; - pageSize?: number; - noResults?: string | ((filterString: string) => ReactNode); - sticky?: boolean; - rowCount: number; - wrapperRef?: MutableRefObject; - onColumnOrderChange: () => void; -} - -export interface RenderHTMLCellProps extends HTMLProps { - cellContent: ReactNode; -} - -const sortTypes = { - alphanumeric: sortAlphanumericCaseInsensitive, -}; - -// Be sure to pass our updateMyData and the skipReset option -export default typedMemo(function DataTable({ - tableClassName, - columns, - data, - serverPaginationData, - width: initialWidth = '100%', - height: initialHeight = 300, - pageSize: initialPageSize = 0, - initialState: initialState_ = {}, - pageSizeOptions = PAGE_SIZE_OPTIONS, - maxPageItemCount = 9, - sticky: doSticky, - searchInput = true, - onServerPaginationChange, - rowCount, - selectPageSize, - noResults: noResultsText = 'No data found', - hooks, - serverPagination, - wrapperRef: userWrapperRef, - onColumnOrderChange, - ...moreUseTableOptions -}: DataTableProps): JSX.Element { - const tableHooks: PluginHook[] = [ - useGlobalFilter, - useSortBy, - usePagination, - useColumnOrder, - doSticky ? useSticky : [], - hooks || [], - ].flat(); - const columnNames = Object.keys(data?.[0] || {}); - const previousColumnNames = usePrevious(columnNames); - const resultsSize = serverPagination ? rowCount : data.length; - const sortByRef = useRef([]); // cache initial `sortby` so sorting doesn't trigger page reset - const pageSizeRef = useRef([initialPageSize, resultsSize]); - const hasPagination = initialPageSize > 0 && resultsSize > 0; // pageSize == 0 means no pagination - const hasGlobalControl = hasPagination || !!searchInput; - const initialState = { - ...initialState_, - // zero length means all pages, the `usePagination` plugin does not - // understand pageSize = 0 - sortBy: sortByRef.current, - pageSize: initialPageSize > 0 ? initialPageSize : resultsSize || 10, - }; - const defaultWrapperRef = useRef(null); - const globalControlRef = useRef(null); - const paginationRef = useRef(null); - const wrapperRef = userWrapperRef || defaultWrapperRef; - const paginationData = JSON.stringify(serverPaginationData); - - const defaultGetTableSize = useCallback(() => { - if (wrapperRef.current) { - // `initialWidth` and `initialHeight` could be also parameters like `100%` - // `Number` returns `NaN` on them, then we fallback to computed size - const width = Number(initialWidth) || wrapperRef.current.clientWidth; - const height = - (Number(initialHeight) || wrapperRef.current.clientHeight) - - (globalControlRef.current?.clientHeight || 0) - - (paginationRef.current?.clientHeight || 0); - return { width, height }; - } - return undefined; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [ - initialHeight, - initialWidth, - wrapperRef, - hasPagination, - hasGlobalControl, - paginationRef, - resultsSize, - paginationData, - ]); - - const defaultGlobalFilter: FilterType = useCallback( - (rows: Row[], columnIds: IdType[], filterValue: string) => { - // allow searching by "col1_value col2_value" - const joinedString = (row: Row) => - columnIds.map(x => row.values[x]).join(' '); - return matchSorter(rows, filterValue, { - keys: [...columnIds, joinedString], - threshold: rankings.ACRONYM, - }) as typeof rows; - }, - [], - ); - - const { - getTableProps, - getTableBodyProps, - prepareRow, - headerGroups, - footerGroups, - page, - pageCount, - gotoPage, - preGlobalFilteredRows, - setGlobalFilter, - setPageSize: setPageSize_, - wrapStickyTable, - setColumnOrder, - allColumns, - state: { pageIndex, pageSize, globalFilter: filterValue, sticky = {} }, - } = useTable( - { - columns, - data, - initialState, - getTableSize: defaultGetTableSize, - globalFilter: defaultGlobalFilter, - sortTypes, - autoResetSortBy: !isEqual(columnNames, previousColumnNames), - ...moreUseTableOptions, - }, - ...tableHooks, - ); - // make setPageSize accept 0 - const setPageSize = (size: number) => { - if (serverPagination) { - onServerPaginationChange(0, size); - } - // keep the original size if data is empty - if (size || resultsSize !== 0) { - setPageSize_(size === 0 ? resultsSize : size); - } - }; - - const noResults = - typeof noResultsText === 'function' - ? noResultsText(filterValue as string) - : noResultsText; - - const getNoResults = () =>
{noResults}
; - - if (!columns || columns.length === 0) { - return ( - wrapStickyTable ? wrapStickyTable(getNoResults) : getNoResults() - ) as JSX.Element; - } - - const shouldRenderFooter = columns.some(x => !!x.Footer); - - let columnBeingDragged = -1; - - const onDragStart = (e: React.DragEvent) => { - const el = e.target as HTMLTableCellElement; - columnBeingDragged = allColumns.findIndex( - col => col.id === el.dataset.columnName, - ); - e.dataTransfer.setData('text/plain', `${columnBeingDragged}`); - }; - - const onDrop = (e: React.DragEvent) => { - const el = e.target as HTMLTableCellElement; - const newPosition = allColumns.findIndex( - col => col.id === el.dataset.columnName, - ); - - if (newPosition !== -1) { - const currentCols = allColumns.map(c => c.id); - const colToBeMoved = currentCols.splice(columnBeingDragged, 1); - currentCols.splice(newPosition, 0, colToBeMoved[0]); - setColumnOrder(currentCols); - // toggle value in TableChart to trigger column width recalc - onColumnOrderChange(); - } - e.preventDefault(); - }; - - const renderTable = () => ( - - - {headerGroups.map(headerGroup => { - const { key: headerGroupKey, ...headerGroupProps } = - headerGroup.getHeaderGroupProps(); - return ( - - {headerGroup.headers.map(column => - column.render('Header', { - key: column.id, - ...column.getSortByToggleProps(), - onDragStart, - onDrop, - }), - )} - - ); - })} - - - {page && page.length > 0 ? ( - page.map(row => { - prepareRow(row); - const { key: rowKey, ...rowProps } = row.getRowProps(); - return ( - - {row.cells.map(cell => - cell.render('Cell', { key: cell.column.id }), - )} - - ); - }) - ) : ( - - - - )} - - {shouldRenderFooter && ( - - {footerGroups.map(footerGroup => { - const { key: footerGroupKey, ...footerGroupProps } = - footerGroup.getHeaderGroupProps(); - return ( - - {footerGroup.headers.map(column => - column.render('Footer', { key: column.id }), - )} - - ); - })} - - )} -
- {noResults} -
- ); - - // force update the pageSize when it's been update from the initial state - if ( - pageSizeRef.current[0] !== initialPageSize || - // when initialPageSize stays as zero, but total number of records changed, - // we'd also need to update page size - (initialPageSize === 0 && pageSizeRef.current[1] !== resultsSize) - ) { - pageSizeRef.current = [initialPageSize, resultsSize]; - setPageSize(initialPageSize); - } - - const paginationStyle: CSSProperties = sticky.height - ? {} - : { visibility: 'hidden' }; - - let resultPageCount = pageCount; - let resultCurrentPageSize = pageSize; - let resultCurrentPage = pageIndex; - let resultOnPageChange: (page: number) => void = gotoPage; - if (serverPagination) { - const serverPageSize = serverPaginationData?.pageSize ?? initialPageSize; - resultPageCount = Math.ceil(rowCount / serverPageSize); - if (!Number.isFinite(resultPageCount)) { - resultPageCount = 0; - } - resultCurrentPageSize = serverPageSize; - const foundPageSizeIndex = pageSizeOptions.findIndex( - ([option]) => option >= resultCurrentPageSize, - ); - if (foundPageSizeIndex === -1) { - resultCurrentPageSize = 0; - } - resultCurrentPage = serverPaginationData?.currentPage ?? 0; - resultOnPageChange = (pageNumber: number) => - onServerPaginationChange(pageNumber, serverPageSize); - } - return ( -
- {hasGlobalControl ? ( -
-
-
- {hasPagination ? ( - - ) : null} -
- {searchInput ? ( -
- - searchInput={ - typeof searchInput === 'boolean' ? undefined : searchInput - } - preGlobalFilteredRows={preGlobalFilteredRows} - setGlobalFilter={setGlobalFilter} - filterValue={filterValue} - /> -
- ) : null} -
-
- ) : null} - {wrapStickyTable ? wrapStickyTable(renderTable) : renderTable()} - {hasPagination && resultPageCount > 1 ? ( - - ) : null} -
- ); -}); diff --git a/superset-frontend/src/katalon/chart-table/src/DataTable/README.md b/superset-frontend/src/katalon/chart-table/src/DataTable/README.md deleted file mode 100644 index 496c63b7702f9..0000000000000 --- a/superset-frontend/src/katalon/chart-table/src/DataTable/README.md +++ /dev/null @@ -1,25 +0,0 @@ - - -# Superset UI Data Table - -Reusable data table based on [react-table](https://github.com/tannerlinsley/react-table), with -built-in support for sorting, filtering, and pagination. - -Intended to be used as a standalone UI component in the future. diff --git a/superset-frontend/src/katalon/chart-table/src/DataTable/components/GlobalFilter.tsx b/superset-frontend/src/katalon/chart-table/src/DataTable/components/GlobalFilter.tsx deleted file mode 100644 index 8e36905ee8526..0000000000000 --- a/superset-frontend/src/katalon/chart-table/src/DataTable/components/GlobalFilter.tsx +++ /dev/null @@ -1,82 +0,0 @@ -/** - * 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. - */ -import React, { ComponentType, ChangeEventHandler } from 'react'; -import { Row, FilterValue } from 'react-table'; -import useAsyncState from '../utils/useAsyncState'; - -export interface SearchInputProps { - count: number; - value: string; - onChange: ChangeEventHandler; -} - -export interface GlobalFilterProps { - preGlobalFilteredRows: Row[]; - // filter value cannot be `undefined` otherwise React will report component - // control type undefined error - filterValue: string; - setGlobalFilter: (filterValue: FilterValue) => void; - searchInput?: ComponentType; -} - -function DefaultSearchInput({ count, value, onChange }: SearchInputProps) { - return ( - - Search{' '} - - - ); -} - -export default (React.memo as (fn: T) => T)(function GlobalFilter< - D extends object, ->({ - preGlobalFilteredRows, - filterValue = '', - searchInput, - setGlobalFilter, -}: GlobalFilterProps) { - const count = preGlobalFilteredRows.length; - const [value, setValue] = useAsyncState( - filterValue, - (newValue: string) => { - setGlobalFilter(newValue || undefined); - }, - 200, - ); - - const SearchInput = searchInput || DefaultSearchInput; - - return ( - { - const target = e.target as HTMLInputElement; - e.preventDefault(); - setValue(target.value); - }} - /> - ); -}); diff --git a/superset-frontend/src/katalon/chart-table/src/DataTable/components/Pagination.tsx b/superset-frontend/src/katalon/chart-table/src/DataTable/components/Pagination.tsx deleted file mode 100644 index 8d7e81ac1fef6..0000000000000 --- a/superset-frontend/src/katalon/chart-table/src/DataTable/components/Pagination.tsx +++ /dev/null @@ -1,121 +0,0 @@ -/** - * 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. - */ -import React, { CSSProperties, forwardRef } from 'react'; - -export interface PaginationProps { - pageCount: number; // number of pages - currentPage?: number; // index of current page, zero-based - maxPageItemCount?: number; - ellipsis?: string; // content for ellipsis item - onPageChange: (page: number) => void; // `page` is zero-based - style?: CSSProperties; -} - -// first, ..., prev, current, next, ..., last -const MINIMAL_PAGE_ITEM_COUNT = 7; - -/** - * Generate numeric page items around current page. - * - Always include first and last page - * - Add ellipsis if needed - */ -export function generatePageItems( - total: number, - current: number, - width: number, -) { - if (width < MINIMAL_PAGE_ITEM_COUNT) { - throw new Error( - `Must allow at least ${MINIMAL_PAGE_ITEM_COUNT} page items`, - ); - } - if (width % 2 === 0) { - throw new Error(`Must allow odd number of page items`); - } - if (total < width) { - return [...new Array(total).keys()]; - } - const left = Math.max( - 0, - Math.min(total - width, current - Math.floor(width / 2)), - ); - const items: (string | number)[] = new Array(width); - for (let i = 0; i < width; i += 1) { - items[i] = i + left; - } - // replace non-ending items with placeholders - if (items[0] > 0) { - items[0] = 0; - items[1] = 'prev-more'; - } - if (items[items.length - 1] < total - 1) { - items[items.length - 1] = total - 1; - items[items.length - 2] = 'next-more'; - } - return items; -} - -export default React.memo( - forwardRef(function Pagination( - { - style, - pageCount, - currentPage = 0, - maxPageItemCount = 9, - onPageChange, - }: PaginationProps, - ref: React.Ref, - ) { - const pageItems = generatePageItems( - pageCount, - currentPage, - maxPageItemCount, - ); - return ( -
- -
- ); - }), -); diff --git a/superset-frontend/src/katalon/chart-table/src/DataTable/components/SelectPageSize.tsx b/superset-frontend/src/katalon/chart-table/src/DataTable/components/SelectPageSize.tsx deleted file mode 100644 index 48d4b9a66874e..0000000000000 --- a/superset-frontend/src/katalon/chart-table/src/DataTable/components/SelectPageSize.tsx +++ /dev/null @@ -1,100 +0,0 @@ -/** - * 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. - */ -import React from 'react'; -import { t } from '@superset-ui/core'; -import { formatSelectOptions } from '@superset-ui/chart-controls'; - -export type SizeOption = [number, string]; - -export interface SelectPageSizeRendererProps { - current: number; - options: SizeOption[]; - onChange: SelectPageSizeProps['onChange']; -} - -function DefaultSelectRenderer({ - current, - options, - onChange, -}: SelectPageSizeRendererProps) { - return ( - - {t('Show')}{' '} - {' '} - {t('entries')} - - ); -} - -export interface SelectPageSizeProps extends SelectPageSizeRendererProps { - total?: number; - selectRenderer?: typeof DefaultSelectRenderer; - onChange: (pageSize: number) => void; -} - -function getOptionValue(x: SizeOption) { - return Array.isArray(x) ? x[0] : x; -} - -export default React.memo(function SelectPageSize({ - total, - options: sizeOptions, - current: currentSize, - selectRenderer, - onChange, -}: SelectPageSizeProps) { - const sizeOptionValues = sizeOptions.map(getOptionValue); - let options = [...sizeOptions]; - // insert current size to list - if ( - currentSize !== undefined && - (currentSize !== total || !sizeOptionValues.includes(0)) && - !sizeOptionValues.includes(currentSize) - ) { - options = [...sizeOptions]; - options.splice( - sizeOptionValues.findIndex(x => x > currentSize), - 0, - formatSelectOptions([currentSize])[0], - ); - } - const current = currentSize === undefined ? sizeOptionValues[0] : currentSize; - const SelectRenderer = selectRenderer || DefaultSelectRenderer; - return ( - - ); -}); diff --git a/superset-frontend/src/katalon/chart-table/src/DataTable/hooks/useSticky.tsx b/superset-frontend/src/katalon/chart-table/src/DataTable/hooks/useSticky.tsx deleted file mode 100644 index 067d071ee1926..0000000000000 --- a/superset-frontend/src/katalon/chart-table/src/DataTable/hooks/useSticky.tsx +++ /dev/null @@ -1,421 +0,0 @@ -/** - * 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. - */ -import React, { - useRef, - useMemo, - useLayoutEffect, - useCallback, - ReactNode, - ReactElement, - ComponentPropsWithRef, - CSSProperties, - UIEventHandler, -} from 'react'; -import { TableInstance, Hooks } from 'react-table'; -import getScrollBarSize from '../utils/getScrollBarSize'; -import needScrollBar from '../utils/needScrollBar'; -import useMountedMemo from '../utils/useMountedMemo'; - -type ReactElementWithChildren< - T extends keyof JSX.IntrinsicElements, - C extends ReactNode = ReactNode, -> = ReactElement & { children: C }, T>; - -type Th = ReactElementWithChildren<'th'>; -type Td = ReactElementWithChildren<'td'>; -type TrWithTh = ReactElementWithChildren<'tr', Th[]>; -type TrWithTd = ReactElementWithChildren<'tr', Td[]>; -type Thead = ReactElementWithChildren<'thead', TrWithTh>; -type Tbody = ReactElementWithChildren<'tbody', TrWithTd>; -type Tfoot = ReactElementWithChildren<'tfoot', TrWithTd>; -type Col = ReactElementWithChildren<'col', null>; -type ColGroup = ReactElementWithChildren<'colgroup', Col>; - -export type Table = ReactElementWithChildren< - 'table', - (Thead | Tbody | Tfoot | ColGroup)[] ->; -export type TableRenderer = () => Table; -export type GetTableSize = () => Partial | undefined; -export type SetStickyState = (size?: Partial) => void; - -export enum ReducerActions { - init = 'init', // this is from global reducer - setStickyState = 'setStickyState', -} - -export type ReducerAction< - T extends string, - P extends Record, -> = P & { type: T }; - -export type ColumnWidths = number[]; - -export interface StickyState { - width?: number; // maximum full table width - height?: number; // maximum full table height - realHeight?: number; // actual table viewport height (header + scrollable area) - bodyHeight?: number; // scrollable area height - tableHeight?: number; // the full table height - columnWidths?: ColumnWidths; - hasHorizontalScroll?: boolean; - hasVerticalScroll?: boolean; - rendering?: boolean; - setStickyState?: SetStickyState; -} - -export interface UseStickyTableOptions { - getTableSize?: GetTableSize; -} - -export interface UseStickyInstanceProps { - // manipulate DOMs in to make the header sticky - wrapStickyTable: (renderer: TableRenderer) => ReactNode; - // update or recompute the sticky table size - setStickyState: SetStickyState; -} - -export type UseStickyState = { - sticky: StickyState; -}; - -const sum = (a: number, b: number) => a + b; -const mergeStyleProp = ( - node: ReactElement<{ style?: CSSProperties }>, - style: CSSProperties, -) => ({ - style: { - ...node.props.style, - ...style, - }, -}); -const fixedTableLayout: CSSProperties = { tableLayout: 'fixed' }; - -/** - * An HOC for generating sticky header and fixed-height scrollable area - */ -function StickyWrap({ - sticky = {}, - width: maxWidth, - height: maxHeight, - children: table, - setStickyState, -}: { - width: number; - height: number; - setStickyState: SetStickyState; - children: Table; - sticky?: StickyState; // current sticky element sizes -}) { - if (!table || table.type !== 'table') { - throw new Error(' must have only one
element as child'); - } - let thead: Thead | undefined; - let tbody: Tbody | undefined; - let tfoot: Tfoot | undefined; - - React.Children.forEach(table.props.children, node => { - if (!node) { - return; - } - if (node.type === 'thead') { - thead = node; - } else if (node.type === 'tbody') { - tbody = node; - } else if (node.type === 'tfoot') { - tfoot = node; - } - }); - if (!thead || !tbody) { - throw new Error( - '
in must contain both thead and tbody.', - ); - } - const columnCount = useMemo(() => { - const headerRows = React.Children.toArray( - thead?.props.children, - ).pop() as TrWithTh; - return headerRows.props.children.length; - }, [thead]); - - const theadRef = useRef(null); // original thead for layout computation - const tfootRef = useRef(null); // original tfoot for layout computation - const scrollHeaderRef = useRef(null); // fixed header - const scrollFooterRef = useRef(null); // fixed footer - const scrollBodyRef = useRef(null); // main body - - const scrollBarSize = getScrollBarSize(); - const { bodyHeight, columnWidths } = sticky; - const needSizer = - !columnWidths || - sticky.width !== maxWidth || - sticky.height !== maxHeight || - sticky.setStickyState !== setStickyState; - - // update scrollable area and header column sizes when mounted - useLayoutEffect(() => { - if (!theadRef.current) { - return; - } - const bodyThead = theadRef.current; - const theadHeight = bodyThead.clientHeight; - const tfootHeight = tfootRef.current ? tfootRef.current.clientHeight : 0; - if (!theadHeight) { - return; - } - const fullTableHeight = (bodyThead.parentNode as HTMLTableElement) - .clientHeight; - const ths = bodyThead.childNodes[0] - .childNodes as NodeListOf; - const widths = Array.from(ths).map( - th => th.getBoundingClientRect()?.width || th.clientWidth, - ); - const [hasVerticalScroll, hasHorizontalScroll] = needScrollBar({ - width: maxWidth, - height: maxHeight - theadHeight - tfootHeight, - innerHeight: fullTableHeight, - innerWidth: widths.reduce(sum), - scrollBarSize, - }); - // real container height, include table header, footer and space for - // horizontal scroll bar - const realHeight = Math.min( - maxHeight, - hasHorizontalScroll ? fullTableHeight + scrollBarSize : fullTableHeight, - ); - setStickyState({ - hasVerticalScroll, - hasHorizontalScroll, - setStickyState, - width: maxWidth, - height: maxHeight, - realHeight, - tableHeight: fullTableHeight, - bodyHeight: realHeight - theadHeight - tfootHeight, - columnWidths: widths, - }); - }, [maxWidth, maxHeight, setStickyState, scrollBarSize]); - - let sizerTable: ReactElement | undefined; - let headerTable: ReactElement | undefined; - let footerTable: ReactElement | undefined; - let bodyTable: ReactElement | undefined; - if (needSizer) { - const theadWithRef = React.cloneElement(thead, { ref: theadRef }); - const tfootWithRef = tfoot && React.cloneElement(tfoot, { ref: tfootRef }); - sizerTable = ( -
- {React.cloneElement(table, {}, theadWithRef, tbody, tfootWithRef)} -
- ); - } - - // reuse previously column widths, will be updated by `useLayoutEffect` above - const colWidths = columnWidths?.slice(0, columnCount); - - if (colWidths && bodyHeight) { - const colgroup = ( -
- {colWidths.map((w, i) => ( - // eslint-disable-next-line react/no-array-index-key - - ))} - - ); - - headerTable = ( -
- {React.cloneElement( - table, - mergeStyleProp(table, fixedTableLayout), - colgroup, - thead, - )} - {headerTable} -
- ); - - footerTable = tfoot && ( -
- {React.cloneElement( - table, - mergeStyleProp(table, fixedTableLayout), - colgroup, - tfoot, - )} - {footerTable} -
- ); - - const onScroll: UIEventHandler = e => { - if (scrollHeaderRef.current) { - scrollHeaderRef.current.scrollLeft = e.currentTarget.scrollLeft; - } - if (scrollFooterRef.current) { - scrollFooterRef.current.scrollLeft = e.currentTarget.scrollLeft; - } - }; - bodyTable = ( -
- {React.cloneElement( - table, - mergeStyleProp(table, fixedTableLayout), - colgroup, - tbody, - )} -
- ); - } - - return ( -
- {headerTable} - {bodyTable} - {footerTable} - {sizerTable} -
- ); -} - -function useInstance(instance: TableInstance) { - const { - dispatch, - state: { sticky }, - data, - page, - rows, - allColumns, - getTableSize = () => undefined, - } = instance; - - const setStickyState = useCallback( - (size?: Partial) => { - dispatch({ - type: ReducerActions.setStickyState, - size, - }); - }, - // turning pages would also trigger a resize - // eslint-disable-next-line react-hooks/exhaustive-deps - [dispatch, getTableSize, page, rows], - ); - - const useStickyWrap = (renderer: TableRenderer) => { - const { width, height } = - useMountedMemo(getTableSize, [getTableSize]) || sticky; - // only change of data should trigger re-render - // eslint-disable-next-line react-hooks/exhaustive-deps - const table = useMemo(renderer, [page, rows, allColumns]); - - useLayoutEffect(() => { - if (!width || !height) { - setStickyState(); - } - }, [width, height]); - - if (!width || !height) { - return null; - } - if (data.length === 0) { - return table; - } - return ( - - {table} - - ); - }; - - Object.assign(instance, { - setStickyState, - wrapStickyTable: useStickyWrap, - }); -} - -export default function useSticky(hooks: Hooks) { - hooks.useInstance.push(useInstance); - hooks.stateReducers.push((newState, action_, prevState) => { - const action = action_ as ReducerAction< - ReducerActions, - { size: StickyState } - >; - if (action.type === ReducerActions.init) { - return { - ...newState, - sticky: { - ...prevState?.sticky, - }, - }; - } - if (action.type === ReducerActions.setStickyState) { - const { size } = action; - if (!size) { - return { ...newState }; - } - return { - ...newState, - sticky: { - ...prevState?.sticky, - ...newState?.sticky, - ...action.size, - }, - }; - } - return newState; - }); -} -useSticky.pluginName = 'useSticky'; diff --git a/superset-frontend/src/katalon/chart-table/src/DataTable/index.tsx b/superset-frontend/src/katalon/chart-table/src/DataTable/index.tsx deleted file mode 100644 index 55bdc9d38c61e..0000000000000 --- a/superset-frontend/src/katalon/chart-table/src/DataTable/index.tsx +++ /dev/null @@ -1,25 +0,0 @@ -/** - * 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 * from './hooks/useSticky'; -export * from './components/GlobalFilter'; -export * from './components/Pagination'; -export * from './components/SelectPageSize'; -export * from './DataTable'; - -export { default } from './DataTable'; diff --git a/superset-frontend/src/katalon/chart-table/src/DataTable/types/react-table.d.ts b/superset-frontend/src/katalon/chart-table/src/DataTable/types/react-table.d.ts deleted file mode 100644 index c1f49ea396f25..0000000000000 --- a/superset-frontend/src/katalon/chart-table/src/DataTable/types/react-table.d.ts +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 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. - */ - -/** - * Merge typing interfaces for UseTable hooks. - * - * Ref: https://gist.github.com/ggascoigne/646e14c9d54258e40588a13aabf0102d - */ -import { - UseGlobalFiltersState, - UseGlobalFiltersOptions, - UseGlobalFiltersInstanceProps, - UsePaginationInstanceProps, - UsePaginationOptions, - UsePaginationState, - UseSortByColumnOptions, - UseSortByColumnProps, - UseSortByInstanceProps, - UseSortByOptions, - UseSortByState, - UseTableHooks, - UseSortByHooks, - UseColumnOrderState, - UseColumnOrderInstanceProps, - Renderer, - HeaderProps, - TableFooterProps, -} from 'react-table'; - -import { - UseStickyState, - UseStickyTableOptions, - UseStickyInstanceProps, -} from '../hooks/useSticky'; - -declare module 'react-table' { - export interface TableOptions - extends UseExpandedOptions, - UseGlobalFiltersOptions, - UsePaginationOptions, - UseRowSelectOptions, - UseSortByOptions, - UseStickyTableOptions {} - - export interface TableInstance - extends UseColumnOrderInstanceProps, - UseExpandedInstanceProps, - UseGlobalFiltersInstanceProps, - UsePaginationInstanceProps, - UseRowSelectInstanceProps, - UseRowStateInstanceProps, - UseSortByInstanceProps, - UseColumnOrderInstanceProps, - UseStickyInstanceProps {} - - export interface TableState - extends UseColumnOrderState, - UseExpandedState, - UseGlobalFiltersState, - UsePaginationState, - UseRowSelectState, - UseSortByState, - UseColumnOrderState, - UseStickyState {} - - // Typing from @types/react-table is incomplete - interface TableSortByToggleProps { - style?: React.CSSProperties; - title?: string; - onClick?: React.MouseEventHandler; - } - - interface TableRearrangeColumnsProps { - onDragStart: (e: React.DragEvent) => void; - onDrop: (e: React.DragEvent) => void; - } - - export interface ColumnInterface - extends UseGlobalFiltersColumnOptions, - UseSortByColumnOptions { - // must define as a new property because it's not possible to override - // the existing `Header` renderer option - Header?: Renderer< - TableSortByToggleProps & HeaderProps & TableRearrangeColumnsProps - >; - Footer?: Renderer>; - } - - export interface ColumnInstance - extends UseGlobalFiltersColumnOptions, - UseSortByColumnProps { - getSortByToggleProps: ( - props?: Partial, - ) => TableSortByToggleProps; - } - - export interface Hooks - extends UseTableHooks, - UseSortByHooks {} -} diff --git a/superset-frontend/src/katalon/chart-table/src/DataTable/utils/getScrollBarSize.ts b/superset-frontend/src/katalon/chart-table/src/DataTable/utils/getScrollBarSize.ts deleted file mode 100644 index 5d86598bf21d8..0000000000000 --- a/superset-frontend/src/katalon/chart-table/src/DataTable/utils/getScrollBarSize.ts +++ /dev/null @@ -1,48 +0,0 @@ -/** - * 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. - */ -let cached: number | undefined; - -const css = (x: TemplateStringsArray) => x.join('\n'); - -export default function getScrollBarSize(forceRefresh = false) { - if (typeof document === 'undefined') { - return 0; - } - if (cached === undefined || forceRefresh) { - const inner = document.createElement('div'); - const outer = document.createElement('div'); - inner.style.cssText = css` - width: auto; - height: 100%; - overflow: scroll; - `; - outer.style.cssText = css` - position: absolute; - visibility: hidden; - overflow: hidden; - width: 100px; - height: 50px; - `; - outer.append(inner); - document.body.append(outer); - cached = outer.clientWidth - inner.clientWidth; - outer.remove(); - } - return cached; -} diff --git a/superset-frontend/src/katalon/chart-table/src/DataTable/utils/needScrollBar.ts b/superset-frontend/src/katalon/chart-table/src/DataTable/utils/needScrollBar.ts deleted file mode 100644 index 2ac111925be4d..0000000000000 --- a/superset-frontend/src/katalon/chart-table/src/DataTable/utils/needScrollBar.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * 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. - */ -/** - * Whether a container need scroll bars when in another container. - */ -export default function needScrollBar({ - width, - height, - innerHeight, - innerWidth, - scrollBarSize, -}: { - width: number; - height: number; - innerHeight: number; - scrollBarSize: number; - innerWidth: number; -}): [boolean, boolean] { - const hasVerticalScroll = innerHeight > height; - const hasHorizontalScroll = - innerWidth > width - (hasVerticalScroll ? scrollBarSize : 0); - return [hasVerticalScroll, hasHorizontalScroll]; -} diff --git a/superset-frontend/src/katalon/chart-table/src/DataTable/utils/sortAlphanumericCaseInsensitive.ts b/superset-frontend/src/katalon/chart-table/src/DataTable/utils/sortAlphanumericCaseInsensitive.ts deleted file mode 100644 index c1adc99949a23..0000000000000 --- a/superset-frontend/src/katalon/chart-table/src/DataTable/utils/sortAlphanumericCaseInsensitive.ts +++ /dev/null @@ -1,37 +0,0 @@ -/** - * 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. - */ - -import { Row } from 'react-table'; - -export const sortAlphanumericCaseInsensitive = ( - rowA: Row, - rowB: Row, - columnId: string, -) => { - const valueA = rowA.values[columnId]; - const valueB = rowB.values[columnId]; - - if (!valueA || typeof valueA !== 'string') { - return -1; - } - if (!valueB || typeof valueB !== 'string') { - return 1; - } - return valueA.localeCompare(valueB); -}; diff --git a/superset-frontend/src/katalon/chart-table/src/DataTable/utils/useAsyncState.ts b/superset-frontend/src/katalon/chart-table/src/DataTable/utils/useAsyncState.ts deleted file mode 100644 index 0d941462e5e54..0000000000000 --- a/superset-frontend/src/katalon/chart-table/src/DataTable/utils/useAsyncState.ts +++ /dev/null @@ -1,51 +0,0 @@ -/** - * 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. - */ -import { useRef, useState } from 'react'; -import { useAsyncDebounce } from 'react-table'; - -// useAsyncDebounce in dist build of `react-table` requires regeneratorRuntime -import 'regenerator-runtime/runtime'; - -/** - * Hook useState to allow always return latest initialValue - */ -export default function useAsyncState unknown>( - initialValue: T, - callback: F, - wait = 200, -) { - const [value, setValue] = useState(initialValue); - const valueRef = useRef(initialValue); - const onChange = useAsyncDebounce(callback, wait); - - // sync updated initialValue - if (valueRef.current !== initialValue) { - valueRef.current = initialValue; - if (value !== initialValue) { - setValue(initialValue); - } - } - - const setBoth = (newValue: T) => { - setValue(newValue); - onChange(newValue); - }; - - return [value, setBoth] as [typeof value, typeof setValue]; -} diff --git a/superset-frontend/src/katalon/chart-table/src/DataTable/utils/useMountedMemo.ts b/superset-frontend/src/katalon/chart-table/src/DataTable/utils/useMountedMemo.ts deleted file mode 100644 index 70f535479cb68..0000000000000 --- a/superset-frontend/src/katalon/chart-table/src/DataTable/utils/useMountedMemo.ts +++ /dev/null @@ -1,40 +0,0 @@ -/** - * 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. - */ -import { useLayoutEffect, useRef, useMemo } from 'react'; - -/** - * Execute a memoized callback only when mounted. Execute again when factory updated. - * Returns undefined if not mounted yet. - */ -export default function useMountedMemo( - factory: () => T, - deps?: unknown[], -): T | undefined { - const mounted = useRef(); - useLayoutEffect(() => { - mounted.current = factory; - }); - return useMemo(() => { - if (mounted.current) { - return factory(); - } - return undefined; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [mounted.current, mounted.current === factory, ...(deps || [])]); -} diff --git a/superset-frontend/src/katalon/chart-table/src/Styles.tsx b/superset-frontend/src/katalon/chart-table/src/Styles.tsx deleted file mode 100644 index 9219b6f0030d2..0000000000000 --- a/superset-frontend/src/katalon/chart-table/src/Styles.tsx +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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. - */ - -import { css, styled } from '@superset-ui/core'; - -export default styled.div` - ${({ theme }) => css` - table { - width: 100%; - min-width: auto; - max-width: none; - margin: 0; - } - - th, - td { - min-width: 4.3em; - } - - thead > tr > th { - padding-right: 0; - position: relative; - background: ${theme.colors.grayscale.light5}; - text-align: left; - } - th svg { - color: ${theme.colors.grayscale.light2}; - margin: ${theme.gridUnit / 2}px; - } - th.is-sorted svg { - color: ${theme.colors.grayscale.base}; - } - .table > tbody > tr:first-of-type > td, - .table > tbody > tr:first-of-type > th { - border-top: 0; - } - - .table > tbody tr td { - font-feature-settings: 'tnum' 1; - } - - .dt-controls { - padding-bottom: 0.65em; - } - .dt-metric { - text-align: right; - } - .dt-totals { - font-weight: ${theme.typography.weights.bold}; - } - .dt-is-null { - color: ${theme.colors.grayscale.light1}; - } - td.dt-is-filter { - cursor: pointer; - } - td.dt-is-filter:hover { - background-color: ${theme.colors.secondary.light4}; - } - td.dt-is-active-filter, - td.dt-is-active-filter:hover { - background-color: ${theme.colors.secondary.light3}; - } - - .dt-global-filter { - float: right; - } - - .dt-truncate-cell { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - .dt-truncate-cell:hover { - overflow: visible; - white-space: normal; - height: auto; - } - - .dt-pagination { - text-align: right; - /* use padding instead of margin so clientHeight can capture it */ - padding-top: 0.5em; - } - .dt-pagination .pagination { - margin: 0; - } - - .pagination > li > span.dt-pagination-ellipsis:focus, - .pagination > li > span.dt-pagination-ellipsis:hover { - background: ${theme.colors.grayscale.light5}; - } - - .dt-no-results { - text-align: center; - padding: 1em 0.6em; - } - `} -`; diff --git a/superset-frontend/src/katalon/chart-table/src/TableChart.tsx b/superset-frontend/src/katalon/chart-table/src/TableChart.tsx deleted file mode 100644 index 21a2f5bd60d88..0000000000000 --- a/superset-frontend/src/katalon/chart-table/src/TableChart.tsx +++ /dev/null @@ -1,429 +0,0 @@ -/* eslint-disable theme-colors/no-literal-colors */ - -import React from 'react'; -import { DataRecord } from '@superset-ui/core'; -import { makeStyles } from '@mui/styles'; -import { DataGrid, GridColDef } from '@katalon-studio/katalon-ui/v2'; -import { getUrlParam } from 'src/utils/urlUtils'; -import { URL_PARAMS } from 'src/constants'; -import moment from 'moment'; -import { TableChartTransformedProps } from './types'; -import { DataTableProps } from './DataTable'; -import Config from '../../../../config'; - -const useStyles = makeStyles(() => ({ - tableHeader: { - backgroundColor: '#f7f9fb', - '& .MuiDataGrid-columnHeaderTitle': { - color: '#46474d', - fontSize: '11px', - fontWeight: 700, - }, - }, - firstColumnHeader: { - backgroundColor: '#f7f9fb', - '& .MuiDataGrid-columnHeaderTitle': { - color: '#46474d', - fontSize: '11px', - fontWeight: 700, - paddingLeft: '16px', - }, - }, - lastColumnHeader: { - backgroundColor: '#f7f9fb', - '& .MuiDataGrid-columnHeaderTitle': { - color: '#46474d', - fontSize: '11px', - fontWeight: 700, - paddingRight: '16px', - }, - }, -})); - -const PAGE_SIZE = 10; - -const statusIconMapper = { - PASSED: '/static/assets/images/katalon/status-passed.svg', - FAILED: '/static/assets/images/katalon/status-failed.svg', - INCOMPLETE: '/static/assets/images/katalon/status-incomplete.svg', - ERROR: '/static/assets/images/katalon/status-error.svg', -}; - -const osIconMapper = (name: string) => { - if (name.toLowerCase().includes('win')) { - return '/static/assets/images/katalon/windows.svg'; - } - if (name.toLowerCase().includes('mac')) { - return '/static/assets/images/katalon/macos.svg'; - } - if (name.toLowerCase().includes('linux')) { - return '/static/assets/images/katalon/linux.svg'; - } - if (name.toLowerCase().includes('android')) { - return '/static/assets/images/katalon/macos.svg'; // TODO: icon for Android - } - if (name.toLowerCase().includes('ios')) { - return '/static/assets/images/katalon/macos.svg'; // TODO: icon for IOS - } - return ''; -}; - -const browserIconMapper = (name: string) => { - if (name.toLowerCase().includes('chrome')) { - return '/static/assets/images/katalon/chrome.svg'; - } - if (name.toLowerCase().includes('firefox')) { - return '/static/assets/images/katalon/firefox.svg'; - } - if (name.toLowerCase().includes('edge')) { - return '/static/assets/images/katalon/edge.svg'; - } - if (name.toLowerCase().includes('safari')) { - return '/static/assets/images/katalon/edge.svg'; // TODO: icon for Safari - } - return ''; -}; - -const statusDecorator = (value: string) => ( -
- icon -
-); - -const IDDecorator = (id: string) => { - const projectId = getUrlParam(URL_PARAMS.projectId); - const masterAppHost = Config.masterApp; - - return ( - - {id} - - ); -}; - -const nameDecorator = (nameList: string[]) => { - if (!nameList || nameList.length === 0) return null; - - return ( - - {nameList[0]} - - ); -}; - -const profileDecorator = (profiles: string[]) => { - if (!profiles || profiles.length === 0) return null; - - const decoratedProfiles = profiles.join(', '); - return ( -
- icon - {decoratedProfiles} -
- ); -}; - -const durationDecorator = (milliseconds: number) => { - let decoratedDuration = moment.utc(milliseconds).format('HH[h] mm[m] ss[s]'); - decoratedDuration = decoratedDuration.replace(/00[hms]/g, '').trim(); - - return {decoratedDuration}; -}; - -const environmentDecorator = (environmentList: any[]) => { - if (!environmentList || environmentList.length === 0) return null; - - return ( -
- {environmentList.map(environment => ( -
- {environment.os && ( - icon - )} - {environment.browser && ( - icon - )} -
- ))} -
- ); -}; - -const timeStartedDecorator = (date: Date) => { - const formattedDate = moment(date).format('DD/MM/YYYY HH:mm'); - return {formattedDate}; -}; - -const testResultStatusDecorator = (testResultStatus: any) => { - const { - totalPassed, - totalFailed, - totalError, - totalIncomplete, - totalSkipped, - } = testResultStatus; - return ( -
- - {totalPassed} / {totalFailed} / {totalError} / {totalIncomplete} /{' '} - {totalSkipped} - -
- ); -}; - -const configurationDecorator = (configurationList: string[]) => { - if (!configurationList || configurationList.length === 0) return null; - - const hashedNumbers: string = configurationList - .map(configuration => `#${configuration}`) - .join(', '); - return {hashedNumbers}; -}; - -const executorDecorator = (executor: any) => { - if (!executor) return null; - - const { name, avatar } = executor; - const executorAvatar = - avatar || - 'https://katalon-testops.s3.amazonaws.com/image/icon/defaultAvatar.png'; - - return ( -
- avatar - {name} -
- ); -}; - -const formatData = (data: any) => - data.map((row: any) => { - const { - configuration, - profile, - environment, - executor, - test_result_status, - run_configuration_name, - test_suite_collection_name, - test_suite_name, - ...rest - } = row; - - const parseJSON = (value: any) => { - try { - return JSON.parse(value); - } catch (error) { - console.error(error); - return value; - } - }; - - const parsedConfiguration = parseJSON(configuration); - const parsedProfile = parseJSON(profile); - const parsedEnvironment = parseJSON(environment); - const parsedExecutor = parseJSON(executor); - const parsedTestResultStatus = parseJSON(test_result_status); - - let name: string[] = []; - if (run_configuration_name) { - name = parseJSON(run_configuration_name); - } else if (test_suite_collection_name) { - name = parseJSON(test_suite_collection_name); - } else if (test_suite_name) { - name = parseJSON(test_suite_name); - } - - return { - ...rest, - configuration: parsedConfiguration, - profile: parsedProfile, - environment: parsedEnvironment, - name, - executor: parsedExecutor, - test_result_status: parsedTestResultStatus, - }; - }); - -export default function TableChart( - props: TableChartTransformedProps & { - sticky?: DataTableProps['sticky']; - }, -) { - // TODO: Only use the decorators for test_run_data_table_dataset dataset - - const classes = useStyles(); - - const { data } = props; - console.log('data', data); - - const formattedData = formatData(data); - console.log('FORMATTED DATA', formattedData); - - const tableColumns: GridColDef[] = [ - { - field: 'status', - headerName: 'STATUS', - flex: 0.2, - headerAlign: 'center', - headerClassName: classes.tableHeader, - renderCell: cell => statusDecorator(cell.value), - }, - { - field: 'id', - headerName: 'ID', - flex: 0.3, - headerClassName: classes.firstColumnHeader, - renderCell: cell => IDDecorator(cell.value), - }, - { - field: 'name', - headerName: 'NAME', - flex: 1.3, - headerClassName: classes.tableHeader, - renderCell: cell => nameDecorator(cell.value), - }, - { - field: 'profile', - headerName: 'PROFILE', - flex: 0.5, - headerClassName: classes.tableHeader, - renderCell: cell => profileDecorator(cell.value), - }, - { - field: 'duration', - headerName: 'DURATION', - flex: 0.5, - headerClassName: classes.tableHeader, - renderCell: cell => durationDecorator(cell.value), - }, - { - field: 'environment', - headerName: 'ENVIRONMENT', - flex: 0.5, - headerClassName: classes.tableHeader, - renderCell: cell => environmentDecorator(cell.value), - }, - { - field: 'time_started', - headerName: 'TIME STARTED', - flex: 0.5, - headerClassName: classes.tableHeader, - renderCell: cell => timeStartedDecorator(cell.value), - }, - { - field: 'test_result_status', - headerName: 'TEST RESULT STATUS', - flex: 0.7, - headerClassName: classes.tableHeader, - renderCell: cell => testResultStatusDecorator(cell.value), - }, - { - field: 'configuration', - headerName: 'CONFIGURATION', - flex: 0.6, - headerClassName: classes.tableHeader, - renderCell: cell => configurationDecorator(cell.value), - }, - { - field: 'executor', - headerName: 'EXECUTOR', - flex: 0.5, - headerClassName: classes.lastColumnHeader, - renderCell: cell => executorDecorator(cell.value), - }, - ]; - - return ( - - ); -} diff --git a/superset-frontend/src/katalon/chart-table/src/buildQuery.ts b/superset-frontend/src/katalon/chart-table/src/buildQuery.ts deleted file mode 100644 index 13bf2e9c2d4c8..0000000000000 --- a/superset-frontend/src/katalon/chart-table/src/buildQuery.ts +++ /dev/null @@ -1,227 +0,0 @@ -/** - * 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. - */ -import { - AdhocColumn, - buildQueryContext, - ensureIsArray, - getMetricLabel, - hasGenericChartAxes, - isPhysicalColumn, - QueryMode, - QueryObject, - removeDuplicates, -} from '@superset-ui/core'; -import { PostProcessingRule } from '@superset-ui/core/src/query/types/PostProcessing'; -import { BuildQuery } from '@superset-ui/core/src/chart/registries/ChartBuildQueryRegistrySingleton'; -import { TableChartFormData } from './types'; -import { updateExternalFormData } from './DataTable/utils/externalAPIs'; - -/** - * Infer query mode from form data. If `all_columns` is set, then raw records mode, - * otherwise defaults to aggregation mode. - * - * The same logic is used in `controlPanel` with control values as well. - */ -export function getQueryMode(formData: TableChartFormData) { - const { query_mode: mode } = formData; - if (mode === QueryMode.aggregate || mode === QueryMode.raw) { - return mode; - } - const rawColumns = formData?.all_columns; - const hasRawColumns = rawColumns && rawColumns.length > 0; - return hasRawColumns ? QueryMode.raw : QueryMode.aggregate; -} - -const buildQuery: BuildQuery = ( - formData: TableChartFormData, - options, -) => { - const { - percent_metrics: percentMetrics, - order_desc: orderDesc = false, - extra_form_data, - } = formData; - const queryMode = getQueryMode(formData); - const sortByMetric = ensureIsArray(formData.timeseries_limit_metric)[0]; - const time_grain_sqla = - extra_form_data?.time_grain_sqla || formData.time_grain_sqla; - let formDataCopy = formData; - // never include time in raw records mode - if (queryMode === QueryMode.raw) { - formDataCopy = { - ...formData, - include_time: false, - }; - } - - return buildQueryContext(formDataCopy, baseQueryObject => { - let { metrics, orderby = [], columns = [] } = baseQueryObject; - let postProcessing: PostProcessingRule[] = []; - - if (queryMode === QueryMode.aggregate) { - metrics = metrics || []; - // override orderby with timeseries metric when in aggregation mode - if (sortByMetric) { - orderby = [[sortByMetric, !orderDesc]]; - } else if (metrics?.length > 0) { - // default to ordering by first metric in descending order - // when no "sort by" metric is set (regardless if "SORT DESC" is set to true) - orderby = [[metrics[0], false]]; - } - // add postprocessing for percent metrics only when in aggregation mode - if (percentMetrics && percentMetrics.length > 0) { - const percentMetricLabels = removeDuplicates( - percentMetrics.map(getMetricLabel), - ); - metrics = removeDuplicates( - metrics.concat(percentMetrics), - getMetricLabel, - ); - postProcessing = [ - { - operation: 'contribution', - options: { - columns: percentMetricLabels, - rename_columns: percentMetricLabels.map(x => `%${x}`), - }, - }, - ]; - } - - columns = columns.map(col => { - if ( - isPhysicalColumn(col) && - time_grain_sqla && - hasGenericChartAxes && - formData?.temporal_columns_lookup?.[col] - ) { - return { - timeGrain: time_grain_sqla, - columnType: 'BASE_AXIS', - sqlExpression: col, - label: col, - expressionType: 'SQL', - } as AdhocColumn; - } - return col; - }); - } - - const moreProps: Partial = {}; - const ownState = options?.ownState ?? {}; - if (formDataCopy.server_pagination) { - moreProps.row_limit = - ownState.pageSize ?? formDataCopy.server_page_length; - moreProps.row_offset = - (ownState.currentPage ?? 0) * (ownState.pageSize ?? 0); - } - - let queryObject = { - ...baseQueryObject, - columns, - orderby, - metrics, - post_processing: postProcessing, - ...moreProps, - }; - - if ( - formData.server_pagination && - options?.extras?.cachedChanges?.[formData.slice_id] && - JSON.stringify(options?.extras?.cachedChanges?.[formData.slice_id]) !== - JSON.stringify(queryObject.filters) - ) { - queryObject = { ...queryObject, row_offset: 0 }; - updateExternalFormData( - options?.hooks?.setDataMask, - 0, - queryObject.row_limit ?? 0, - ); - } - // Because we use same buildQuery for all table on the page we need split them by id - options?.hooks?.setCachedChanges({ - [formData.slice_id]: queryObject.filters, - }); - - const extraQueries: QueryObject[] = []; - if ( - metrics?.length && - formData.show_totals && - queryMode === QueryMode.aggregate - ) { - extraQueries.push({ - ...queryObject, - columns: [], - row_limit: 0, - row_offset: 0, - post_processing: [], - order_desc: undefined, // we don't need orderby stuff here, - orderby: undefined, // because this query will be used for get total aggregation. - }); - } - - const interactiveGroupBy = formData.extra_form_data?.interactive_groupby; - if (interactiveGroupBy && queryObject.columns) { - queryObject.columns = [ - ...new Set([...queryObject.columns, ...interactiveGroupBy]), - ]; - } - - if (formData.server_pagination) { - return [ - { ...queryObject }, - { - ...queryObject, - row_limit: 0, - row_offset: 0, - post_processing: [], - is_rowcount: true, - }, - ...extraQueries, - ]; - } - - return [queryObject, ...extraQueries]; - }); -}; - -// Use this closure to cache changing of external filters, if we have server pagination we need reset page to 0, after -// external filter changed -export const cachedBuildQuery = (): BuildQuery => { - let cachedChanges: any = {}; - const setCachedChanges = (newChanges: any) => { - cachedChanges = { ...cachedChanges, ...newChanges }; - }; - - return (formData, options) => - buildQuery( - { ...formData }, - { - extras: { cachedChanges }, - ownState: options?.ownState ?? {}, - hooks: { - ...options?.hooks, - setDataMask: () => {}, - setCachedChanges, - }, - }, - ); -}; - -export default cachedBuildQuery(); diff --git a/superset-frontend/src/katalon/chart-table/src/consts.ts b/superset-frontend/src/katalon/chart-table/src/consts.ts deleted file mode 100644 index e370c4b029529..0000000000000 --- a/superset-frontend/src/katalon/chart-table/src/consts.ts +++ /dev/null @@ -1,32 +0,0 @@ -/** - * 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. - */ -import { formatSelectOptions } from '@superset-ui/chart-controls'; -import { addLocaleData, t } from '@superset-ui/core'; -import i18n from './i18n'; - -addLocaleData(i18n); - -export const PAGE_SIZE_OPTIONS = formatSelectOptions([ - [0, t('page_size.all')], - 10, - 20, - 50, - 100, - 200, -]); diff --git a/superset-frontend/src/katalon/chart-table/src/controlPanel.tsx b/superset-frontend/src/katalon/chart-table/src/controlPanel.tsx deleted file mode 100644 index a59ade460a5fc..0000000000000 --- a/superset-frontend/src/katalon/chart-table/src/controlPanel.tsx +++ /dev/null @@ -1,557 +0,0 @@ -/* eslint-disable camelcase */ -/** - * 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. - */ -import React from 'react'; -import { - ChartDataResponseResult, - ensureIsArray, - FeatureFlag, - GenericDataType, - hasGenericChartAxes, - isAdhocColumn, - isFeatureEnabled, - isPhysicalColumn, - QueryFormColumn, - QueryMode, - smartDateFormatter, - t, -} from '@superset-ui/core'; -import { - ColumnOption, - ControlConfig, - ControlPanelConfig, - ControlPanelsContainerProps, - ControlStateMapping, - D3_TIME_FORMAT_OPTIONS, - QueryModeLabel, - sections, - sharedControls, - ControlPanelState, - ControlState, - Dataset, - ColumnMeta, - defineSavedMetrics, - getStandardizedControls, -} from '@superset-ui/chart-controls'; - -import { PAGE_SIZE_OPTIONS } from './consts'; - -function getQueryMode(controls: ControlStateMapping): QueryMode { - const mode = controls?.query_mode?.value; - if (mode === QueryMode.aggregate || mode === QueryMode.raw) { - return mode as QueryMode; - } - const rawColumns = controls?.all_columns?.value as - | QueryFormColumn[] - | undefined; - const hasRawColumns = rawColumns && rawColumns.length > 0; - return hasRawColumns ? QueryMode.raw : QueryMode.aggregate; -} - -/** - * Visibility check - */ -function isQueryMode(mode: QueryMode) { - return ({ controls }: Pick) => - getQueryMode(controls) === mode; -} - -const isAggMode = isQueryMode(QueryMode.aggregate); -const isRawMode = isQueryMode(QueryMode.raw); - -const validateAggControlValues = ( - controls: ControlStateMapping, - values: any[], -) => { - const areControlsEmpty = values.every(val => ensureIsArray(val).length === 0); - return areControlsEmpty && isAggMode({ controls }) - ? [t('Group By, Metrics or Percentage Metrics must have a value')] - : []; -}; - -const queryMode: ControlConfig<'RadioButtonControl'> = { - type: 'RadioButtonControl', - label: t('Query mode'), - default: null, - options: [ - [QueryMode.aggregate, QueryModeLabel[QueryMode.aggregate]], - [QueryMode.raw, QueryModeLabel[QueryMode.raw]], - ], - mapStateToProps: ({ controls }) => ({ value: getQueryMode(controls) }), - rerender: ['all_columns', 'groupby', 'metrics', 'percent_metrics'], -}; - -const allColumnsControl: typeof sharedControls.groupby = { - ...sharedControls.groupby, - label: t('Columns'), - description: t('Columns to display'), - multi: true, - freeForm: true, - allowAll: true, - commaChoosesOption: false, - optionRenderer: c => , - valueRenderer: c => , - valueKey: 'column_name', - mapStateToProps: ({ datasource, controls }, controlState) => ({ - options: datasource?.columns || [], - queryMode: getQueryMode(controls), - externalValidationErrors: - isRawMode({ controls }) && ensureIsArray(controlState?.value).length === 0 - ? [t('must have a value')] - : [], - }), - visibility: isRawMode, - resetOnHide: false, -}; - -const percentMetricsControl: typeof sharedControls.metrics = { - ...sharedControls.metrics, - label: t('Percentage metrics'), - description: t( - 'Select one or many metrics to display, that will be displayed in the percentages of total. ' + - 'Percentage metrics will be calculated only from data within the row limit. ' + - 'You can use an aggregation function on a column or write custom SQL to create a percentage metric.', - ), - visibility: isAggMode, - resetOnHide: false, - mapStateToProps: ({ datasource, controls }, controlState) => ({ - columns: datasource?.columns || [], - savedMetrics: defineSavedMetrics(datasource), - datasource, - datasourceType: datasource?.type, - queryMode: getQueryMode(controls), - externalValidationErrors: validateAggControlValues(controls, [ - controls.groupby?.value, - controls.metrics?.value, - controlState?.value, - ]), - }), - rerender: ['groupby', 'metrics'], - default: [], - validators: [], -}; - -const config: ControlPanelConfig = { - controlPanelSections: [ - sections.genericTime, - { - label: t('Query'), - expanded: true, - controlSetRows: [ - [ - { - name: 'query_mode', - config: queryMode, - }, - ], - [ - { - name: 'groupby', - override: { - visibility: isAggMode, - resetOnHide: false, - mapStateToProps: ( - state: ControlPanelState, - controlState: ControlState, - ) => { - const { controls } = state; - const originalMapStateToProps = - sharedControls?.groupby?.mapStateToProps; - const newState = - originalMapStateToProps?.(state, controlState) ?? {}; - newState.externalValidationErrors = validateAggControlValues( - controls, - [ - controls.metrics?.value, - controls.percent_metrics?.value, - controlState.value, - ], - ); - - return newState; - }, - rerender: ['metrics', 'percent_metrics'], - }, - }, - ], - [ - hasGenericChartAxes && isAggMode - ? { - name: 'time_grain_sqla', - config: { - ...sharedControls.time_grain_sqla, - visibility: ({ controls }) => { - const dttmLookup = Object.fromEntries( - ensureIsArray(controls?.groupby?.options).map(option => [ - option.column_name, - option.is_dttm, - ]), - ); - - return ensureIsArray(controls?.groupby.value) - .map(selection => { - if (isAdhocColumn(selection)) { - return true; - } - if (isPhysicalColumn(selection)) { - return !!dttmLookup[selection]; - } - return false; - }) - .some(Boolean); - }, - }, - } - : null, - hasGenericChartAxes && isAggMode ? 'temporal_columns_lookup' : null, - ], - [ - { - name: 'metrics', - override: { - validators: [], - visibility: isAggMode, - resetOnHide: false, - mapStateToProps: ( - { controls, datasource, form_data }: ControlPanelState, - controlState: ControlState, - ) => ({ - columns: datasource?.columns[0]?.hasOwnProperty('filterable') - ? (datasource as Dataset)?.columns?.filter( - (c: ColumnMeta) => c.filterable, - ) - : datasource?.columns, - savedMetrics: defineSavedMetrics(datasource), - // current active adhoc metrics - selectedMetrics: - form_data.metrics || - (form_data.metric ? [form_data.metric] : []), - datasource, - externalValidationErrors: validateAggControlValues(controls, [ - controls.groupby?.value, - controls.percent_metrics?.value, - controlState.value, - ]), - }), - rerender: ['groupby', 'percent_metrics'], - }, - }, - { - name: 'all_columns', - config: allColumnsControl, - }, - ], - [ - { - name: 'percent_metrics', - config: percentMetricsControl, - }, - ], - ['adhoc_filters'], - [ - { - name: 'timeseries_limit_metric', - override: { - visibility: isAggMode, - resetOnHide: false, - }, - }, - { - name: 'order_by_cols', - config: { - type: 'SelectControl', - label: t('Ordering'), - description: t('Order results by selected columns'), - multi: true, - default: [], - mapStateToProps: ({ datasource }) => ({ - choices: datasource?.hasOwnProperty('order_by_choices') - ? (datasource as Dataset)?.order_by_choices - : datasource?.columns || [], - }), - visibility: isRawMode, - resetOnHide: false, - }, - }, - ], - isFeatureEnabled(FeatureFlag.DASHBOARD_CROSS_FILTERS) || - isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) - ? [ - { - name: 'server_pagination', - config: { - type: 'CheckboxControl', - label: t('Server pagination'), - description: t( - 'Enable server side pagination of results (experimental feature)', - ), - default: false, - }, - }, - ] - : [], - [ - { - name: 'row_limit', - override: { - default: 1000, - visibility: ({ controls }: ControlPanelsContainerProps) => - !controls?.server_pagination?.value, - }, - }, - { - name: 'server_page_length', - config: { - type: 'SelectControl', - freeForm: true, - label: t('Server Page Length'), - default: 10, - choices: PAGE_SIZE_OPTIONS, - description: t('Rows per page, 0 means no pagination'), - visibility: ({ controls }: ControlPanelsContainerProps) => - Boolean(controls?.server_pagination?.value), - }, - }, - ], - !hasGenericChartAxes - ? [ - { - name: 'include_time', - config: { - type: 'CheckboxControl', - label: t('Include time'), - description: t( - 'Whether to include the time granularity as defined in the time section', - ), - default: false, - visibility: isAggMode, - resetOnHide: false, - }, - }, - ] - : [null], - [ - { - name: 'order_desc', - config: { - type: 'CheckboxControl', - label: t('Sort descending'), - default: true, - description: t( - 'If enabled, this control sorts the results/values descending, otherwise it sorts the results ascending.', - ), - visibility: isAggMode, - resetOnHide: false, - }, - }, - ], - [ - { - name: 'show_totals', - config: { - type: 'CheckboxControl', - label: t('Show totals'), - default: false, - description: t( - 'Show total aggregations of selected metrics. Note that row limit does not apply to the result.', - ), - visibility: isAggMode, - resetOnHide: false, - }, - }, - ], - ], - }, - { - label: t('Options'), - expanded: true, - controlSetRows: [ - [ - { - name: 'table_timestamp_format', - config: { - type: 'SelectControl', - freeForm: true, - label: t('Timestamp format'), - default: smartDateFormatter.id, - renderTrigger: true, - clearable: false, - choices: D3_TIME_FORMAT_OPTIONS, - description: t('D3 time format for datetime columns'), - }, - }, - ], - [ - { - name: 'page_length', - config: { - type: 'SelectControl', - freeForm: true, - renderTrigger: true, - label: t('Page length'), - default: null, - choices: PAGE_SIZE_OPTIONS, - description: t('Rows per page, 0 means no pagination'), - visibility: ({ controls }: ControlPanelsContainerProps) => - !controls?.server_pagination?.value, - }, - }, - null, - ], - [ - { - name: 'include_search', - config: { - type: 'CheckboxControl', - label: t('Search box'), - renderTrigger: true, - default: false, - description: t('Whether to include a client-side search box'), - }, - }, - { - name: 'show_cell_bars', - config: { - type: 'CheckboxControl', - label: t('Cell bars'), - renderTrigger: true, - default: true, - description: t( - 'Whether to display a bar chart background in table columns', - ), - }, - }, - ], - [ - { - name: 'align_pn', - config: { - type: 'CheckboxControl', - label: t('Align +/-'), - renderTrigger: true, - default: false, - description: t( - 'Whether to align background charts with both positive and negative values at 0', - ), - }, - }, - { - name: 'color_pn', - config: { - type: 'CheckboxControl', - label: t('Color +/-'), - renderTrigger: true, - default: true, - description: t( - 'Whether to colorize numeric values by whether they are positive or negative', - ), - }, - }, - ], - [ - { - name: 'allow_rearrange_columns', - config: { - type: 'CheckboxControl', - label: t('Allow columns to be rearranged'), - renderTrigger: true, - default: false, - description: t( - "Allow end user to drag-and-drop column headers to rearrange them. Note their changes won't persist for the next time they open the chart.", - ), - }, - }, - ], - [ - { - name: 'column_config', - config: { - type: 'ColumnConfigControl', - label: t('Customize columns'), - description: t('Further customize how to display each column'), - width: 400, - height: 320, - renderTrigger: true, - shouldMapStateToProps() { - return true; - }, - mapStateToProps(explore, _, chart) { - return { - queryResponse: chart?.queriesResponse?.[0] as - | ChartDataResponseResult - | undefined, - }; - }, - }, - }, - ], - [ - { - name: 'conditional_formatting', - config: { - type: 'ConditionalFormattingControl', - renderTrigger: true, - label: t('Conditional formatting'), - description: t( - 'Apply conditional color formatting to numeric columns', - ), - shouldMapStateToProps() { - return true; - }, - mapStateToProps(explore, _, chart) { - const verboseMap = explore?.datasource?.hasOwnProperty( - 'verbose_map', - ) - ? (explore?.datasource as Dataset)?.verbose_map - : explore?.datasource?.columns ?? {}; - const chartStatus = chart?.chartStatus; - const { colnames, coltypes } = - chart?.queriesResponse?.[0] ?? {}; - const numericColumns = - Array.isArray(colnames) && Array.isArray(coltypes) - ? colnames - .filter( - (colname: string, index: number) => - coltypes[index] === GenericDataType.NUMERIC, - ) - .map(colname => ({ - value: colname, - label: verboseMap[colname] ?? colname, - })) - : []; - return { - removeIrrelevantConditions: chartStatus === 'success', - columnOptions: numericColumns, - verboseMap, - }; - }, - }, - }, - ], - ], - }, - ], - formDataOverrides: formData => ({ - ...formData, - metrics: getStandardizedControls().popAllMetrics(), - groupby: getStandardizedControls().popAllColumns(), - }), -}; - -export default config; diff --git a/superset-frontend/src/katalon/chart-table/src/i18n.ts b/superset-frontend/src/katalon/chart-table/src/i18n.ts deleted file mode 100644 index 3ea82b00e0782..0000000000000 --- a/superset-frontend/src/katalon/chart-table/src/i18n.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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. - */ - -import { Locale } from '@superset-ui/core'; - -const en = { - 'Query Mode': [''], - Aggregate: [''], - 'Raw Records': [''], - 'Emit Filter Events': [''], - 'Show Cell Bars': [''], - 'page_size.show': ['Show'], - 'page_size.all': ['All'], - 'page_size.entries': ['entries'], - 'table.previous_page': ['Previous'], - 'table.next_page': ['Next'], - 'search.num_records': ['%s record', '%s records...'], -}; - -const translations: Partial> = { - en, - fr: { - 'Query Mode': [''], - Aggregate: [''], - 'Raw Records': [''], - 'Emit Filter Events': [''], - 'Show Cell Bars': [''], - 'page_size.show': ['Afficher'], - 'page_size.all': ['tous'], - 'page_size.entries': ['entrées'], - 'table.previous_page': ['Précédent'], - 'table.next_page': ['Suivante'], - 'search.num_records': ['%s enregistrement', '%s enregistrements...'], - }, - zh: { - 'Query Mode': ['查询模式'], - Aggregate: ['分组聚合'], - 'Raw Records': ['原始数据'], - 'Emit Filter Events': ['关联看板过滤器'], - 'Show Cell Bars': ['为指标添加条状图背景'], - 'page_size.show': ['每页显示'], - 'page_size.all': ['全部'], - 'page_size.entries': ['条'], - 'table.previous_page': ['上一页'], - 'table.next_page': ['下一页'], - 'search.num_records': ['%s条记录...'], - }, -}; - -export default translations; diff --git a/superset-frontend/src/katalon/chart-table/test/TableChart.test.tsx b/superset-frontend/src/katalon/chart-table/test/TableChart.test.tsx deleted file mode 100644 index d6998476baa2b..0000000000000 --- a/superset-frontend/src/katalon/chart-table/test/TableChart.test.tsx +++ /dev/null @@ -1,304 +0,0 @@ -/** - * 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. - */ -import React from 'react'; -import { CommonWrapper } from 'enzyme'; -import { render, screen } from '@testing-library/react'; -import '@testing-library/jest-dom'; -import TableChart from '../src/TableChart'; -import transformProps from '../src/transformProps'; -import DateWithFormatter from '../src/utils/DateWithFormatter'; -import testData from './testData'; -import { mount, ProviderWrapper } from './enzyme'; - -describe('plugin-chart-table', () => { - describe('transformProps', () => { - it('should parse pageLength to pageSize', () => { - expect(transformProps(testData.basic).pageSize).toBe(20); - expect( - transformProps({ - ...testData.basic, - rawFormData: { ...testData.basic.rawFormData, page_length: '20' }, - }).pageSize, - ).toBe(20); - expect( - transformProps({ - ...testData.basic, - rawFormData: { ...testData.basic.rawFormData, page_length: '' }, - }).pageSize, - ).toBe(0); - }); - - it('should memoize data records', () => { - expect(transformProps(testData.basic).data).toBe( - transformProps(testData.basic).data, - ); - }); - - it('should memoize columns meta', () => { - expect(transformProps(testData.basic).columns).toBe( - transformProps({ - ...testData.basic, - rawFormData: { ...testData.basic.rawFormData, pageLength: null }, - }).columns, - ); - }); - - it('should format timestamp', () => { - // eslint-disable-next-line no-underscore-dangle - const parsedDate = transformProps(testData.basic).data[0] - .__timestamp as DateWithFormatter; - expect(String(parsedDate)).toBe('2020-01-01 12:34:56'); - expect(parsedDate.getTime()).toBe(1577882096000); - }); - }); - - describe('TableChart', () => { - let wrap: CommonWrapper; // the ReactDataTable wrapper - let tree: Cheerio; - - it('render basic data', () => { - wrap = mount( - , - ); - - tree = wrap.render(); // returns a CheerioWrapper with jQuery-like API - const cells = tree.find('td'); - expect(cells).toHaveLength(12); - expect(cells.eq(0).text()).toEqual('2020-01-01 12:34:56'); - expect(cells.eq(1).text()).toEqual('Michael'); - // number is not in `metrics` list, so it should output raw value - // (in real world Superset, this would mean the column is used in GROUP BY) - expect(cells.eq(2).text()).toEqual('2467063'); - // should not render column with `.` in name as `undefined` - expect(cells.eq(3).text()).toEqual('foo'); - expect(cells.eq(6).text()).toEqual('2467'); - expect(cells.eq(8).text()).toEqual('N/A'); - }); - - it('render advanced data', () => { - wrap = mount( - , - ); - tree = wrap.render(); - // should successful rerender with new props - const cells = tree.find('td'); - expect(tree.find('th').eq(1).text()).toEqual('Sum of Num'); - expect(cells.eq(0).text()).toEqual('Michael'); - expect(cells.eq(2).text()).toEqual('12.346%'); - expect(cells.eq(4).text()).toEqual('2.47k'); - }); - - it('render advanced data with currencies', () => { - render( - ProviderWrapper({ - children: ( - - ), - }), - ); - const cells = document.querySelectorAll('td'); - expect(document.querySelectorAll('th')[1]).toHaveTextContent( - 'Sum of Num', - ); - expect(cells[0]).toHaveTextContent('Michael'); - expect(cells[2]).toHaveTextContent('12.346%'); - expect(cells[4]).toHaveTextContent('$ 2.47k'); - }); - - it('render raw data', () => { - const props = transformProps({ - ...testData.raw, - rawFormData: { ...testData.raw.rawFormData }, - }); - render( - ProviderWrapper({ - children: , - }), - ); - const cells = document.querySelectorAll('td'); - expect(document.querySelectorAll('th')[0]).toHaveTextContent('num'); - expect(cells[0]).toHaveTextContent('1234'); - expect(cells[1]).toHaveTextContent('10000'); - expect(cells[1]).toHaveTextContent('0'); - }); - - it('render raw data with currencies', () => { - const props = transformProps({ - ...testData.raw, - rawFormData: { - ...testData.raw.rawFormData, - column_config: { - num: { - currencyFormat: { symbol: 'USD', symbolPosition: 'prefix' }, - }, - }, - }, - }); - render( - ProviderWrapper({ - children: , - }), - ); - const cells = document.querySelectorAll('td'); - - expect(document.querySelectorAll('th')[0]).toHaveTextContent('num'); - expect(cells[0]).toHaveTextContent('$ 1.23k'); - expect(cells[1]).toHaveTextContent('$ 10k'); - expect(cells[2]).toHaveTextContent('$ 0'); - }); - - it('render empty data', () => { - wrap.setProps({ ...transformProps(testData.empty), sticky: false }); - tree = wrap.render(); - expect(tree.text()).toContain('No records found'); - }); - - it('render color with column color formatter', () => { - render( - ProviderWrapper({ - children: ( - ', - targetValue: 2467, - }, - ], - }, - })} - /> - ), - }), - ); - - expect(getComputedStyle(screen.getByTitle('2467063')).background).toBe( - 'rgba(172, 225, 196, 1)', - ); - expect(getComputedStyle(screen.getByTitle('2467')).background).toBe(''); - }); - - it('render cell without color', () => { - const dataWithEmptyCell = testData.advanced.queriesData[0]; - dataWithEmptyCell.data.push({ - __timestamp: null, - name: 'Noah', - sum__num: null, - '%pct_nice': 0.643, - 'abc.com': 'bazzinga', - }); - - render( - ProviderWrapper({ - children: ( - - ), - }), - ); - expect(getComputedStyle(screen.getByTitle('2467')).background).toBe( - 'rgba(172, 225, 196, 0.812)', - ); - expect(getComputedStyle(screen.getByTitle('2467063')).background).toBe( - '', - ); - expect(getComputedStyle(screen.getByText('N/A')).background).toBe(''); - }); - }); - - it('render cell bars properly, and only when it is toggled on in both regular and percent metrics', () => { - const props = transformProps({ - ...testData.raw, - rawFormData: { ...testData.raw.rawFormData }, - }); - - props.columns[0].isMetric = true; - - render( - ProviderWrapper({ - children: , - }), - ); - let cells = document.querySelectorAll('div.cell-bar'); - cells.forEach(cell => { - expect(cell).toHaveClass('positive'); - }); - props.columns[0].isMetric = false; - props.columns[0].isPercentMetric = true; - - render( - ProviderWrapper({ - children: , - }), - ); - cells = document.querySelectorAll('div.cell-bar'); - cells.forEach(cell => { - expect(cell).toHaveClass('positive'); - }); - - props.showCellBars = false; - - render( - ProviderWrapper({ - children: , - }), - ); - cells = document.querySelectorAll('td'); - - cells.forEach(cell => { - expect(cell).toHaveClass('test-c7w8t3'); - }); - - props.columns[0].isPercentMetric = false; - props.columns[0].isMetric = true; - - render( - ProviderWrapper({ - children: , - }), - ); - cells = document.querySelectorAll('td'); - cells.forEach(cell => { - expect(cell).toHaveClass('test-c7w8t3'); - }); - }); -}); diff --git a/superset-frontend/src/katalon/chart-table/test/buildQuery.test.ts b/superset-frontend/src/katalon/chart-table/test/buildQuery.test.ts deleted file mode 100644 index 164f31aa05492..0000000000000 --- a/superset-frontend/src/katalon/chart-table/test/buildQuery.test.ts +++ /dev/null @@ -1,125 +0,0 @@ -/** - * 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. - */ -import { QueryMode, TimeGranularity } from '@superset-ui/core'; -import * as supersetCoreModule from '@superset-ui/core'; -import buildQuery from '../src/buildQuery'; -import { TableChartFormData } from '../src/types'; - -const basicFormData: TableChartFormData = { - viz_type: 'table', - datasource: '11__table', -}; - -describe('plugin-chart-table', () => { - describe('buildQuery', () => { - it('should add post-processing and ignore duplicate metrics', () => { - const query = buildQuery({ - ...basicFormData, - query_mode: QueryMode.aggregate, - metrics: ['aaa', 'aaa'], - percent_metrics: ['bbb', 'bbb'], - }).queries[0]; - expect(query.metrics).toEqual(['aaa', 'bbb']); - expect(query.post_processing).toEqual([ - { - operation: 'contribution', - options: { - columns: ['bbb'], - rename_columns: ['%bbb'], - }, - }, - ]); - }); - - it('should not add metrics in raw records mode', () => { - const query = buildQuery({ - ...basicFormData, - query_mode: QueryMode.raw, - columns: ['a'], - metrics: ['aaa', 'aaa'], - percent_metrics: ['bbb', 'bbb'], - }).queries[0]; - expect(query.metrics).toBeUndefined(); - expect(query.post_processing).toEqual([]); - }); - - it('should not add post-processing when there is no percent metric', () => { - const query = buildQuery({ - ...basicFormData, - query_mode: QueryMode.aggregate, - metrics: ['aaa'], - percent_metrics: [], - }).queries[0]; - expect(query.metrics).toEqual(['aaa']); - expect(query.post_processing).toEqual([]); - }); - - it('should not add post-processing in raw records mode', () => { - const query = buildQuery({ - ...basicFormData, - query_mode: QueryMode.raw, - metrics: ['aaa'], - columns: ['rawcol'], - percent_metrics: ['ccc'], - }).queries[0]; - expect(query.metrics).toBeUndefined(); - expect(query.columns).toEqual(['rawcol']); - expect(query.post_processing).toEqual([]); - }); - it('should prefer extra_form_data.time_grain_sqla over formData.time_grain_sqla', () => { - Object.defineProperty(supersetCoreModule, 'hasGenericChartAxes', { - value: true, - }); - const query = buildQuery({ - ...basicFormData, - groupby: ['col1'], - query_mode: QueryMode.aggregate, - time_grain_sqla: TimeGranularity.MONTH, - extra_form_data: { time_grain_sqla: TimeGranularity.QUARTER }, - temporal_columns_lookup: { col1: true }, - }).queries[0]; - expect(query.columns?.[0]).toEqual({ - timeGrain: TimeGranularity.QUARTER, - columnType: 'BASE_AXIS', - sqlExpression: 'col1', - label: 'col1', - expressionType: 'SQL', - }); - }); - it('should fallback to formData.time_grain_sqla if extra_form_data.time_grain_sqla is not set', () => { - Object.defineProperty(supersetCoreModule, 'hasGenericChartAxes', { - value: true, - }); - const query = buildQuery({ - ...basicFormData, - time_grain_sqla: TimeGranularity.MONTH, - groupby: ['col1'], - query_mode: QueryMode.aggregate, - temporal_columns_lookup: { col1: true }, - }).queries[0]; - expect(query.columns?.[0]).toEqual({ - timeGrain: TimeGranularity.MONTH, - columnType: 'BASE_AXIS', - sqlExpression: 'col1', - label: 'col1', - expressionType: 'SQL', - }); - }); - }); -}); diff --git a/superset-frontend/src/katalon/chart-table/test/enzyme.tsx b/superset-frontend/src/katalon/chart-table/test/enzyme.tsx deleted file mode 100644 index afd95b5b6ebab..0000000000000 --- a/superset-frontend/src/katalon/chart-table/test/enzyme.tsx +++ /dev/null @@ -1,67 +0,0 @@ -/** - * 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. - */ -import React, { ReactElement } from 'react'; -import { shallow as enzymeShallow, mount as enzymeMount } from 'enzyme'; -import { - EmotionCacheProvider, - createEmotionCache, - supersetTheme, - ThemeProvider, -} from '@superset-ui/core'; - -const emotionCache = createEmotionCache({ - key: 'test', -}); - -type optionsType = { - wrappingComponentProps?: any; - wrappingComponent?: ReactElement; - context?: any; -}; - -export function ProviderWrapper(props: any) { - const { children, theme = supersetTheme } = props; - return ( - - {children} - - ); -} - -export function mount(component: ReactElement, options: optionsType = {}) { - return enzymeMount(component, { - ...options, - wrappingComponent: ProviderWrapper, - wrappingComponentProps: { - theme: supersetTheme, - ...options?.wrappingComponentProps, - }, - }); -} - -export function shallow(component: ReactElement, options: optionsType = {}) { - return enzymeShallow(component, { - ...options, - wrappingComponent: ProviderWrapper, - wrappingComponentProps: { - theme: supersetTheme, - ...options?.wrappingComponentProps, - }, - }).dive(); -} diff --git a/superset-frontend/src/katalon/chart-table/test/sortAlphanumericCaseInsensitive.test.ts b/superset-frontend/src/katalon/chart-table/test/sortAlphanumericCaseInsensitive.test.ts deleted file mode 100644 index 356596ec21061..0000000000000 --- a/superset-frontend/src/katalon/chart-table/test/sortAlphanumericCaseInsensitive.test.ts +++ /dev/null @@ -1,243 +0,0 @@ -/** - * 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. - */ - -import { defaultOrderByFn, Row } from 'react-table'; -import { sortAlphanumericCaseInsensitive } from '../src/DataTable/utils/sortAlphanumericCaseInsensitive'; - -type RecursivePartial = { - [P in keyof T]?: T[P] | RecursivePartial; -}; - -const testData = [ - { - values: { - col: 'test value', - }, - }, - { - values: { - col: 'a lowercase test value', - }, - }, - { - values: { - col: '5', - }, - }, - { - values: { - col: NaN, - }, - }, - { - values: { - col: '1234', - }, - }, - { - values: { - col: Infinity, - }, - }, - { - values: { - col: '.!# value starting with non-letter characters', - }, - }, - { - values: { - col: 'An uppercase test value', - }, - }, - { - values: { - col: undefined, - }, - }, - { - values: { - col: null, - }, - }, -]; - -describe('sortAlphanumericCaseInsensitive', () => { - it('Sort rows', () => { - const sorted = [...testData].sort((a, b) => - // @ts-ignore - sortAlphanumericCaseInsensitive(a, b, 'col'), - ); - - expect(sorted).toEqual([ - { - values: { - col: null, - }, - }, - { - values: { - col: undefined, - }, - }, - { - values: { - col: Infinity, - }, - }, - { - values: { - col: NaN, - }, - }, - { - values: { - col: '.!# value starting with non-letter characters', - }, - }, - { - values: { - col: '1234', - }, - }, - { - values: { - col: '5', - }, - }, - { - values: { - col: 'a lowercase test value', - }, - }, - { - values: { - col: 'An uppercase test value', - }, - }, - { - values: { - col: 'test value', - }, - }, - ]); - }); -}); - -const testDataMulti: Array>> = [ - { - values: { - colA: 'group 1', - colB: '10', - }, - }, - { - values: { - colA: 'group 1', - colB: '15', - }, - }, - { - values: { - colA: 'group 1', - colB: '20', - }, - }, - { - values: { - colA: 'group 2', - colB: '10', - }, - }, - { - values: { - colA: 'group 3', - colB: '10', - }, - }, - { - values: { - colA: 'group 3', - colB: '15', - }, - }, - { - values: { - colA: 'group 3', - colB: '10', - }, - }, -]; - -describe('sortAlphanumericCaseInsensitiveMulti', () => { - it('Sort rows', () => { - const sorted = defaultOrderByFn( - [...testDataMulti] as Array>, - [ - (a, b) => sortAlphanumericCaseInsensitive(a, b, 'colA'), - (a, b) => sortAlphanumericCaseInsensitive(a, b, 'colB'), - ], - [true, false], - ); - - expect(sorted).toEqual([ - { - values: { - colA: 'group 1', - colB: '20', - }, - }, - { - values: { - colA: 'group 1', - colB: '15', - }, - }, - { - values: { - colA: 'group 1', - colB: '10', - }, - }, - { - values: { - colA: 'group 2', - colB: '10', - }, - }, - { - values: { - colA: 'group 3', - colB: '15', - }, - }, - { - values: { - colA: 'group 3', - colB: '10', - }, - }, - { - values: { - colA: 'group 3', - colB: '10', - }, - }, - ]); - }); -}); diff --git a/superset-frontend/src/katalon/chart-table/test/testData.ts b/superset-frontend/src/katalon/chart-table/test/testData.ts deleted file mode 100644 index 1f255703f57c1..0000000000000 --- a/superset-frontend/src/katalon/chart-table/test/testData.ts +++ /dev/null @@ -1,230 +0,0 @@ -/** - * 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. - */ -import { - ChartDataResponseResult, - ChartProps, - DatasourceType, - GenericDataType, - QueryMode, - supersetTheme, -} from '@superset-ui/core'; -import { TableChartProps, TableChartFormData } from '../src/types'; - -const basicFormData: TableChartFormData = { - datasource: '1__abc', - viz_type: 'table', - align_pn: false, - color_pn: false, - show_cell_bars: true, - include_search: false, - order_desc: true, - page_length: 20, - metrics: [], - percent_metrics: null, - timeseries_limit_metric: '', - table_filter: false, - table_timestamp_format: '%Y-%m-%d %H:%M:%S', -}; - -const basicChartProps = { - width: 200, - height: 500, - datasource: { - id: 0, - name: '', - type: DatasourceType.Table, - columns: [], - metrics: [], - columnFormats: {}, - verboseMap: {}, - }, - hooks: {}, - initialValues: {}, - queriesData: [ - { - data: { - columns: [], - records: [], - }, - }, - ], - formData: basicFormData, - theme: supersetTheme, -}; - -const basicQueryResult: ChartDataResponseResult = { - annotation_data: null, - cache_key: null, - cached_dttm: null, - cache_timeout: null, - data: [], - colnames: [], - coltypes: [], - error: null, - is_cached: false, - query: 'SELECT ...', - rowcount: 100, - stacktrace: null, - status: 'success', - from_dttm: null, - to_dttm: null, -}; - -/** - * Basic data input - */ -const basic: TableChartProps = { - ...new ChartProps(basicChartProps), - queriesData: [ - { - ...basicQueryResult, - colnames: ['__timestamp', 'name', 'sum__num', 'abc.com'], - coltypes: [ - GenericDataType.TEMPORAL, - GenericDataType.STRING, - GenericDataType.NUMERIC, - GenericDataType.STRING, - ], - data: [ - { - __timestamp: '2020-01-01T12:34:56', - name: 'Michael', - sum__num: 2467063, - '%pct_nice': 0.123456, - 'abc.com': 'foo', - }, - { - __timestamp: 1585932584140, - name: 'Joe', - sum__num: 2467, - '%pct_nice': 0.00001, - 'abc.com': 'bar', - }, - { - __timestamp: null, - name: 'Maria', - sum__num: 12342, - '%pct_nice': 0.341, - 'abc.com': 'baz', - }, - ], - }, - ], -}; - -/** - * Advanced data input with - * - verbose map - * - metric columns - */ -const advanced: TableChartProps = { - ...basic, - datasource: { - ...basic.datasource, - verboseMap: { - sum__num: 'Sum of Num', - }, - }, - rawFormData: { - ...basicFormData, - metrics: ['sum__num'], - percent_metrics: ['pct_nice'], - column_config: { - name: { - d3NumberFormat: '.3s', - }, - sum__num: { - d3NumberFormat: '.3s', - }, - pct_nice: { - d3NumberFormat: '.3s', - }, - 'abc.com': { - d3NumberFormat: '.3s', - }, - }, - }, - queriesData: [ - { - ...basicQueryResult, - colnames: ['name', 'sum__num', '%pct_nice'], - coltypes: [ - GenericDataType.STRING, - GenericDataType.NUMERIC, - GenericDataType.NUMERIC, - ], - data: [...(basic.queriesData[0].data || [])], - }, - ], -}; - -const raw = { - ...advanced, - rawFormData: { - ...advanced.rawFormData, - query_mode: QueryMode.raw, - columns: ['num'], - }, - queriesData: [ - { - ...basicQueryResult, - colnames: ['num'], - coltypes: [GenericDataType.NUMERIC], - data: [ - { - num: 1234, - }, - { - num: 10000, - }, - { - num: 0, - }, - ], - }, - ], -}; - -const advancedWithCurrency = { - ...advanced, - datasource: { - ...advanced.datasource, - currencyFormats: { - sum__num: { symbol: 'USD', symbolPosition: 'prefix' }, - }, - }, -}; - -const empty = { - ...advanced, - queriesData: [ - { - ...advanced.queriesData[0], - data: [], - }, - ], -}; - -export default { - basic, - advanced, - advancedWithCurrency, - empty, - raw, -}; diff --git a/superset-frontend/src/katalon/chart-table/test/tsconfig.json b/superset-frontend/src/katalon/chart-table/test/tsconfig.json deleted file mode 100644 index 237243534a93c..0000000000000 --- a/superset-frontend/src/katalon/chart-table/test/tsconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "compilerOptions": { - "composite": false, - "emitDeclarationOnly": false, - "noEmit": true, - "rootDir": "../../../" - }, - "extends": "../../../tsconfig.json", - "include": [ - "**/*", - "../types/**/*", - "../../../types/**/*" - ], - "references": [ - { - "path": ".." - } - ] -} diff --git a/superset-frontend/src/katalon/chart-table/types/external.d.ts b/superset-frontend/src/katalon/chart-table/types/external.d.ts deleted file mode 100644 index eb7f1895cb717..0000000000000 --- a/superset-frontend/src/katalon/chart-table/types/external.d.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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. - */ - -declare module '*.png'; -declare module '*.jpg'; -declare module 'regenerator-runtime/runtime'; diff --git a/superset-frontend/src/visualizations/presets/MainPreset.js b/superset-frontend/src/visualizations/presets/MainPreset.js index 6afc6cf40fbe1..42be2e79c4b75 100644 --- a/superset-frontend/src/visualizations/presets/MainPreset.js +++ b/superset-frontend/src/visualizations/presets/MainPreset.js @@ -85,7 +85,7 @@ import { HandlebarsChartPlugin } from '@superset-ui/plugin-chart-handlebars'; import TableChartPlugin from '@superset-ui/plugin-chart-table'; import FilterBoxChartPlugin from '../FilterBox/FilterBoxChartPlugin'; import TimeTableChartPlugin from '../TimeTable'; -import KatalonChartTable from '../../katalon/chart-table/src'; +import KatalonChartTable from '../../katalon/DataTable'; export default class MainPreset extends Preset { constructor() {