diff --git a/superset-frontend/src/dataMask/types.ts b/superset-frontend/packages/superset-ui-core/src/dashboard/index.ts similarity index 70% rename from superset-frontend/src/dataMask/types.ts rename to superset-frontend/packages/superset-ui-core/src/dashboard/index.ts index 95d2073a07d0..10b785cba877 100644 --- a/superset-frontend/src/dataMask/types.ts +++ b/superset-frontend/packages/superset-ui-core/src/dashboard/index.ts @@ -16,14 +16,5 @@ * specific language governing permissions and limitations * under the License. */ -import { DataMask } from '@superset-ui/core'; -export enum DataMaskType { - NativeFilters = 'nativeFilters', - CrossFilters = 'crossFilters', -} - -export type DataMaskState = { [id: string]: DataMask }; - -export type DataMaskWithId = { id: string } & DataMask; -export type DataMaskStateWithId = { [filterId: string]: DataMaskWithId }; +export * from './types/Base'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/types.ts b/superset-frontend/packages/superset-ui-core/src/dashboard/types/Base.ts similarity index 68% rename from superset-frontend/src/dashboard/components/nativeFilters/types.ts rename to superset-frontend/packages/superset-ui-core/src/dashboard/types/Base.ts index 85f1941e0da0..fbd631d25914 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/types.ts +++ b/superset-frontend/packages/superset-ui-core/src/dashboard/types/Base.ts @@ -19,20 +19,20 @@ import { AdhocFilter, DataMask } from '@superset-ui/core'; -export interface Column { +export interface NativeFilterColumn { name: string; displayName?: string; } -export interface Scope { +export interface NativeFilterScope { rootPath: string[]; excluded: number[]; } /** The target of a filter is the datasource/column being filtered */ -export interface Target { +export interface NativeFilterTarget { datasetId: number; - column: Column; + column: NativeFilterColumn; // maybe someday support this? // show values from these columns in the filter options selector @@ -44,16 +44,37 @@ export enum NativeFilterType { DIVIDER = 'DIVIDER', } +export enum DataMaskType { + NativeFilters = 'nativeFilters', + CrossFilters = 'crossFilters', +} + +export type DataMaskState = { [id: string]: DataMask }; + +export type DataMaskWithId = { id: string } & DataMask; +export type DataMaskStateWithId = { [filterId: string]: DataMaskWithId }; + +export type FilterSet = { + id: number; + name: string; + nativeFilters: Filters; + dataMask: DataMaskStateWithId; +}; + +export type FilterSets = { + [filtersSetId: string]: FilterSet; +}; + export interface Filter { cascadeParentIds: string[]; defaultDataMask: DataMask; id: string; // randomly generated at filter creation name: string; - scope: Scope; + scope: NativeFilterScope; filterType: string; // for now there will only ever be one target // when multiple targets are supported, change this to Target[] - targets: [Partial]; + targets: [Partial]; controlValues: { [key: string]: any; }; @@ -70,6 +91,7 @@ export interface Filter { type: typeof NativeFilterType.NATIVE_FILTER; description: string; } + export interface Divider { id: string; title: string; @@ -78,3 +100,18 @@ export interface Divider { } export type FilterConfiguration = Array; + +export type Filters = { + [filterId: string]: Filter; +}; + +export type NativeFiltersState = { + filters: Filters; + filterSets: FilterSets; + focusedFilterId?: string; +}; + +export type DashboardComponentMetadata = { + nativeFilters: NativeFiltersState; + dataMask: DataMaskStateWithId; +}; diff --git a/superset-frontend/packages/superset-ui-core/src/index.ts b/superset-frontend/packages/superset-ui-core/src/index.ts index 7ea8f2aaa247..23d972fc9a05 100644 --- a/superset-frontend/packages/superset-ui-core/src/index.ts +++ b/superset-frontend/packages/superset-ui-core/src/index.ts @@ -16,11 +16,13 @@ * specific language governing permissions and limitations * under the License. */ + export * from './models'; export * from './utils'; export * from './types'; export * from './translation'; export * from './connection'; +export * from './dashboard'; export * from './dynamic-plugins'; export * from './query'; export * from './number-format'; diff --git a/superset-frontend/spec/fixtures/mockNativeFilters.ts b/superset-frontend/spec/fixtures/mockNativeFilters.ts index 1381ff4322e0..516a2c5aa3b1 100644 --- a/superset-frontend/spec/fixtures/mockNativeFilters.ts +++ b/superset-frontend/spec/fixtures/mockNativeFilters.ts @@ -16,10 +16,12 @@ * specific language governing permissions and limitations * under the License. */ -import { ExtraFormData } from '@superset-ui/core'; -import { NativeFilterType } from 'src/dashboard/components/nativeFilters/types'; -import { NativeFiltersState } from 'src/dashboard/reducers/types'; -import { DataMaskStateWithId } from '../../src/dataMask/types'; +import { + DataMaskStateWithId, + ExtraFormData, + NativeFiltersState, + NativeFilterType, +} from '@superset-ui/core'; export const nativeFilters: NativeFiltersState = { filterSets: {}, diff --git a/superset-frontend/src/dashboard/actions/nativeFilters.ts b/superset-frontend/src/dashboard/actions/nativeFilters.ts index 337d3044a541..71cc01d99681 100644 --- a/superset-frontend/src/dashboard/actions/nativeFilters.ts +++ b/superset-frontend/src/dashboard/actions/nativeFilters.ts @@ -17,21 +17,21 @@ * under the License. */ -import { makeApi } from '@superset-ui/core'; +import { + FilterConfiguration, + Filters, + FilterSet, + FilterSets, + makeApi, +} from '@superset-ui/core'; import { Dispatch } from 'redux'; -import { FilterConfiguration } from 'src/dashboard/components/nativeFilters/types'; import { SET_DATA_MASK_FOR_FILTER_CONFIG_FAIL, setDataMaskForFilterConfigComplete, } from 'src/dataMask/actions'; import { HYDRATE_DASHBOARD } from './hydrate'; import { dashboardInfoChanged } from './dashboardInfo'; -import { - Filters, - FilterSet, - FilterSetFullData, - FilterSets, -} from '../reducers/types'; +import { FilterSetFullData } from '../reducers/types'; import { DashboardInfo, RootState } from '../types'; export const SET_FILTER_CONFIG_BEGIN = 'SET_FILTER_CONFIG_BEGIN'; diff --git a/superset-frontend/src/dashboard/components/BuilderComponentPane.tsx b/superset-frontend/src/dashboard/components/BuilderComponentPane.tsx index 3d2cbbbda47f..9d2c2fba5ad1 100644 --- a/superset-frontend/src/dashboard/components/BuilderComponentPane.tsx +++ b/superset-frontend/src/dashboard/components/BuilderComponentPane.tsx @@ -31,6 +31,8 @@ import NewRow from './gridComponents/new/NewRow'; import NewTabs from './gridComponents/new/NewTabs'; import NewMarkdown from './gridComponents/new/NewMarkdown'; import SliceAdder from '../containers/SliceAdder'; +import dashboardComponents from '../../visualizations/presets/dashboardComponents'; +import NewDynamicComponent from './gridComponents/new/NewDynamicComponent'; export interface BCPProps { isStandalone: boolean; @@ -106,6 +108,14 @@ const BuilderComponentPane: React.FC = ({ + {dashboardComponents + .getAll() + .map(({ key: componentKey, metadata }) => ( + + ))} ; }; diff --git a/superset-frontend/src/dashboard/components/CrossFilterScopingModal/types.ts b/superset-frontend/src/dashboard/components/CrossFilterScopingModal/types.ts index b56ffc0eea5e..6dfd11f95bb5 100644 --- a/superset-frontend/src/dashboard/components/CrossFilterScopingModal/types.ts +++ b/superset-frontend/src/dashboard/components/CrossFilterScopingModal/types.ts @@ -17,8 +17,8 @@ * under the License. */ -import { Scope } from '../nativeFilters/types'; +import { NativeFilterScope } from '@superset-ui/core'; export type CrossFilterScopingFormType = { - scope: Scope; + scope: NativeFilterScope; }; diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardContainer.tsx b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardContainer.tsx index cce9bf7a0471..aebb2a14071f 100644 --- a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardContainer.tsx +++ b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardContainer.tsx @@ -20,7 +20,7 @@ // when its container size changes, due to e.g., builder side panel opening import React, { FC, useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { FeatureFlag, isFeatureEnabled } from '@superset-ui/core'; +import { FeatureFlag, Filters, isFeatureEnabled } from '@superset-ui/core'; import { ParentSize } from '@vx/responsive'; import Tabs from 'src/components/Tabs'; import DashboardGrid from 'src/dashboard/containers/DashboardGrid'; @@ -31,7 +31,6 @@ import { DASHBOARD_ROOT_DEPTH, } from 'src/dashboard/util/constants'; import { getRootLevelTabIndex, getRootLevelTabsComponent } from './utils'; -import { Filters } from '../../reducers/types'; import { getChartIdsInFilterScope } from '../../util/activeDashboardFilters'; import findTabIndexByComponentId from '../../util/findTabIndexByComponentId'; import { findTabsWithChartsInScope } from '../nativeFilters/utils'; diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/state.ts b/superset-frontend/src/dashboard/components/DashboardBuilder/state.ts index 31cf5ae0feb1..51d255db1044 100644 --- a/superset-frontend/src/dashboard/components/DashboardBuilder/state.ts +++ b/superset-frontend/src/dashboard/components/DashboardBuilder/state.ts @@ -17,6 +17,7 @@ * under the License. */ import { useSelector } from 'react-redux'; +import { Filter } from '@superset-ui/core'; import { FeatureFlag, isFeatureEnabled } from 'src/featureFlags'; import { useCallback, useEffect, useState, useContext } from 'react'; import { URL_PARAMS } from 'src/constants'; @@ -27,7 +28,6 @@ import { useFilters, useNativeFiltersDataMask, } from '../nativeFilters/FilterBar/state'; -import { Filter } from '../nativeFilters/types'; // eslint-disable-next-line import/prefer-default-export export const useNativeFilters = () => { diff --git a/superset-frontend/src/dashboard/components/FiltersBadge/index.tsx b/superset-frontend/src/dashboard/components/FiltersBadge/index.tsx index 921d8db557bd..316534823772 100644 --- a/superset-frontend/src/dashboard/components/FiltersBadge/index.tsx +++ b/superset-frontend/src/dashboard/components/FiltersBadge/index.tsx @@ -20,9 +20,9 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { uniqWith } from 'lodash'; import cx from 'classnames'; +import { DataMaskStateWithId, Filters } from '@superset-ui/core'; import Icons from 'src/components/Icons'; import { usePrevious } from 'src/hooks/usePrevious'; -import { DataMaskStateWithId } from 'src/dataMask/types'; import DetailsPanelPopover from './DetailsPanel'; import { Pill } from './Styles'; import { @@ -38,7 +38,6 @@ import { DashboardLayout, RootState, } from '../../types'; -import { Filters } from '../../reducers/types'; export interface FiltersBadgeProps { chartId: number; diff --git a/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts b/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts index 695e2f94bc79..3eafe248a15b 100644 --- a/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts +++ b/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts @@ -17,19 +17,21 @@ * under the License. */ import { + DataMaskStateWithId, + DataMaskType, ensureIsArray, FeatureFlag, + Filters, FilterState, isFeatureEnabled, + NativeFilterType, } from '@superset-ui/core'; import { NO_TIME_RANGE, TIME_FILTER_MAP } from 'src/explore/constants'; import { getChartIdsInFilterScope } from 'src/dashboard/util/activeDashboardFilters'; -import { ChartConfiguration, Filters } from 'src/dashboard/reducers/types'; -import { DataMaskStateWithId, DataMaskType } from 'src/dataMask/types'; +import { ChartConfiguration } from 'src/dashboard/reducers/types'; import { areObjectsEqual } from 'src/reduxUtils'; import { Layout } from '../../types'; import { getTreeCheckedItems } from '../nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils'; -import { NativeFilterType } from '../nativeFilters/types'; export enum IndicatorStatus { Unset = 'UNSET', diff --git a/superset-frontend/src/dashboard/components/gridComponents/DynamicComponent.tsx b/superset-frontend/src/dashboard/components/gridComponents/DynamicComponent.tsx new file mode 100644 index 000000000000..707597d8c0ca --- /dev/null +++ b/superset-frontend/src/dashboard/components/gridComponents/DynamicComponent.tsx @@ -0,0 +1,177 @@ +/** + * 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, { FC, Suspense } from 'react'; +import { DashboardComponentMetadata, JsonObject, t } from '@superset-ui/core'; +import backgroundStyleOptions from 'src/dashboard/util/backgroundStyleOptions'; +import cx from 'classnames'; +import { useSelector } from 'react-redux'; +import DragDroppable from '../dnd/DragDroppable'; +import { COLUMN_TYPE, ROW_TYPE } from '../../util/componentTypes'; +import WithPopoverMenu from '../menu/WithPopoverMenu'; +import ResizableContainer from '../resizable/ResizableContainer'; +import { + BACKGROUND_TRANSPARENT, + GRID_BASE_UNIT, + GRID_MIN_COLUMN_COUNT, +} from '../../util/constants'; +import HoverMenu from '../menu/HoverMenu'; +import DeleteComponentButton from '../DeleteComponentButton'; +import BackgroundStyleDropdown from '../menu/BackgroundStyleDropdown'; +import dashboardComponents from '../../../visualizations/presets/dashboardComponents'; +import { RootState } from '../../types'; + +type FilterSummaryType = { + component: JsonObject; + parentComponent: JsonObject; + index: number; + depth: number; + handleComponentDrop: (...args: any[]) => any; + editMode: boolean; + columnWidth: number; + availableColumnCount: number; + onResizeStart: Function; + onResizeStop: Function; + onResize: Function; + deleteComponent: Function; + updateComponents: Function; + parentId: number; + id: number; +}; + +const DynamicComponent: FC = ({ + component, + parentComponent, + index, + depth, + handleComponentDrop, + editMode, + columnWidth, + availableColumnCount, + onResizeStart, + onResizeStop, + onResize, + deleteComponent, + parentId, + updateComponents, + id, +}) => { + // inherit the size of parent columns + const widthMultiple = + parentComponent.type === COLUMN_TYPE + ? parentComponent.meta.width || GRID_MIN_COLUMN_COUNT + : component.meta.width || GRID_MIN_COLUMN_COUNT; + + const handleDeleteComponent = () => { + deleteComponent(id, parentId); + }; + + const rowStyle = backgroundStyleOptions.find( + opt => opt.value === (component.meta.background || BACKGROUND_TRANSPARENT), + ); + + const updateMeta = (metaKey: string, nextValue: string | number) => { + updateComponents({ + [component.id]: { + ...component, + meta: { + ...component.meta, + [metaKey]: nextValue, + }, + }, + }); + }; + + const { Component } = dashboardComponents.get(component.meta.componentKey); + const dashboardData = useSelector( + ({ nativeFilters, dataMask }) => ({ + nativeFilters, + dataMask, + }), + ); + + return ( + + {({ dropIndicatorProps, dragSourceRef }) => ( + updateMeta('background', value)} + />, + ]} + editMode={editMode} + > +
+ +
+ {editMode && ( + + + + )} + {t('Loading...')}
}> + + +
+ + + {dropIndicatorProps &&
} + + )} + + ); +}; +export default DynamicComponent; diff --git a/superset-frontend/src/dashboard/components/gridComponents/index.js b/superset-frontend/src/dashboard/components/gridComponents/index.js index ce014f8d57ce..95c524f5f7a6 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/index.js +++ b/superset-frontend/src/dashboard/components/gridComponents/index.js @@ -25,6 +25,7 @@ import { ROW_TYPE, TAB_TYPE, TABS_TYPE, + DYNAMIC_TYPE, } from '../../util/componentTypes'; import ChartHolder from './ChartHolder'; @@ -35,6 +36,7 @@ import Header from './Header'; import Row from './Row'; import Tab from './Tab'; import TabsConnected from './Tabs'; +import DynamicComponent from './DynamicComponent'; export { default as ChartHolder } from './ChartHolder'; export { default as Markdown } from './Markdown'; @@ -44,6 +46,7 @@ export { default as Header } from './Header'; export { default as Row } from './Row'; export { default as Tab } from './Tab'; export { default as Tabs } from './Tabs'; +export { default as DynamicComponent } from './DynamicComponent'; export const componentLookup = { [CHART_TYPE]: ChartHolder, @@ -54,4 +57,5 @@ export const componentLookup = { [ROW_TYPE]: Row, [TAB_TYPE]: Tab, [TABS_TYPE]: TabsConnected, + [DYNAMIC_TYPE]: DynamicComponent, }; diff --git a/superset-frontend/src/dashboard/components/gridComponents/new/DraggableNewComponent.jsx b/superset-frontend/src/dashboard/components/gridComponents/new/DraggableNewComponent.jsx index bfb799f46640..f4f33c9333df 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/new/DraggableNewComponent.jsx +++ b/superset-frontend/src/dashboard/components/gridComponents/new/DraggableNewComponent.jsx @@ -37,10 +37,10 @@ const defaultProps = { export default class DraggableNewComponent extends React.PureComponent { render() { - const { label, id, type, className } = this.props; + const { label, id, type, className, meta } = this.props; return ( = ({ + componentKey, + metadata, +}) => ( + +); + +export default DraggableNewDynamicComponent; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadeFilterControl/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadeFilterControl/index.tsx index 5b3085625de8..f19b6b01ac89 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadeFilterControl/index.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadeFilterControl/index.tsx @@ -17,11 +17,14 @@ * under the License. */ import React, { RefObject } from 'react'; -import { styled, DataMask } from '@superset-ui/core'; +import { + DataMaskStateWithId, + Filter, + styled, + DataMask, +} from '@superset-ui/core'; import FilterControl from 'src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControl'; import { CascadeFilter } from 'src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/types'; -import { Filter } from 'src/dashboard/components/nativeFilters/types'; -import { DataMaskStateWithId } from 'src/dataMask/types'; export interface CascadeFilterControlProps { dataMaskSelected?: DataMaskStateWithId; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadePopover/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadePopover/index.tsx index b164e5a7341b..0bb177b9b9c1 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadePopover/index.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadePopover/index.tsx @@ -23,15 +23,21 @@ import React, { useState, useRef, } from 'react'; -import { styled, t, DataMask, css, SupersetTheme } from '@superset-ui/core'; +import { + css, + DataMask, + DataMaskStateWithId, + Filter, + styled, + SupersetTheme, + t, +} from '@superset-ui/core'; import Popover from 'src/components/Popover'; import Icons from 'src/components/Icons'; import { Pill } from 'src/dashboard/components/FiltersBadge/Styles'; -import { DataMaskStateWithId } from 'src/dataMask/types'; import FilterControl from 'src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControl'; import CascadeFilterControl from 'src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadeFilterControl'; import { CascadeFilter } from 'src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/types'; -import { Filter } from 'src/dashboard/components/nativeFilters/types'; interface CascadePopoverProps { dataMaskSelected: DataMaskStateWithId; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/types.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/types.ts index c5a9d1388c78..6d319f6d2945 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/types.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/types.ts @@ -17,8 +17,7 @@ * under the License. */ -import { DataMask } from '@superset-ui/core'; -import { Filter } from '../../types'; +import { DataMask, Filter } from '@superset-ui/core'; export type CascadeFilter = Filter & { dataMask?: DataMask } & { cascadeChildren: CascadeFilter[]; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink/index.tsx index 106388d5e553..bb3c1517104e 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink/index.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink/index.tsx @@ -20,8 +20,7 @@ import React, { useState } from 'react'; import { useDispatch } from 'react-redux'; import { setFilterConfiguration } from 'src/dashboard/actions/nativeFilters'; import Button from 'src/components/Button'; -import { styled } from '@superset-ui/core'; -import { FilterConfiguration } from 'src/dashboard/components/nativeFilters/types'; +import { FilterConfiguration, styled } from '@superset-ui/core'; import { FiltersConfigModal } from 'src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal'; import { getFilterBarTestId } from '..'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx index f0c0a564a08e..fb83fc96ea3d 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx @@ -18,22 +18,24 @@ */ import React, { FC, useCallback, useMemo, useState } from 'react'; import { css } from '@emotion/react'; -import { DataMask, styled, t } from '@superset-ui/core'; +import { + DataMask, + DataMaskStateWithId, + Filter, + NativeFilterType, + styled, + t, +} from '@superset-ui/core'; import { createHtmlPortalNode, InPortal, OutPortal, } from 'react-reverse-portal'; import { Collapse } from 'src/common/components'; -import { DataMaskStateWithId } from 'src/dataMask/types'; import { useDashboardHasTabs, useSelectFiltersInScope, } from 'src/dashboard/components/nativeFilters/state'; -import { - Filter, - NativeFilterType, -} from 'src/dashboard/components/nativeFilters/types'; import CascadePopover from '../CascadeFilters/CascadePopover'; import { useFilters } from '../state'; import { buildCascadeFiltersTree } from './utils'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/state.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/state.ts index 810ef5d8b488..80ce41b5aef4 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/state.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/state.ts @@ -18,9 +18,11 @@ */ import { useMemo } from 'react'; import { useSelector } from 'react-redux'; -import { NativeFiltersState } from 'src/dashboard/reducers/types'; -import { DataMaskStateWithId } from 'src/dataMask/types'; -import { ExtraFormData } from '@superset-ui/core'; +import { + DataMaskStateWithId, + ExtraFormData, + NativeFiltersState, +} from '@superset-ui/core'; import { mergeExtraFormData } from '../../utils'; // eslint-disable-next-line import/prefer-default-export diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/types.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/types.ts index 52550c542f1d..60a7b2d526f2 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/types.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/types.ts @@ -17,9 +17,7 @@ * under the License. */ import React, { RefObject } from 'react'; -import { DataMask } from '@superset-ui/core'; -import { DataMaskStateWithId } from 'src/dataMask/types'; -import { Filter } from '../../types'; +import { DataMask, DataMaskStateWithId, Filter } from '@superset-ui/core'; export interface FilterProps { dataMaskSelected?: DataMaskStateWithId; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/utils.ts index 12ca897a3072..87f11a76f9ad 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/utils.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/utils.ts @@ -18,11 +18,11 @@ */ import { debounce } from 'lodash'; import { Dispatch } from 'react'; +import { Filter, NativeFilterType, Divider } from '@superset-ui/core'; import { setFocusedNativeFilter, unsetFocusedNativeFilter, } from 'src/dashboard/actions/nativeFilters'; -import { Filter, NativeFilterType, Divider } from '../../types'; import { CascadeFilter } from '../CascadeFilters/types'; import { mapParentFiltersToChildren } from '../utils'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/EditSection.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/EditSection.tsx index 5e78091f83c8..8658bcd783a7 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/EditSection.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/EditSection.tsx @@ -17,12 +17,11 @@ * under the License. */ import React, { FC, useMemo, useState } from 'react'; -import { HandlerFunction, styled, t } from '@superset-ui/core'; +import { DataMaskState, HandlerFunction, styled, t } from '@superset-ui/core'; import { Typography, Tooltip } from 'src/common/components'; import { useDispatch } from 'react-redux'; import Button from 'src/components/Button'; import { updateFilterSet } from 'src/dashboard/actions/nativeFilters'; -import { DataMaskState } from 'src/dataMask/types'; import { WarningOutlined } from '@ant-design/icons'; import { ActionButtons } from './Footer'; import { useNativeFiltersDataMask, useFilters, useFilterSets } from '../state'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FilterSetUnit.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FilterSetUnit.tsx index e667b27f5e75..00b3c9a9f32c 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FilterSetUnit.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FilterSetUnit.tsx @@ -18,10 +18,15 @@ */ import { Typography, Dropdown, Menu } from 'src/common/components'; import React, { FC } from 'react'; -import { FilterSet } from 'src/dashboard/reducers/types'; -import { DataMaskState } from 'src/dataMask/types'; +import { + DataMaskState, + FilterSet, + HandlerFunction, + styled, + supersetTheme, + t, +} from '@superset-ui/core'; import { CheckOutlined, EllipsisOutlined } from '@ant-design/icons'; -import { HandlerFunction, styled, supersetTheme, t } from '@superset-ui/core'; import Button from 'src/components/Button'; import { Tooltip } from 'src/components/Tooltip'; import FiltersHeader from './FiltersHeader'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FiltersHeader.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FiltersHeader.tsx index c263da6a69f0..8f5f4a1a93c2 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FiltersHeader.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FiltersHeader.tsx @@ -17,16 +17,20 @@ * under the License. */ import React, { FC } from 'react'; -import { styled, t, useTheme } from '@superset-ui/core'; +import { + DataMaskState, + FilterSet, + NativeFilterType, + styled, + t, + useTheme, +} from '@superset-ui/core'; import { Collapse, Typography, Tooltip } from 'src/common/components'; -import { DataMaskState } from 'src/dataMask/types'; import Icons from 'src/components/Icons'; import { areObjectsEqual } from 'src/reduxUtils'; -import { FilterSet } from 'src/dashboard/reducers/types'; import { getFilterValueForDisplay } from './utils'; import { useFilters } from '../state'; import { getFilterBarTestId } from '../index'; -import { NativeFilterType } from '../../types'; const FilterHeader = styled.div` display: flex; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/index.tsx index 09a6304225f2..18f5a5688be3 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/index.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/index.tsx @@ -18,18 +18,25 @@ */ import React, { useEffect, useState } from 'react'; -import { DataMask, HandlerFunction, styled, t } from '@superset-ui/core'; +import { + DataMask, + DataMaskState, + DataMaskWithId, + Filter, + Filters, + FilterSet, + HandlerFunction, + styled, + t, +} from '@superset-ui/core'; import { useDispatch } from 'react-redux'; -import { DataMaskState, DataMaskWithId } from 'src/dataMask/types'; import { createFilterSet, deleteFilterSet, updateFilterSet, } from 'src/dashboard/actions/nativeFilters'; -import { Filters, FilterSet } from 'src/dashboard/reducers/types'; import { areObjectsEqual } from 'src/reduxUtils'; import { findExistingFilterSet } from './utils'; -import { Filter } from '../../types'; import { useFilters, useNativeFiltersDataMask, useFilterSets } from '../state'; import Footer from './Footer'; import FilterSetUnit from './FilterSetUnit'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/findExistingFilterSet.test.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/findExistingFilterSet.test.ts index 4c17ac86ad4a..06821ff6b70b 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/findExistingFilterSet.test.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/findExistingFilterSet.test.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { FilterSet } from 'src/dashboard/reducers/types'; +import { FilterSet } from '@superset-ui/core'; import { findExistingFilterSet } from '.'; const createDataMaskSelected = () => ({ diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/index.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/index.ts index 368fbbbb2bdf..187739ff9979 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/index.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/index.ts @@ -18,10 +18,8 @@ */ import shortid from 'shortid'; -import { t } from '@superset-ui/core'; +import { DataMaskState, FilterSet, t } from '@superset-ui/core'; import { areObjectsEqual } from 'src/reduxUtils'; -import { DataMaskState } from 'src/dataMask/types'; -import { FilterSet } from 'src/dashboard/reducers/types'; export const generateFiltersSetId = () => `FILTERS_SET-${shortid.generate()}`; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Header/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Header/index.tsx index 9b35b18078f5..2aac16e5e86b 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Header/index.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Header/index.tsx @@ -17,15 +17,20 @@ * under the License. */ /* eslint-disable no-param-reassign */ -import { styled, t, useTheme } from '@superset-ui/core'; +import { + DataMaskState, + DataMaskStateWithId, + Filter, + styled, + t, + useTheme, +} from '@superset-ui/core'; import React, { FC } from 'react'; import Icons from 'src/components/Icons'; import Button from 'src/components/Button'; import { useSelector } from 'react-redux'; -import { DataMaskState, DataMaskStateWithId } from 'src/dataMask/types'; import FilterConfigurationLink from 'src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink'; import { useFilters } from 'src/dashboard/components/nativeFilters/FilterBar/state'; -import { Filter } from 'src/dashboard/components/nativeFilters/types'; import { getFilterBarTestId } from '..'; import { RootState } from '../../../../types'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx index 02156b22bc62..6b07c2c7234a 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx @@ -18,7 +18,16 @@ */ /* eslint-disable no-param-reassign */ -import { DataMask, HandlerFunction, styled, t } from '@superset-ui/core'; +import { + DataMaskStateWithId, + DataMaskWithId, + Filter, + NativeFilterType, + DataMask, + HandlerFunction, + styled, + t, +} from '@superset-ui/core'; import React, { useEffect, useState, useCallback, useMemo } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import cx from 'classnames'; @@ -28,14 +37,9 @@ import { useHistory } from 'react-router-dom'; import { usePrevious } from 'src/hooks/usePrevious'; import { FeatureFlag, isFeatureEnabled } from 'src/featureFlags'; import { updateDataMask, clearDataMask } from 'src/dataMask/actions'; -import { DataMaskStateWithId, DataMaskWithId } from 'src/dataMask/types'; import { useImmer } from 'use-immer'; import { isEmpty, isEqual } from 'lodash'; import { testWithId } from 'src/utils/testUtils'; -import { - Filter, - NativeFilterType, -} from 'src/dashboard/components/nativeFilters/types'; import Loading from 'src/components/Loading'; import { getInitialDataMask } from 'src/dataMask/reducer'; import { URL_PARAMS } from 'src/constants'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/state.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/state.ts index 8e7022f070b0..054f440a74f4 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/state.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/state.ts @@ -19,20 +19,18 @@ /* eslint-disable no-param-reassign */ import { useSelector } from 'react-redux'; import { filter, keyBy } from 'lodash'; -import { - Filters, - FilterSets as FilterSetsType, -} from 'src/dashboard/reducers/types'; import { DataMaskState, DataMaskStateWithId, DataMaskWithId, -} from 'src/dataMask/types'; + Filter, + Filters, + FilterSets as FilterSetsType, +} from '@superset-ui/core'; import { useContext, useEffect, useMemo, useState } from 'react'; import { ChartsState, RootState } from 'src/dashboard/types'; import { MigrationContext } from 'src/dashboard/containers/DashboardPage'; import { FILTER_BOX_MIGRATION_STATES } from 'src/explore/constants'; -import { Filter } from 'src/dashboard/components/nativeFilters/types'; import { NATIVE_FILTER_PREFIX } from '../FiltersConfigModal/utils'; export const useFilterSets = () => diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/utils.ts index a2bc7caa0479..926abbf06956 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/utils.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/utils.ts @@ -17,10 +17,13 @@ * under the License. */ -import { DataMaskStateWithId } from 'src/dataMask/types'; import { areObjectsEqual } from 'src/reduxUtils'; -import { FilterState } from '@superset-ui/core'; -import { Filter, Divider } from '../types'; +import { + DataMaskStateWithId, + Filter, + FilterState, + Divider, +} from '@superset-ui/core'; export enum TabIds { AllFilters = 'allFilters', diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/DividerConfigForm.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/DividerConfigForm.tsx index 7ab2b100206f..afef49684fdf 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/DividerConfigForm.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/DividerConfigForm.tsx @@ -19,8 +19,7 @@ import React from 'react'; import { FormItem } from 'src/components/Form'; import { Input, TextArea } from 'src/common/components'; -import { styled, t } from '@superset-ui/core'; -import { NativeFilterType } from '../types'; +import { NativeFilterType, styled, t } from '@superset-ui/core'; interface Props { componentId: string; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterConfigurePane.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterConfigurePane.tsx index e77a29bad46b..744bcf8fe4a8 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterConfigurePane.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterConfigurePane.tsx @@ -16,9 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -import { styled } from '@superset-ui/core'; +import { NativeFilterType, styled } from '@superset-ui/core'; import React from 'react'; -import { NativeFilterType } from '../types'; import FilterTitlePane from './FilterTitlePane'; import { FilterRemoval } from './types'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTitlePane.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTitlePane.tsx index 1a1f4cd121bb..756a3e0e9a8a 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTitlePane.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTitlePane.tsx @@ -16,10 +16,9 @@ * specific language governing permissions and limitations * under the License. */ -import { styled, t, useTheme } from '@superset-ui/core'; +import { NativeFilterType, styled, t, useTheme } from '@superset-ui/core'; import React from 'react'; import { Dropdown, MainNav as Menu } from 'src/common/components'; -import { NativeFilterType } from '../types'; import FilterTitleContainer from './FilterTitleContainer'; import { FilterRemoval } from './types'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.tsx index 65ee3f01548c..877e43fdf750 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.tsx @@ -18,11 +18,10 @@ */ import React, { FC, useCallback, useState } from 'react'; -import { t, styled } from '@superset-ui/core'; +import { NativeFilterScope, styled, t } from '@superset-ui/core'; import { Radio } from 'src/components/Radio'; import { Form, Typography } from 'src/common/components'; import { useComponentDidUpdate } from 'src/hooks/useComponentDidUpdate/useComponentDidUpdate'; -import { Scope } from '../../../types'; import { ScopingType } from './types'; import ScopingTree from './ScopingTree'; import { getDefaultScopeValue, isScopingAll } from './utils'; @@ -30,9 +29,9 @@ import { getDefaultScopeValue, isScopingAll } from './utils'; type FilterScopeProps = { pathToFormValue?: string[]; updateFormValues: (values: any) => void; - formFilterScope?: Scope; + formFilterScope?: NativeFilterScope; forceUpdate: Function; - filterScope?: Scope; + filterScope?: NativeFilterScope; formScopingType?: ScopingType; chartId?: number; initiallyExcludedCharts?: number[]; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/ScopingTree.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/ScopingTree.tsx index af140f862c86..713eb95e7a79 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/ScopingTree.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/ScopingTree.tsx @@ -18,19 +18,19 @@ */ import React, { FC, useMemo, useState } from 'react'; +import { NativeFilterScope } from '@superset-ui/core'; import { Tree } from 'src/common/components'; import { DASHBOARD_ROOT_ID } from 'src/dashboard/util/constants'; import { Tooltip } from 'src/components/Tooltip'; import Icons from 'src/components/Icons'; import { useFilterScopeTree } from './state'; import { findFilterScope, getTreeCheckedItems } from './utils'; -import { Scope } from '../../../types'; type ScopingTreeProps = { forceUpdate: Function; updateFormValues: (values: any) => void; - formScope?: Scope; - initialScope: Scope; + formScope?: NativeFilterScope; + initialScope: NativeFilterScope; chartId?: number; initiallyExcludedCharts?: number[]; }; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils.ts index 555b87ff7779..4bf04c7e957b 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils.ts @@ -23,9 +23,8 @@ import { TAB_TYPE, } from 'src/dashboard/util/componentTypes'; import { DASHBOARD_ROOT_ID } from 'src/dashboard/util/constants'; -import { t } from '@superset-ui/core'; +import { NativeFilterScope, t } from '@superset-ui/core'; import { BuildTreeLeafTitle, TreeItem } from './types'; -import { Scope } from '../../../types'; export const isShowTypeInTree = ({ type, meta }: LayoutItem, charts?: Charts) => (type === TAB_TYPE || type === CHART_TYPE || type === DASHBOARD_ROOT_TYPE) && @@ -114,7 +113,10 @@ const checkTreeItem = ( }); }; -export const getTreeCheckedItems = (scope: Scope, layout: Layout) => { +export const getTreeCheckedItems = ( + scope: NativeFilterScope, + layout: Layout, +) => { const checkedItems: string[] = []; checkTreeItem(checkedItems, layout, [...scope.rootPath], [...scope.excluded]); return [...new Set(checkedItems)]; @@ -124,7 +126,7 @@ export const getTreeCheckedItems = (scope: Scope, layout: Layout) => { export const findFilterScope = ( checkedKeys: string[], layout: Layout, -): Scope => { +): NativeFilterScope => { if (!checkedKeys.length) { return { rootPath: [], @@ -170,14 +172,14 @@ export const findFilterScope = ( export const getDefaultScopeValue = ( chartId?: number, initiallyExcludedCharts: number[] = [], -): Scope => ({ +): NativeFilterScope => ({ rootPath: [DASHBOARD_ROOT_ID], excluded: chartId ? [chartId, ...initiallyExcludedCharts] : initiallyExcludedCharts, }); -export const isScopingAll = (scope: Scope, chartId?: number) => +export const isScopingAll = (scope: NativeFilterScope, chartId?: number) => !scope || (scope.rootPath[0] === DASHBOARD_ROOT_ID && !scope.excluded.filter(item => item !== chartId).length); diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx index 387c18e5f145..97e1d6853e1b 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx @@ -27,9 +27,11 @@ import { Behavior, ChartDataResponseResult, Column, + Filter, GenericDataType, getChartMetadataRegistry, JsonResponse, + NativeFilterType, styled, SupersetApiError, SupersetClient, @@ -71,10 +73,6 @@ import { FeatureFlag, isFeatureEnabled } from 'src/featureFlags'; import { waitForAsyncData } from 'src/middleware/asyncEvent'; import { cacheWrapper } from 'src/utils/cacheWrapper'; import { ClientErrorObject } from 'src/utils/getClientErrorObject'; -import { - Filter, - NativeFilterType, -} from 'src/dashboard/components/nativeFilters/types'; import { SingleValueType } from 'src/filters/components/Range/SingleValueType'; import { getFormData } from 'src/dashboard/components/nativeFilters/utils'; import { diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/getControlItemsMap.test.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/getControlItemsMap.test.tsx index 25ed9ea3b793..87cf5366e5cd 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/getControlItemsMap.test.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/getControlItemsMap.test.tsx @@ -18,12 +18,9 @@ */ import userEvent from '@testing-library/user-event'; import React from 'react'; +import { Filter, NativeFilterType } from '@superset-ui/core'; import { render, screen } from 'spec/helpers/testing-library'; import { FormInstance } from 'src/common/components'; -import { - Filter, - NativeFilterType, -} from 'src/dashboard/components/nativeFilters/types'; import getControlItemsMap, { ControlItemsProps } from './getControlItemsMap'; import { getControlItems, setNativeFilterFieldValues } from './utils'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/getControlItemsMap.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/getControlItemsMap.tsx index d202552f3903..3fcf9f23e2e3 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/getControlItemsMap.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/getControlItemsMap.tsx @@ -23,7 +23,12 @@ import { import React from 'react'; import { Checkbox } from 'src/common/components'; import { FormInstance } from 'antd/lib/form'; -import { getChartControlPanelRegistry, styled, t } from '@superset-ui/core'; +import { + Filter, + getChartControlPanelRegistry, + styled, + t, +} from '@superset-ui/core'; import { Tooltip } from 'src/components/Tooltip'; import { FormItem } from 'src/components/Form'; import { @@ -37,7 +42,6 @@ import { StyledLabel, StyledRowFormItem, } from './FiltersConfigForm'; -import { Filter } from '../../types'; import { ColumnSelect } from './ColumnSelect'; export interface ControlItemsProps { diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/state.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/state.ts index 0fa8c778b9de..0b707d82d566 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/state.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/state.ts @@ -18,10 +18,9 @@ */ import { useEffect, useState } from 'react'; import { FormInstance } from 'antd/lib/form'; -import { t } from '@superset-ui/core'; +import { Filter, t } from '@superset-ui/core'; import { NativeFiltersForm, NativeFiltersFormItem } from '../types'; import { setNativeFilterFieldValues, useForceUpdate } from './utils'; -import { Filter } from '../../types'; // When some fields in form changed we need re-fetch data for Filter defaultValue // eslint-disable-next-line import/prefer-default-export diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.tsx index e3fcfcf8383b..d288bba05e0a 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.tsx @@ -24,18 +24,20 @@ import React, { useRef, } from 'react'; import { uniq, isEqual, sortBy, debounce } from 'lodash'; -import { t, styled, SLOW_DEBOUNCE } from '@superset-ui/core'; -import { Form } from 'src/common/components'; -import ErrorBoundary from 'src/components/ErrorBoundary'; -import { StyledModal } from 'src/components/Modal'; -import { testWithId } from 'src/utils/testUtils'; -import { useFilterConfigMap, useFilterConfiguration } from '../state'; import { Filter, FilterConfiguration, NativeFilterType, Divider, -} from '../types'; + styled, + SLOW_DEBOUNCE, + t, +} from '@superset-ui/core'; +import { Form } from 'src/common/components'; +import ErrorBoundary from 'src/components/ErrorBoundary'; +import { StyledModal } from 'src/components/Modal'; +import { testWithId } from 'src/utils/testUtils'; +import { useFilterConfigMap, useFilterConfiguration } from '../state'; import FiltureConfigurePane from './FilterConfigurePane'; import FiltersConfigForm, { FilterPanels, diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/state.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/state.ts index 2ab54d980605..285c30e5c03b 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/state.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/state.ts @@ -1,7 +1,7 @@ import { useEffect } from 'react'; import { usePrevious } from 'src/hooks/usePrevious'; +import { NativeFilterType } from '@superset-ui/core'; import { FilterRemoval } from './types'; -import { NativeFilterType } from '../types'; /** * Licensed to the Apache Software Foundation (ASF) under one diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/types.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/types.ts index c5165fc0f3e2..42daba882214 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/types.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/types.ts @@ -16,11 +16,15 @@ * specific language governing permissions and limitations * under the License. */ -import { AdhocFilter, DataMask } from '@superset-ui/core'; -import { NativeFilterType, Scope } from '../types'; +import { + AdhocFilter, + DataMask, + NativeFilterType, + NativeFilterScope, +} from '@superset-ui/core'; export interface NativeFiltersFormItem { - scope: Scope; + scope: NativeFilterScope; name: string; filterType: string; dataset: { diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts index 539a882e074c..b6edd9fd024a 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts @@ -20,7 +20,14 @@ import { FormInstance } from 'antd/lib/form'; import shortid from 'shortid'; import { getInitialDataMask } from 'src/dataMask/reducer'; -import { t } from '@superset-ui/core'; +import { + Filter, + FilterConfiguration, + NativeFilterType, + Divider, + t, + NativeFilterTarget, +} from '@superset-ui/core'; import { DASHBOARD_ROOT_ID } from 'src/dashboard/util/constants'; import { FilterRemoval, @@ -28,13 +35,6 @@ import { FilterHierarchy, FilterHierarchyNode, } from './types'; -import { - Filter, - FilterConfiguration, - NativeFilterType, - Divider, - Target, -} from '../types'; export const REMOVAL_DELAY_SECS = 5; @@ -156,7 +156,7 @@ export const createHandleSave = description: formInputs.description, }; } - const target: Partial = {}; + const target: Partial = {}; if (formInputs.dataset) { target.datasetId = formInputs.dataset.value; } diff --git a/superset-frontend/src/dashboard/components/nativeFilters/state.ts b/superset-frontend/src/dashboard/components/nativeFilters/state.ts index da295a17849c..be2089c6be08 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/state.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/state.ts @@ -23,7 +23,7 @@ import { FilterConfiguration, NativeFilterType, Divider, -} from './types'; +} from '@superset-ui/core'; import { ActiveTabs, DashboardLayout, RootState } from '../../types'; import { TAB_TYPE } from '../../util/componentTypes'; import { CascadeFilter } from './FilterBar/CascadeFilters/types'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/utils.ts index 60925c79bac8..1ebba4619e35 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/utils.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/utils.ts @@ -17,21 +17,21 @@ * under the License. */ import { - ExtraFormData, - QueryFormData, - getChartMetadataRegistry, + AdhocFilter, Behavior, + DataMaskStateWithId, EXTRA_FORM_DATA_APPEND_KEYS, EXTRA_FORM_DATA_OVERRIDE_KEYS, - AdhocFilter, + ExtraFormData, FeatureFlag, + Filter, + getChartMetadataRegistry, + QueryFormData, } from '@superset-ui/core'; import { Charts, DashboardLayout } from 'src/dashboard/types'; import { RefObject } from 'react'; -import { DataMaskStateWithId } from 'src/dataMask/types'; import extractUrlParams from 'src/dashboard/util/extractUrlParams'; import { isFeatureEnabled } from 'src/featureFlags'; -import { Filter } from './types'; import { CHART_TYPE, TAB_TYPE } from '../../util/componentTypes'; import { DASHBOARD_GRID_ID, DASHBOARD_ROOT_ID } from '../../util/constants'; diff --git a/superset-frontend/src/dashboard/fixtures/mockNativeFilters.ts b/superset-frontend/src/dashboard/fixtures/mockNativeFilters.ts index f6766cfb70ba..9ace211b9b3e 100644 --- a/superset-frontend/src/dashboard/fixtures/mockNativeFilters.ts +++ b/superset-frontend/src/dashboard/fixtures/mockNativeFilters.ts @@ -16,9 +16,11 @@ * specific language governing permissions and limitations * under the License. */ -import { NativeFilterType } from 'src/dashboard/components/nativeFilters/types'; -import { NativeFiltersState } from 'src/dashboard/reducers/types'; -import { DataMaskStateWithId } from 'src/dataMask/types'; +import { + DataMaskStateWithId, + NativeFiltersState, + NativeFilterType, +} from '@superset-ui/core'; export const mockDataMaskInfo: DataMaskStateWithId = { DefaultsID: { diff --git a/superset-frontend/src/dashboard/reducers/nativeFilters.ts b/superset-frontend/src/dashboard/reducers/nativeFilters.ts index 1521ec10c512..b3900af31cf5 100644 --- a/superset-frontend/src/dashboard/reducers/nativeFilters.ts +++ b/superset-frontend/src/dashboard/reducers/nativeFilters.ts @@ -24,8 +24,11 @@ import { SET_FOCUSED_NATIVE_FILTER, UNSET_FOCUSED_NATIVE_FILTER, } from 'src/dashboard/actions/nativeFilters'; -import { FilterSet, NativeFiltersState } from './types'; -import { FilterConfiguration } from '../components/nativeFilters/types'; +import { + FilterSet, + FilterConfiguration, + NativeFiltersState, +} from '@superset-ui/core'; import { HYDRATE_DASHBOARD } from '../actions/hydrate'; export function getInitialState({ diff --git a/superset-frontend/src/dashboard/reducers/types.ts b/superset-frontend/src/dashboard/reducers/types.ts index 5cef1a1fa742..c1c723cf0179 100644 --- a/superset-frontend/src/dashboard/reducers/types.ts +++ b/superset-frontend/src/dashboard/reducers/types.ts @@ -18,9 +18,7 @@ */ import componentTypes from 'src/dashboard/util/componentTypes'; -import { DataMaskStateWithId } from 'src/dataMask/types'; -import { JsonObject } from '@superset-ui/core'; -import { Filter, Scope } from '../components/nativeFilters/types'; +import { NativeFilterScope, JsonObject } from '@superset-ui/core'; export enum Scoping { All = 'All', @@ -31,7 +29,7 @@ export type ChartConfiguration = { [chartId: number]: { id: number; crossFilters: { - scope: Scope; + scope: NativeFilterScope; }; }; }; @@ -82,13 +80,6 @@ export type LayoutItem = { }; }; -export type FilterSet = { - id: number; - name: string; - nativeFilters: Filters; - dataMask: DataMaskStateWithId; -}; - export type FilterSetFullData = { changed_by_fk: string | null; changed_on: string | null; @@ -101,17 +92,3 @@ export type FilterSetFullData = { owner_type: string; params: JsonObject; }; - -export type FilterSets = { - [filtersSetId: string]: FilterSet; -}; - -export type Filters = { - [filterId: string]: Filter; -}; - -export type NativeFiltersState = { - filters: Filters; - filterSets: FilterSets; - focusedFilterId?: string; -}; diff --git a/superset-frontend/src/dashboard/types.ts b/superset-frontend/src/dashboard/types.ts index 1496b988943f..24b7a5b0bd8e 100644 --- a/superset-frontend/src/dashboard/types.ts +++ b/superset-frontend/src/dashboard/types.ts @@ -18,17 +18,17 @@ */ import { ChartProps, + DataMaskStateWithId, ExtraFormData, GenericDataType, JsonObject, + NativeFiltersState, } from '@superset-ui/core'; import { DatasourceMeta } from '@superset-ui/chart-controls'; import { chart } from 'src/chart/chartReducer'; import componentTypes from 'src/dashboard/util/componentTypes'; import { User } from 'src/types/bootstrapTypes'; -import { DataMaskStateWithId } from '../dataMask/types'; -import { NativeFiltersState } from './reducers/types'; import { ChartState } from '../explore/types'; export { Dashboard } from 'src/types/Dashboard'; diff --git a/superset-frontend/src/dashboard/util/activeAllDashboardFilters.ts b/superset-frontend/src/dashboard/util/activeAllDashboardFilters.ts index 7b9dc10a4a0e..f0a9b709ee5d 100644 --- a/superset-frontend/src/dashboard/util/activeAllDashboardFilters.ts +++ b/superset-frontend/src/dashboard/util/activeAllDashboardFilters.ts @@ -16,12 +16,15 @@ * specific language governing permissions and limitations * under the License. */ -import { DataMaskStateWithId } from 'src/dataMask/types'; -import { JsonObject } from '@superset-ui/core'; +import { + DataMaskStateWithId, + Filters, + JsonObject, + NativeFilterScope, +} from '@superset-ui/core'; import { CHART_TYPE } from './componentTypes'; -import { Scope } from '../components/nativeFilters/types'; import { ActiveFilters, Layout, LayoutItem } from '../types'; -import { ChartConfiguration, Filters } from '../reducers/types'; +import { ChartConfiguration } from '../reducers/types'; import { DASHBOARD_ROOT_ID } from './constants'; // Looking for affected chart scopes and values @@ -35,7 +38,7 @@ export const findAffectedCharts = ({ }: { child: string; layout: { [key: string]: LayoutItem }; - scope: Scope; + scope: NativeFilterScope; activeFilters: ActiveFilters; filterId: string; extraFormData: any; diff --git a/superset-frontend/src/dashboard/util/charts/getFormDataWithExtraFilters.ts b/superset-frontend/src/dashboard/util/charts/getFormDataWithExtraFilters.ts index 24aa2e821a29..90022a9dce39 100644 --- a/superset-frontend/src/dashboard/util/charts/getFormDataWithExtraFilters.ts +++ b/superset-frontend/src/dashboard/util/charts/getFormDataWithExtraFilters.ts @@ -16,13 +16,17 @@ * specific language governing permissions and limitations * under the License. */ -import { DataRecordFilters, JsonObject } from '@superset-ui/core'; +import { + DataMaskStateWithId, + DataRecordFilters, + JsonObject, + NativeFiltersState, +} from '@superset-ui/core'; import { ChartQueryPayload, Charts, LayoutItem } from 'src/dashboard/types'; import { getExtraFormData } from 'src/dashboard/components/nativeFilters/utils'; -import { DataMaskStateWithId } from 'src/dataMask/types'; import { areObjectsEqual } from 'src/reduxUtils'; import getEffectiveExtraFilters from './getEffectiveExtraFilters'; -import { ChartConfiguration, NativeFiltersState } from '../../reducers/types'; +import { ChartConfiguration } from '../../reducers/types'; import { getAllActiveFilters } from '../activeAllDashboardFilters'; // We cache formData objects so that our connected container components don't always trigger diff --git a/superset-frontend/src/dashboard/util/componentIsResizable.ts b/superset-frontend/src/dashboard/util/componentIsResizable.ts index 21d0ef17b799..fd1d9d19aa62 100644 --- a/superset-frontend/src/dashboard/util/componentIsResizable.ts +++ b/superset-frontend/src/dashboard/util/componentIsResizable.ts @@ -16,8 +16,17 @@ * specific language governing permissions and limitations * under the License. */ -import { COLUMN_TYPE, CHART_TYPE, MARKDOWN_TYPE } from './componentTypes'; +import { + COLUMN_TYPE, + CHART_TYPE, + MARKDOWN_TYPE, + DYNAMIC_TYPE, +} from './componentTypes'; export default function componentIsResizable(entity: { type: string }) { - return [COLUMN_TYPE, CHART_TYPE, MARKDOWN_TYPE].indexOf(entity.type) > -1; + return ( + [COLUMN_TYPE, CHART_TYPE, MARKDOWN_TYPE, DYNAMIC_TYPE].indexOf( + entity.type, + ) > -1 + ); } diff --git a/superset-frontend/src/dashboard/util/componentTypes.ts b/superset-frontend/src/dashboard/util/componentTypes.ts index 177aad05d61f..0630d4411aab 100644 --- a/superset-frontend/src/dashboard/util/componentTypes.ts +++ b/superset-frontend/src/dashboard/util/componentTypes.ts @@ -28,6 +28,8 @@ export const NEW_COMPONENT_SOURCE_TYPE = 'NEW_COMPONENT_SOURCE'; export const ROW_TYPE = 'ROW'; export const TABS_TYPE = 'TABS'; export const TAB_TYPE = 'TAB'; +// Dynamic type proposes lazy loading of custom dashboard components that can be added in separate repository +export const DYNAMIC_TYPE = 'DYNAMIC'; export default { CHART_TYPE, @@ -42,4 +44,5 @@ export default { ROW_TYPE, TABS_TYPE, TAB_TYPE, + DYNAMIC_TYPE, }; diff --git a/superset-frontend/src/dashboard/util/constants.ts b/superset-frontend/src/dashboard/util/constants.ts index 9434a5a898f1..640028eb4e94 100644 --- a/superset-frontend/src/dashboard/util/constants.ts +++ b/superset-frontend/src/dashboard/util/constants.ts @@ -31,6 +31,7 @@ export const NEW_MARKDOWN_ID = 'NEW_MARKDOWN_ID'; export const NEW_ROW_ID = 'NEW_ROW_ID'; export const NEW_TAB_ID = 'NEW_TAB_ID'; export const NEW_TABS_ID = 'NEW_TABS_ID'; +export const NEW_DYNAMIC_COMPONENT = 'NEW_DYNAMIC_COMPONENT'; // grid constants export const DASHBOARD_ROOT_DEPTH = 0; diff --git a/superset-frontend/src/dashboard/util/filterboxMigrationHelper.ts b/superset-frontend/src/dashboard/util/filterboxMigrationHelper.ts index 87b3ab5e52b6..523577520ee7 100644 --- a/superset-frontend/src/dashboard/util/filterboxMigrationHelper.ts +++ b/superset-frontend/src/dashboard/util/filterboxMigrationHelper.ts @@ -19,17 +19,13 @@ import shortid from 'shortid'; import { find, isEmpty } from 'lodash'; -import { - Filter, - NativeFilterType, -} from 'src/dashboard/components/nativeFilters/types'; import { FILTER_CONFIG_ATTRIBUTES, TIME_FILTER_LABELS, TIME_FILTER_MAP, } from 'src/explore/constants'; import { DASHBOARD_FILTER_SCOPE_GLOBAL } from 'src/dashboard/reducers/dashboardFilters'; -import { TimeGranularity } from '@superset-ui/core'; +import { Filter, NativeFilterType, TimeGranularity } from '@superset-ui/core'; import { getChartIdsInFilterScope } from './activeDashboardFilters'; import getFilterConfigsFromFormdata from './getFilterConfigsFromFormdata'; diff --git a/superset-frontend/src/dashboard/util/getDetailedComponentWidth.js b/superset-frontend/src/dashboard/util/getDetailedComponentWidth.js index efad55f63cbb..66a2dc5cdfdc 100644 --- a/superset-frontend/src/dashboard/util/getDetailedComponentWidth.js +++ b/superset-frontend/src/dashboard/util/getDetailedComponentWidth.js @@ -23,6 +23,7 @@ import { COLUMN_TYPE, MARKDOWN_TYPE, CHART_TYPE, + DYNAMIC_TYPE, } from './componentTypes'; function getTotalChildWidth({ id, components }) { @@ -84,6 +85,7 @@ export default function getDetailedComponentWidth({ } }); } else if ( + component.type === DYNAMIC_TYPE || component.type === MARKDOWN_TYPE || component.type === CHART_TYPE ) { diff --git a/superset-frontend/src/dashboard/util/getFormDataWithExtraFilters.test.ts b/superset-frontend/src/dashboard/util/getFormDataWithExtraFilters.test.ts index d60efaa185b4..0756ef03b3fc 100644 --- a/superset-frontend/src/dashboard/util/getFormDataWithExtraFilters.test.ts +++ b/superset-frontend/src/dashboard/util/getFormDataWithExtraFilters.test.ts @@ -16,11 +16,11 @@ * specific language governing permissions and limitations * under the License. */ +import { Filter } from '@superset-ui/core'; import getFormDataWithExtraFilters, { GetFormDataWithExtraFiltersArguments, } from 'src/dashboard/util/charts/getFormDataWithExtraFilters'; import { DASHBOARD_ROOT_ID } from 'src/dashboard/util/constants'; -import { Filter } from 'src/dashboard/components/nativeFilters/types'; import { LayoutItem } from 'src/dashboard/types'; import { dashboardLayout } from 'spec/fixtures/mockDashboardLayout'; import { sliceId as chartId } from 'spec/fixtures/mockChartQueries'; diff --git a/superset-frontend/src/dashboard/util/isDashboardEmpty.ts b/superset-frontend/src/dashboard/util/isDashboardEmpty.ts index 78481c503b92..7f3cc62bf86f 100644 --- a/superset-frontend/src/dashboard/util/isDashboardEmpty.ts +++ b/superset-frontend/src/dashboard/util/isDashboardEmpty.ts @@ -16,9 +16,13 @@ * specific language governing permissions and limitations * under the License. */ -import { CHART_TYPE, MARKDOWN_TYPE } from './componentTypes'; +import { CHART_TYPE, MARKDOWN_TYPE, DYNAMIC_TYPE } from './componentTypes'; -const USER_CONTENT_COMPONENT_TYPE: string[] = [CHART_TYPE, MARKDOWN_TYPE]; +const USER_CONTENT_COMPONENT_TYPE: string[] = [ + CHART_TYPE, + MARKDOWN_TYPE, + DYNAMIC_TYPE, +]; export default function isDashboardEmpty(layout: any): boolean { // has at least one chart or markdown component return !Object.values(layout).some( diff --git a/superset-frontend/src/dashboard/util/isValidChild.ts b/superset-frontend/src/dashboard/util/isValidChild.ts index 78d8984bc50a..6b2465eaaaeb 100644 --- a/superset-frontend/src/dashboard/util/isValidChild.ts +++ b/superset-frontend/src/dashboard/util/isValidChild.ts @@ -43,6 +43,7 @@ import { ROW_TYPE, TABS_TYPE, TAB_TYPE, + DYNAMIC_TYPE, } from './componentTypes'; import { DASHBOARD_ROOT_DEPTH as rootDepth } from './constants'; @@ -62,6 +63,7 @@ const parentMaxDepthLookup = { [DASHBOARD_GRID_TYPE]: { [CHART_TYPE]: depthOne, + [DYNAMIC_TYPE]: depthOne, [MARKDOWN_TYPE]: depthOne, [COLUMN_TYPE]: depthOne, [DIVIDER_TYPE]: depthOne, @@ -72,6 +74,7 @@ const parentMaxDepthLookup = { [ROW_TYPE]: { [CHART_TYPE]: depthFour, + [DYNAMIC_TYPE]: depthFour, [MARKDOWN_TYPE]: depthFour, [COLUMN_TYPE]: depthFour, }, @@ -82,6 +85,7 @@ const parentMaxDepthLookup = { [TAB_TYPE]: { [CHART_TYPE]: depthFive, + [DYNAMIC_TYPE]: depthFive, [MARKDOWN_TYPE]: depthFive, [COLUMN_TYPE]: depthThree, [DIVIDER_TYPE]: depthFive, @@ -101,6 +105,7 @@ const parentMaxDepthLookup = { // these have no valid children [CHART_TYPE]: {}, + [DYNAMIC_TYPE]: {}, [DIVIDER_TYPE]: {}, [HEADER_TYPE]: {}, [MARKDOWN_TYPE]: {}, diff --git a/superset-frontend/src/dashboard/util/newComponentFactory.js b/superset-frontend/src/dashboard/util/newComponentFactory.js index 04dc71c32705..8fddfda83c38 100644 --- a/superset-frontend/src/dashboard/util/newComponentFactory.js +++ b/superset-frontend/src/dashboard/util/newComponentFactory.js @@ -28,12 +28,14 @@ import { ROW_TYPE, TABS_TYPE, TAB_TYPE, + DYNAMIC_TYPE, } from './componentTypes'; import { MEDIUM_HEADER, BACKGROUND_TRANSPARENT, GRID_DEFAULT_CHART_WIDTH, + GRID_COLUMN_COUNT, } from './constants'; const typeToDefaultMetaData = { @@ -56,6 +58,10 @@ const typeToDefaultMetaData = { defaultText: t('Tab title'), placeholder: t('Tab title'), }, + [DYNAMIC_TYPE]: { + width: GRID_COLUMN_COUNT, + background: BACKGROUND_TRANSPARENT, + }, }; function uuid(type) { diff --git a/superset-frontend/src/dataMask/actions.ts b/superset-frontend/src/dataMask/actions.ts index b98f36ebd5f2..a26b49f80729 100644 --- a/superset-frontend/src/dataMask/actions.ts +++ b/superset-frontend/src/dataMask/actions.ts @@ -16,10 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -import { DataMask } from '@superset-ui/core'; -import { FilterConfiguration } from '../dashboard/components/nativeFilters/types'; +import { DataMask, FilterConfiguration, Filters } from '@superset-ui/core'; import { FeatureFlag, isFeatureEnabled } from '../featureFlags'; -import { Filters } from '../dashboard/reducers/types'; import { getInitialDataMask } from './reducer'; export const CLEAR_DATA_MASK_STATE = 'CLEAR_DATA_MASK_STATE'; diff --git a/superset-frontend/src/dataMask/reducer.ts b/superset-frontend/src/dataMask/reducer.ts index 60d09f0df347..ae30d1be7852 100644 --- a/superset-frontend/src/dataMask/reducer.ts +++ b/superset-frontend/src/dataMask/reducer.ts @@ -20,23 +20,25 @@ /* eslint-disable no-param-reassign */ // <- When we work with Immer, we need reassign, so disabling lint import produce from 'immer'; -import { DataMask, FeatureFlag } from '@superset-ui/core'; +import { + DataMask, + DataMaskStateWithId, + DataMaskWithId, + FeatureFlag, + Filter, + FilterConfiguration, + Filters, +} from '@superset-ui/core'; import { NATIVE_FILTER_PREFIX } from 'src/dashboard/components/nativeFilters/FiltersConfigModal/utils'; import { HYDRATE_DASHBOARD } from 'src/dashboard/actions/hydrate'; import { isFeatureEnabled } from 'src/featureFlags'; -import { DataMaskStateWithId, DataMaskWithId } from './types'; import { AnyDataMaskAction, CLEAR_DATA_MASK_STATE, SET_DATA_MASK_FOR_FILTER_CONFIG_COMPLETE, UPDATE_DATA_MASK, } from './actions'; -import { - Filter, - FilterConfiguration, -} from '../dashboard/components/nativeFilters/types'; import { areObjectsEqual } from '../reduxUtils'; -import { Filters } from '../dashboard/reducers/types'; export function getInitialDataMask( id?: string | number, diff --git a/superset-frontend/src/preamble.ts b/superset-frontend/src/preamble.ts index 5380fe269861..0547e8a6abcc 100644 --- a/superset-frontend/src/preamble.ts +++ b/superset-frontend/src/preamble.ts @@ -25,6 +25,7 @@ import { merge } from 'lodash'; import setupClient from './setup/setupClient'; import setupColors from './setup/setupColors'; import setupFormatters from './setup/setupFormatters'; +import setupDashboardComponents from './setup/setupDasboardComponents'; if (process.env.WEBPACK_MODE === 'development') { setHotLoaderConfig({ logLevel: 'debug', trackTailUpdates: false }); @@ -60,6 +61,8 @@ setupColors( // Setup number formatters setupFormatters(); +setupDashboardComponents(); + export const theme = merge( supersetTheme, bootstrapData?.common?.theme_overrides ?? {}, diff --git a/superset-frontend/src/setup/setupDasboardComponents.ts b/superset-frontend/src/setup/setupDasboardComponents.ts new file mode 100644 index 000000000000..f5799331adaf --- /dev/null +++ b/superset-frontend/src/setup/setupDasboardComponents.ts @@ -0,0 +1,31 @@ +/** + * 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. + */ + +/* + This file can be overridden from outside by custom config, it will add/delete new components to existing config in + superset-frontend/src/visualizations/presets/dashboardComponents.ts file + */ + +// import dashboardComponentsRegistry from '../visualizations/presets/dashboardComponents'; +// import example from '../visualizations/dashboardComponents/ExampleComponent'; + +export default function setupDashboardComponents() { + // Add custom dashboard components here. Example: + // dashboardComponentsRegistry.set('example', example); +} diff --git a/superset-frontend/src/utils/functionalRegistry.ts b/superset-frontend/src/utils/functionalRegistry.ts new file mode 100644 index 000000000000..7ae73f4e7b0c --- /dev/null +++ b/superset-frontend/src/utils/functionalRegistry.ts @@ -0,0 +1,83 @@ +/** + * 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 } from 'react'; +import { JsonObject } from '@superset-ui/core'; + +export interface RegistryMetadata { + description: string; + name: string; +} + +export interface ComponentItem { + metadata: Metadata; + loadComponent: () => Promise<{ default: ComponentType }>; +} + +export interface ComponentRegistry { + metadata: Metadata; + Component: ComponentType; +} + +export type FunctionalRegistryState = { + registry: { [key: string]: RegistryT & { key: string } }; + registryKeys: string[]; +}; + +export const registryGetAll = + ({ registryKeys, registry }: FunctionalRegistryState) => + () => + registryKeys.map(key => registry[key]); + +export const registryDelete = + ({ registryKeys, registry }: FunctionalRegistryState) => + (keyToDelete: string) => { + // eslint-disable-next-line no-param-reassign + registryKeys = registryKeys.filter(key => key !== keyToDelete); + // eslint-disable-next-line no-param-reassign + delete registry[keyToDelete]; + }; + +export const registryGet = + ({ registry }: FunctionalRegistryState) => + (key: string) => + registry[key]; + +export const registrySet = + ({ registryKeys, registry }: FunctionalRegistryState) => + (key: string, item: JsonObject) => { + registryKeys.push(key); + // eslint-disable-next-line no-param-reassign + registry[key] = { + key, + ...item, + }; + }; + +export const registrySetComponent = + ({ registryKeys, registry }: FunctionalRegistryState) => + (key: string, item: ComponentItem) => { + registryKeys.push(key); + // eslint-disable-next-line no-param-reassign + registry[key] = { + key, + metadata: item.metadata, + Component: React.lazy(item.loadComponent), + }; + }; diff --git a/superset-frontend/src/visualizations/dashboardComponents/DashboardComponentsRegistry.ts b/superset-frontend/src/visualizations/dashboardComponents/DashboardComponentsRegistry.ts new file mode 100644 index 000000000000..1b6faa654489 --- /dev/null +++ b/superset-frontend/src/visualizations/dashboardComponents/DashboardComponentsRegistry.ts @@ -0,0 +1,62 @@ +/** + * 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 { + ComponentItem, + ComponentRegistry, + FunctionalRegistryState, + registryDelete, + registryGet, + registryGetAll, + RegistryMetadata, + registrySetComponent, +} from '../../utils/functionalRegistry'; + +export interface DashboardComponentsRegistryMetadata extends RegistryMetadata { + iconName: string; +} + +/* + This is registry that contains list of dynamic dashboard components that can be added in addition to main components + */ + +const DashboardComponentsRegistry = ( + initComponents: { key: string; item: ComponentItem }[] = [], +) => { + const state: FunctionalRegistryState< + ComponentRegistry + > = { + registry: {}, + registryKeys: [], + }; + + const set = registrySetComponent(state); + + initComponents.forEach(({ key, item }) => { + set(key, item); + }); + + return { + set, + get: registryGet(state), + delete: registryDelete(state), + getAll: registryGetAll(state), + }; +}; + +export default DashboardComponentsRegistry; diff --git a/superset-frontend/src/visualizations/dashboardComponents/ExampleComponent/ExampleComponent.tsx b/superset-frontend/src/visualizations/dashboardComponents/ExampleComponent/ExampleComponent.tsx new file mode 100644 index 000000000000..22c135363d76 --- /dev/null +++ b/superset-frontend/src/visualizations/dashboardComponents/ExampleComponent/ExampleComponent.tsx @@ -0,0 +1,33 @@ +/** + * 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 { DashboardComponentMetadata, t } from '@superset-ui/core'; + +// TODO: POC only component can be removed after PR approved +const ExampleComponent = ({ + metadata, +}: { + metadata: DashboardComponentMetadata; +}) => ( +
+ {t('We have the following keys: %s', Object.keys(metadata).join(', '))} +
+); + +export default ExampleComponent; diff --git a/superset-frontend/src/visualizations/dashboardComponents/ExampleComponent/index.ts b/superset-frontend/src/visualizations/dashboardComponents/ExampleComponent/index.ts new file mode 100644 index 000000000000..8e67d420362d --- /dev/null +++ b/superset-frontend/src/visualizations/dashboardComponents/ExampleComponent/index.ts @@ -0,0 +1,28 @@ +/** + * 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. + */ + +// TODO: POC only component can be removed after PR approved +export default { + metadata: { + name: 'Example', + description: 'Example description', + iconName: 'filter', + }, + loadComponent: () => import('./ExampleComponent'), +}; diff --git a/superset-frontend/src/visualizations/presets/dashboardComponents.ts b/superset-frontend/src/visualizations/presets/dashboardComponents.ts new file mode 100644 index 000000000000..0d527f3e8c7a --- /dev/null +++ b/superset-frontend/src/visualizations/presets/dashboardComponents.ts @@ -0,0 +1,30 @@ +/** + * 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. + */ + +/* + Preset dashboard components (in addition to basic components like row, column, chart, etc...) + */ + +import DashboardComponentsRegistry from '../dashboardComponents/DashboardComponentsRegistry'; + +const dashboardComponents = DashboardComponentsRegistry([ + // Here can be added default dashboard components +]); + +export default dashboardComponents;