diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/chart/registries/ChartBuildQueryRegistrySingleton.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/chart/registries/ChartBuildQueryRegistrySingleton.ts index 3e7da4c38ec7..0092de2e3b5f 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/chart/registries/ChartBuildQueryRegistrySingleton.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/chart/registries/ChartBuildQueryRegistrySingleton.ts @@ -1,7 +1,18 @@ -import { Registry, makeSingleton, OverwritePolicy, QueryContext } from '../..'; +import { Registry, makeSingleton, OverwritePolicy, QueryContext, SetDataMaskHook } from '../..'; // Ideally this would be -type BuildQuery = (formData: any) => QueryContext; +export type BuildQuery = ( + formData: T, + options?: { + extras?: { + cachedChanges?: any; + }; + hooks?: { + setDataMask: SetDataMaskHook; + setCachedChanges: (newChanges: any) => void; + }; + }, +) => QueryContext; class ChartBuildQueryRegistry extends Registry { constructor() { diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/chart/types/TransformFunction.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/chart/types/TransformFunction.ts index 94e197fa1b88..ea07000e486b 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/chart/types/TransformFunction.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/chart/types/TransformFunction.ts @@ -1,4 +1,4 @@ -import { QueryFormData, QueryContext } from '../..'; +import { QueryFormData, QueryContext, SetDataMaskHook } from '../..'; import ChartProps from '../models/ChartProps'; import { PlainObject } from './Base'; @@ -10,6 +10,17 @@ export type PreTransformProps = TransformFunction; export type TransformProps = TransformFunction; export type PostTransformProps = TransformFunction; -export type BuildQueryFunction = (formData: T) => QueryContext; +export type BuildQueryFunction = ( + formData: T, + options?: { + extras?: { + cachedChanges?: any; + }; + hooks?: { + setDataMask: SetDataMaskHook; + setCachedChanges: (newChanges: any) => void; + }; + }, +) => QueryContext; export default {}; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/buildQueryContext.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/buildQueryContext.ts index bf9880d955c1..c4621c2f6816 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/buildQueryContext.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/buildQueryContext.ts @@ -2,26 +2,46 @@ import buildQueryObject from './buildQueryObject'; import DatasourceKey from './DatasourceKey'; import { QueryFieldAliases, QueryFormData } from './types/QueryFormData'; import { QueryContext, QueryObject } from './types/Query'; +import { SetDataMaskHook } from '../chart'; -const WRAP_IN_ARRAY = (baseQueryObject: QueryObject) => [baseQueryObject]; +const WRAP_IN_ARRAY = ( + baseQueryObject: QueryObject, + options?: { + extras?: { + cachedChanges?: any; + }; + hooks?: { + setDataMask: SetDataMaskHook; + setCachedChanges: (newChanges: any) => void; + }; + }, +) => [baseQueryObject]; -export type BuildFinalQuerieObjects = (baseQueryObject: QueryObject) => QueryObject[]; +export type BuildFinalQueryObjects = (baseQueryObject: QueryObject) => QueryObject[]; export default function buildQueryContext( formData: QueryFormData, options?: | { - buildQuery?: BuildFinalQuerieObjects; + buildQuery?: BuildFinalQueryObjects; queryFields?: QueryFieldAliases; + hooks?: { setDataMask: SetDataMaskHook }; } - | BuildFinalQuerieObjects, + | BuildFinalQueryObjects, ): QueryContext { - const { queryFields, buildQuery = WRAP_IN_ARRAY } = + const { queryFields, buildQuery = WRAP_IN_ARRAY, hooks = {} } = typeof options === 'function' ? { buildQuery: options, queryFields: {} } : options || {}; return { datasource: new DatasourceKey(formData.datasource).toObject(), force: formData.force || false, - queries: buildQuery(buildQueryObject(formData, queryFields)), + queries: buildQuery(buildQueryObject(formData, queryFields), { + extras: {}, + hooks: { + setDataMask: () => {}, + setCachedChanges: () => {}, + ...hooks, + }, + }), result_format: formData.result_format || 'json', result_type: formData.result_type || 'full', }; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/DataTable.tsx b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/DataTable.tsx index 4f5e01387d6c..0048a4a4df6c 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/DataTable.tsx +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/DataTable.tsx @@ -36,14 +36,11 @@ import { Row, } from 'react-table'; import { matchSorter, rankings } from 'match-sorter'; -import { SetDataMaskHook } from '@superset-ui/core'; import GlobalFilter, { GlobalFilterProps } from './components/GlobalFilter'; import SelectPageSize, { SelectPageSizeProps, SizeOption } from './components/SelectPageSize'; import SimplePagination from './components/Pagination'; import useSticky from './hooks/useSticky'; -import { updateExternalFormData } from './utils/externalAPIs'; -import ServerPagination from './components/ServerPagination'; -import { ServerPage } from '../types'; +import { PAGE_SIZE_OPTIONS } from '../consts'; export interface DataTableProps extends TableOptions { tableClassName?: string; @@ -55,12 +52,12 @@ export interface DataTableProps extends TableOptions { width?: string | number; height?: string | number; serverPagination?: boolean; - setDataMask: SetDataMaskHook; - currentPage?: number; + onServerPaginationChange: (pageNumber: number, pageSize: number) => void; + serverPaginationData: { pageSize?: number; currentPage?: number }; pageSize?: number; noResults?: string | ((filterString: string) => ReactNode); sticky?: boolean; - showNextButton: boolean; + rowCount: number; wrapperRef?: MutableRefObject; } @@ -73,17 +70,17 @@ export default function DataTable({ tableClassName, columns, data, - currentPage = 0, + serverPaginationData, width: initialWidth = '100%', height: initialHeight = 300, pageSize: initialPageSize = 0, initialState: initialState_ = {}, - pageSizeOptions = [10, 25, 50, 100, 200], + pageSizeOptions = PAGE_SIZE_OPTIONS, maxPageItemCount = 9, sticky: doSticky, searchInput = true, - setDataMask, - showNextButton, + onServerPaginationChange, + rowCount, selectPageSize, noResults: noResultsText = 'No data found', hooks, @@ -98,7 +95,7 @@ export default function DataTable({ doSticky ? useSticky : [], hooks || [], ].flat(); - const resultsSize = data.length; + 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 @@ -129,7 +126,16 @@ export default function DataTable({ } return undefined; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [initialHeight, initialWidth, wrapperRef, hasPagination, hasGlobalControl, showNextButton]); + }, [ + initialHeight, + initialWidth, + wrapperRef, + hasPagination, + hasGlobalControl, + paginationRef, + resultsSize, + JSON.stringify(serverPaginationData), + ]); const defaultGlobalFilter: FilterType = useCallback( (rows: Row[], columnIds: IdType[], filterValue: string) => { @@ -170,7 +176,7 @@ export default function DataTable({ // make setPageSize accept 0 const setPageSize = (size: number) => { if (serverPagination) { - updateExternalFormData(setDataMask, 0, size); + onServerPaginationChange(0, size); } // keep the original size if data is empty if (size || resultsSize !== 0) { @@ -224,7 +230,7 @@ export default function DataTable({ ); - // force upate the pageSize when it's been update from the initial state + // 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, @@ -235,16 +241,29 @@ export default function DataTable({ setPageSize(initialPageSize); } - const goToBEPage = (direction: ServerPage) => { - updateExternalFormData( - setDataMask, - direction === ServerPage.NEXT ? currentPage + 1 : currentPage - 1, - pageSize, - ); - }; - 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 ? ( @@ -254,7 +273,7 @@ export default function DataTable({ {hasPagination ? ( ({
) : null} {wrapStickyTable ? wrapStickyTable(renderTable) : renderTable()} - {serverPagination && ( - - )} - {!serverPagination && hasPagination ? ( + {hasPagination && resultPageCount > 1 ? ( ) : null} diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/components/SelectPageSize.tsx b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/components/SelectPageSize.tsx index c098e2c5c98b..5355b85f42c4 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/components/SelectPageSize.tsx +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/components/SelectPageSize.tsx @@ -17,8 +17,9 @@ * under the License. */ import React from 'react'; +import { formatSelectOptions } from '@superset-ui/chart-controls'; -export type SizeOption = number | [number, string]; +export type SizeOption = [number, string]; export interface SelectPageSizeRendererProps { current: number; @@ -81,7 +82,7 @@ export default React.memo(function SelectPageSize({ options.splice( sizeOptionValues.findIndex(x => x > currentSize), 0, - currentSize, + formatSelectOptions([currentSize])[0], ); } const current = currentSize === undefined ? sizeOptionValues[0] : currentSize; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/components/ServerPagination.tsx b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/components/ServerPagination.tsx deleted file mode 100644 index 538dba66d03f..000000000000 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/components/ServerPagination.tsx +++ /dev/null @@ -1,58 +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 } from 'react'; -import { t } from '@superset-ui/core'; -import { ServerPage } from '../../types'; - -export interface ServerPaginationProps { - showNext: boolean; - showPrevious: boolean; - onPageChange: (direction: ServerPage) => void; // `page` next/previous - style?: CSSProperties; -} - -export default React.memo( - React.forwardRef(function ServerPagination( - { style, onPageChange, showNext, showPrevious }: ServerPaginationProps, - ref: React.Ref, - ) { - const getButton = (name: ServerPage, label: string) => ( -
  • - { - e.preventDefault(); - onPageChange(name); - }} - > - {label} - -
  • - ); - return ( -
    -
      - {showPrevious && getButton(ServerPage.PREVIOUS, t('table.previous_page'))} - {showNext && getButton(ServerPage.NEXT, t('table.next_page'))} -
    -
    - ); - }), -); diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/utils/externalAPIs.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/utils/externalAPIs.ts index d87e3ffebd50..ab910621c161 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/utils/externalAPIs.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/utils/externalAPIs.ts @@ -20,7 +20,7 @@ import { SetDataMaskHook } from '@superset-ui/core'; export const updateExternalFormData = ( - setDataMask: SetDataMaskHook, + setDataMask: SetDataMaskHook = () => {}, pageNumber: number, pageSize: number, ) => @@ -29,7 +29,7 @@ export const updateExternalFormData = ( extraFormData: { custom_form_data: { row_offset: pageNumber * pageSize, - row_limit: pageSize + 1, + row_limit: pageSize, }, }, currentState: { diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/TableChart.tsx b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/TableChart.tsx index 41c1611e29dd..08bf8b524c7a 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/TableChart.tsx +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/TableChart.tsx @@ -32,7 +32,8 @@ import DataTable, { import Styles from './Styles'; import formatValue from './utils/formatValue'; -import { PAGE_SIZE_OPTIONS } from './controlPanel'; +import { PAGE_SIZE_OPTIONS } from './consts'; +import { updateExternalFormData } from './DataTable/utils/externalAPIs'; type ValueRange = [number, number]; @@ -147,14 +148,14 @@ export default function TableChart( width, data, isRawRecords, - showNextButton, + rowCount = 0, columns: columnsMeta, alignPositiveNegative = false, colorPositiveNegative = false, includeSearch = false, pageSize = 0, serverPagination = false, - currentPage, + serverPaginationData, setDataMask, showCellBars = true, emitFilter = false, @@ -167,11 +168,12 @@ export default function TableChart( const [filters, setFilters] = useState(initialFilters); // only take relevant page size options - const pageSizeOptions = useMemo( - () => - PAGE_SIZE_OPTIONS.filter(([n]) => n <= 2 * data.length || serverPagination) as SizeOption[], - [data.length], - ); + const pageSizeOptions = useMemo(() => { + const getServerPagination = (n: number) => n <= rowCount; + return PAGE_SIZE_OPTIONS.filter(([n]) => + serverPagination ? getServerPagination(n) : n <= 2 * data.length, + ) as SizeOption[]; + }, [data.length, rowCount]); const getValueRange = useCallback( function getValueRange(key: string) { @@ -284,20 +286,24 @@ export default function TableChart( const columns = useMemo(() => columnsMeta.map(getColumnConfigs), [columnsMeta, getColumnConfigs]); + const handleServerPaginationChange = (pageNumber: number, pageSize: number) => { + updateExternalFormData(setDataMask, pageNumber, pageSize); + }; + return ( columns={columns} data={data} - showNextButton={showNextButton} + rowCount={rowCount} tableClassName="table table-striped table-condensed" pageSize={pageSize} - currentPage={currentPage} + serverPaginationData={serverPaginationData} pageSizeOptions={pageSizeOptions} width={width} height={height} serverPagination={serverPagination} - setDataMask={setDataMask} + onServerPaginationChange={handleServerPaginationChange} // 9 page items in > 340px works well even for 100+ pages maxPageItemCount={width > 340 ? 9 : 7} noResults={(filter: string) => t(filter ? 'No matching records found' : 'No records found')} diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/buildQuery.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/buildQuery.ts index c4074efc80b2..19b264bf644c 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/buildQuery.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/buildQuery.ts @@ -25,7 +25,9 @@ import { QueryObject, } 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, @@ -43,7 +45,7 @@ export function getQueryMode(formData: TableChartFormData) { return hasRawColumns ? QueryMode.raw : QueryMode.aggregate; } -export default function buildQuery(formData: TableChartFormData) { +const buildQuery: BuildQuery = (formData: TableChartFormData, options) => { const { percent_metrics: percentMetrics, order_desc: orderDesc = false } = formData; const queryMode = getQueryMode(formData); const sortByMetric = ensureIsArray(formData.timeseries_limit_metric)[0]; @@ -88,21 +90,60 @@ export default function buildQuery(formData: TableChartFormData) { const moreProps: Partial = {}; if (formDataCopy.server_pagination) { const rowLimit = formDataCopy.extra_form_data?.custom_form_data?.row_limit; - // 1 - means all data - if (rowLimit !== 1) { - moreProps.row_limit = rowLimit ?? formDataCopy.server_page_length + 1; // +1 to determine if exists next page - } + moreProps.row_limit = rowLimit ?? formDataCopy.server_page_length; moreProps.row_offset = formDataCopy?.extra_form_data?.custom_form_data?.row_offset ?? 0; } - return [ + let queryObject = { + ...baseQueryObject, + 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 }); + + if (formData.server_pagination) { + return [ + { ...queryObject }, + { ...queryObject, row_limit: 0, row_offset: 0, post_processing: [], is_rowcount: true }, + ]; + } + return [queryObject]; + }); +}; + +// Use this closure to cache changing of external filters, if we have server pagination we need reset page to 0, after +// external filter changed +const cachedBuildQuery = (): BuildQuery => { + let cachedChanges: any = {}; + const setCachedChanges = (newChanges: any) => { + cachedChanges = { ...cachedChanges, ...newChanges }; + }; + + return (formData, options) => + buildQuery( + { ...formData }, { - ...baseQueryObject, - orderby, - metrics, - post_processing: postProcessing, - ...moreProps, + extras: { cachedChanges }, + hooks: { + ...options?.hooks, + setDataMask: () => {}, + setCachedChanges, + }, }, - ]; - }); -} + ); +}; + +export default cachedBuildQuery; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/consts.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/consts.ts new file mode 100644 index 000000000000..e370c4b02952 --- /dev/null +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/consts.ts @@ -0,0 +1,32 @@ +/** + * 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/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/controlPanel.tsx b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/controlPanel.tsx index bd2eb9af4d55..a5d55ee783b9 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/controlPanel.tsx +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/controlPanel.tsx @@ -27,7 +27,6 @@ import { QueryFormColumn, } from '@superset-ui/core'; import { - formatSelectOptions, D3_TIME_FORMAT_OPTIONS, ControlConfig, ColumnOption, @@ -39,18 +38,10 @@ import { } from '@superset-ui/chart-controls'; import i18n from './i18n'; +import { PAGE_SIZE_OPTIONS } from './consts'; addLocaleData(i18n); -export const PAGE_SIZE_OPTIONS = formatSelectOptions([ - [0, t('page_size.all')], - 10, - 20, - 50, - 100, - 200, -]); - const QueryModeLabel = { [QueryMode.aggregate]: t('Aggregate'), [QueryMode.raw]: t('Raw Records'), diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/index.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/index.ts index ff4729805410..898717e4773f 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/index.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/index.ts @@ -16,11 +16,11 @@ * specific language governing permissions and limitations * under the License. */ -import { t, ChartMetadata, ChartPlugin } from '@superset-ui/core'; +import { t, ChartMetadata, ChartPlugin, BuildQueryFunction } from '@superset-ui/core'; import transformProps from './transformProps'; import thumbnail from './images/thumbnail.png'; import controlPanel from './controlPanel'; -import buildQuery from './buildQuery'; +import cachedBuildQuery from './buildQuery'; import { TableChartFormData, TableChartProps } from './types'; // must export something for the module to be exist in dev mode @@ -41,7 +41,7 @@ export default class TableChartPlugin extends ChartPlugin, }); } } diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/transformProps.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/transformProps.ts index 8973f2436976..360300fb895b 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/transformProps.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/transformProps.ts @@ -19,21 +19,21 @@ import memoizeOne from 'memoize-one'; import { DataRecord, + GenericDataType, + getMetricLabel, getNumberFormatter, - NumberFormats, getTimeFormatter, - smartDateFormatter, getTimeFormatterForGranularity, - TimeFormatter, - TimeFormats, - GenericDataType, - getMetricLabel, + NumberFormats, QueryMode, + smartDateFormatter, + TimeFormats, + TimeFormatter, } from '@superset-ui/core'; import isEqualColumns from './utils/isEqualColumns'; import DateWithFormatter from './utils/DateWithFormatter'; -import { TableChartProps, TableChartTransformedProps, DataColumnMeta } from './types'; +import { DataColumnMeta, TableChartProps, TableChartTransformedProps } from './types'; const { PERCENT_3_POINT } = NumberFormats; const { DATABASE_DATETIME } = TimeFormats; @@ -168,14 +168,14 @@ const getPageSize = ( return numRecords * numColumns > 5000 ? 200 : 0; }; -export default function transformProps(chartProps: TableChartProps): TableChartTransformedProps { +const transformProps = (chartProps: TableChartProps): TableChartTransformedProps => { const { height, width, rawFormData: formData, queriesData, initialValues: filters = {}, - ownCurrentState: { currentPage, pageSize }, + ownCurrentState: serverPaginationData = {}, hooks: { onAddFilter: onChangeFilter, setDataMask = () => {} }, } = chartProps; @@ -193,14 +193,8 @@ export default function transformProps(chartProps: TableChartProps): TableChartT } = formData; const [metrics, percentMetrics, columns] = processColumns(chartProps); - let data = queriesData?.[0]?.data; - let showNextButton = false; - // We do request +1 items for BE pagination to know if how `next` button - if (serverPagination && data.length === (pageSize ?? serverPageLength) + 1) { - data.pop(); - showNextButton = true; - } - data = processDataRecords(data, columns); + const data = processDataRecords(queriesData?.[0]?.data, columns); + const rowCount = queriesData?.[1]?.data?.[0]?.rowcount as number; return { height, @@ -211,14 +205,14 @@ export default function transformProps(chartProps: TableChartProps): TableChartT serverPagination, metrics, percentMetrics, - currentPage, + serverPaginationData, setDataMask, alignPositiveNegative, colorPositiveNegative, showCellBars, sortDesc, includeSearch, - showNextButton, + rowCount, pageSize: serverPagination ? serverPageLength : getPageSize(pageLength, data.length, columns.length), @@ -226,4 +220,6 @@ export default function transformProps(chartProps: TableChartProps): TableChartT emitFilter: tableFilter === true, onChangeFilter, }; -} +}; + +export default transformProps; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/types.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/types.ts index 69465334cb10..8b47a3c15cce 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/types.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/types.ts @@ -81,9 +81,9 @@ export interface TableChartProps extends ChartProps { export interface TableChartTransformedProps { height: number; width: number; - showNextButton: boolean; + rowCount?: number; serverPagination: boolean; - currentPage?: number; + serverPaginationData: { pageSize?: number; currentPage?: number }; setDataMask: SetDataMaskHook; isRawRecords?: boolean; data: D[]; @@ -104,9 +104,4 @@ export interface TableChartTransformedProps { onChangeFilter?: ChartProps['hooks']['onAddFilter']; } -export enum ServerPage { - NEXT = 'next', - PREVIOUS = 'previous', -} - export default {}; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/test/buildQuery.test.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/test/buildQuery.test.ts index e10c1bbe71a1..015cc0a9e556 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/test/buildQuery.test.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/test/buildQuery.test.ts @@ -17,7 +17,7 @@ * under the License. */ import { QueryMode } from '@superset-ui/core'; -import buildQuery from '../src/buildQuery'; +import buildQueryCached from '../src/buildQuery'; import { TableChartFormData } from '../src/types'; const basicFormData: TableChartFormData = { @@ -28,7 +28,7 @@ const basicFormData: TableChartFormData = { describe('plugin-chart-table', () => { describe('buildQuery', () => { it('should add post-processing in aggregate mode', () => { - const query = buildQuery({ + const query = buildQueryCached()({ ...basicFormData, query_mode: QueryMode.aggregate, metrics: ['aaa'], @@ -47,7 +47,7 @@ describe('plugin-chart-table', () => { }); it('should not add post-processing when there is not percent metric', () => { - const query = buildQuery({ + const query = buildQueryCached()({ ...basicFormData, query_mode: QueryMode.aggregate, metrics: ['aaa'], @@ -58,7 +58,7 @@ describe('plugin-chart-table', () => { }); it('should not add post-processing in raw records mode', () => { - const query = buildQuery({ + const query = buildQueryCached()({ ...basicFormData, query_mode: QueryMode.raw, metrics: ['aaa'],