refactor(monorepo): stage 1 (#17427)

* skip geojson in pre-commit

update prettier

* update package.json

update package.json

u package

pkg

pkg2

* lint main repo 2

lint main repo

lint

* lintrc

lintrc 2

lintrc2

lintrc 3

lintrc

* fix import

* refresh lock file

* fix break line make @ts-ignore invalid

* update rat-excludes

rat-excludes

update rat-excludes

* update eslintrc.js

* lint lint lint
This commit is contained in:
Yongjie Zhao 2021-11-17 07:31:36 +00:00 committed by GitHub
parent 34d7f0a860
commit 9070b6b19c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
119 changed files with 2399 additions and 2222 deletions

View File

@ -33,6 +33,7 @@ repos:
hooks:
- id: check-docstring-first
- id: check-added-large-files
exclude: \.(geojson)$
- id: check-yaml
exclude: ^helm/superset/templates/
- id: debug-statements
@ -45,7 +46,7 @@ repos:
- id: black
language_version: python3
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.2.1 # Use the sha or tag you want to point at
rev: v2.4.1 # Use the sha or tag you want to point at
hooks:
- id: prettier
files: 'superset-frontend'

View File

@ -48,3 +48,16 @@ vendor/*
# github configuration
.github/*
.*mdx
# skip license check in superset-ui
tmp/*
lib/*
esm/*
tsconfig.tsbuildinfo
.*ipynb
.*yml
.*iml
.esprintrc
.prettierignore
superset-frontend/packages/generator-superset
superset-frontend/temporary_superset_ui

View File

@ -16,6 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
const packageConfig = require('./package');
const importCoreModules = [];
Object.entries(packageConfig.dependencies).forEach(([pkg]) => {
if (/@superset-ui/.test(pkg)) {
importCoreModules.push(pkg);
}
});
module.exports = {
extends: [
'airbnb',
@ -33,7 +42,15 @@ module.exports = {
browser: true,
},
settings: {
'import/resolver': 'webpack',
'import/resolver': {
webpack: {},
node: {
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
},
},
// Allow only core/src and core/test, avoid import modules from lib
'import/internal-regex': /^@superset-ui\/core\/(src|test)\/.*/,
'import/core-modules': importCoreModules,
react: {
version: 'detect',
},
@ -76,11 +93,11 @@ module.exports = {
'@typescript-eslint/no-empty-function': 0,
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/no-use-before-define': 1, // disabled temporarily
'@typescript-eslint/no-non-null-assertion': 0, // disabled temporarily
'@typescript-eslint/explicit-function-return-type': 0,
'@typescript-eslint/explicit-module-boundary-types': 0, // re-enable up for discussion
camelcase: 0,
'class-methods-use-this': 0,
curly: 1,
'func-names': 0,
'guard-for-in': 0,
'import/no-cycle': 0, // re-enable up for discussion, might require some major refactors
@ -170,11 +187,11 @@ module.exports = {
},
{
files: [
'src/**/*.test.ts',
'src/**/*.test.tsx',
'src/**/*.test.js',
'src/**/*.test.jsx',
'src/**/fixtures.*',
'*.test.ts',
'*.test.tsx',
'*.test.js',
'*.test.jsx',
'fixtures.*',
],
plugins: ['jest', 'jest-dom', 'no-only-tests', 'testing-library'],
env: {
@ -195,9 +212,28 @@ module.exports = {
'error',
{ devDependencies: true },
],
'jest/consistent-test-it': 'error',
'no-only-tests/no-only-tests': 'error',
'max-classes-per-file': 0,
'@typescript-eslint/no-non-null-assertion': 0,
// TODO: disabled temporarily, re-enable after monorepo
'jest/consistent-test-it': 'error',
'jest/expect-expect': 0,
'jest/no-test-prefixes': 0,
'jest/valid-expect-in-promise': 0,
'jest/valid-expect': 0,
'jest/valid-title': 0,
'jest-dom/prefer-to-have-attribute': 0,
'jest-dom/prefer-to-have-text-content': 0,
'jest-dom/prefer-to-have-style': 0,
},
},
{
files: './packages/generator-superset/**/*.test.*',
env: {
node: true,
},
rules: {
'jest/expect-expect': 0,
},
},
],
@ -210,7 +246,7 @@ module.exports = {
},
],
'class-methods-use-this': 0,
curly: 1,
curly: 2,
'func-names': 0,
'guard-for-in': 0,
'import/extensions': [

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
const packageConfig = require('./package.json');
const packageConfig = require('./package');
module.exports = {
sourceMaps: true,

View File

@ -22,7 +22,7 @@
export default function parsePostForm(requestBody: ArrayBuffer) {
type ParsedFields = Record<string, string[] | string>;
if (requestBody.constructor.name !== 'ArrayBuffer') {
return (requestBody as unknown) as ParsedFields;
return requestBody as unknown as ParsedFields;
}
const lines = new TextDecoder('utf-8').decode(requestBody).split('\n');
const fields: ParsedFields = {};

File diff suppressed because it is too large Load Diff

View File

@ -2,37 +2,6 @@
"name": "superset",
"version": "0.0.0dev",
"description": "Superset is a data exploration platform designed to be visual, intuitive, and interactive.",
"license": "Apache-2.0",
"directories": {
"doc": "docs",
"test": "spec"
},
"scripts": {
"tdd": "cross-env NODE_ENV=test jest --watch",
"test": "cross-env NODE_ENV=test jest",
"type": "tsc --noEmit",
"cover": "cross-env NODE_ENV=test jest --coverage",
"dev": "webpack --mode=development --color --watch",
"dev-server": "cross-env NODE_ENV=development BABEL_ENV=development node --max_old_space_size=4096 ./node_modules/webpack-dev-server/bin/webpack-dev-server.js --mode=development",
"prod": "npm run build",
"build-dev": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=development webpack --mode=development --color",
"build-instrumented": "cross-env NODE_ENV=production BABEL_ENV=instrumented webpack --mode=production --color",
"build": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=production BABEL_ENV=\"${BABEL_ENV:=production}\" webpack --mode=production --color",
"lint": "eslint --ignore-path=.eslintignore --ext .js,.jsx,.ts,.tsx . && npm run type",
"prettier-check": "prettier --check 'src/**/*.{css,less,sass,scss}'",
"lint-fix": "eslint --fix --ignore-path=.eslintignore --ext .js,.jsx,.ts,tsx . && npm run clean-css && npm run type",
"clean-css": "prettier --write 'src/**/*.{css,less,sass,scss}'",
"format": "prettier --write './{src,spec,cypress-base}/**/*{.js,.jsx,.ts,.tsx,.css,.less,.scss,.sass}'",
"prettier": "npm run format",
"check-translation": "prettier --check ../superset/translations/**/LC_MESSAGES/*.json",
"clean-translation": "prettier --write ../superset/translations/**/LC_MESSAGES/*.json",
"storybook": "cross-env NODE_ENV=development BABEL_ENV=development start-storybook -s ./src/assets/images -p 6006",
"build-storybook": "build-storybook"
},
"repository": {
"type": "git",
"url": "git+https://github.com/apache/superset.git"
},
"keywords": [
"big",
"data",
@ -45,21 +14,66 @@
"database",
"flask"
],
"author": "Apache",
"homepage": "https://superset.apache.org/",
"bugs": {
"url": "https://github.com/apache/superset/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/apache/superset.git"
},
"license": "Apache-2.0",
"author": "Apache",
"directories": {
"doc": "docs",
"test": "spec"
},
"scripts": {
"build": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=production BABEL_ENV=\"${BABEL_ENV:=production}\" webpack --mode=production --color",
"build-dev": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=development webpack --mode=development --color",
"build-instrumented": "cross-env NODE_ENV=production BABEL_ENV=instrumented webpack --mode=production --color",
"build-storybook": "build-storybook",
"check-translation": "prettier --check ../superset/translations/**/LC_MESSAGES/*.json",
"clean-css": "prettier --write 'src/**/*.{css,less,sass,scss}'",
"clean-translation": "prettier --write ../superset/translations/**/LC_MESSAGES/*.json",
"cover": "cross-env NODE_ENV=test jest --coverage",
"dev": "webpack --mode=development --color --watch",
"dev-server": "cross-env NODE_ENV=development BABEL_ENV=development node --max_old_space_size=4096 ./node_modules/webpack-dev-server/bin/webpack-dev-server.js --mode=development",
"format": "prettier --write './{src,spec,cypress-base,plugins,packages}/**/*{.js,.jsx,.ts,.tsx,.css,.less,.scss,.sass}'",
"lint": "eslint --ignore-path=.eslintignore --ext .js,.jsx,.ts,.tsx . && npm run type",
"lint-fix": "eslint --fix --ignore-path=.eslintignore --ext .js,.jsx,.ts,tsx . && npm run clean-css && npm run type",
"prettier": "npm run format",
"prettier-check": "prettier --check 'src/**/*.{css,less,sass,scss}'",
"prod": "npm run build",
"prune": "rm -rf ./{packages,plugins}/*/{lib,esm,tsconfig.tsbuildinfo,package-lock.json}",
"storybook": "cross-env NODE_ENV=development BABEL_ENV=development start-storybook -s ./src/assets/images -p 6006",
"tdd": "cross-env NODE_ENV=test jest --watch",
"test": "cross-env NODE_ENV=test jest",
"type": "tsc --noEmit"
},
"browserslist": [
"last 3 chrome versions",
"last 3 firefox versions",
"last 3 safari versions",
"last 3 edge versions"
],
"engines": {
"node": "^16.9.1",
"npm": "^7.5.4"
"stylelint": {
"rules": {
"block-opening-brace-space-before": "always",
"no-missing-end-of-source-newline": "never",
"rule-empty-line-before": [
"always",
{
"except": [
"first-nested"
],
"ignore": [
"after-comment"
]
}
]
}
},
"homepage": "https://superset.apache.org/",
"dependencies": {
"@ant-design/icons": "^4.2.2",
"@babel/runtime-corejs3": "^7.12.5",
@ -178,12 +192,15 @@
"redux-thunk": "^2.1.0",
"redux-undo": "^1.0.0-beta9-9-7",
"regenerator-runtime": "^0.13.5",
"rimraf": "^3.0.2",
"rison": "^0.1.1",
"scroll-into-view-if-needed": "^2.2.28",
"shortid": "^2.2.6",
"src": "file:./src",
"urijs": "^1.19.6",
"use-immer": "^0.6.0",
"use-query-params": "^1.1.9"
"use-query-params": "^1.1.9",
"yargs": "^15.4.1"
},
"devDependencies": {
"@babel/cli": "^7.15.7",
@ -258,7 +275,7 @@
"css-minimizer-webpack-plugin": "^3.0.2",
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0",
"eslint": "^7.17.0",
"eslint": "^7.32.0",
"eslint-config-airbnb": "^18.2.1",
"eslint-config-prettier": "^7.1.0",
"eslint-import-resolver-typescript": "^2.5.0",
@ -284,17 +301,18 @@
"jest-environment-enzyme": "^7.1.2",
"jest-enzyme": "^7.1.2",
"jest-websocket-mock": "^2.2.0",
"lerna": "^3.22.1",
"jsdom": "^16.4.0",
"lerna": "^3.22.1",
"less": "^3.12.2",
"less-loader": "^5.0.0",
"mini-css-extract-plugin": "^2.3.0",
"mock-socket": "^9.0.3",
"node-fetch": "^2.6.1",
"prettier": "^2.2.1",
"prettier": "^2.4.1",
"prettier-plugin-packagejson": "^2.2.15",
"process": "^0.11.10",
"react-test-renderer": "^16.9.0",
"react-resizable": "^3.0.4",
"react-test-renderer": "^16.9.0",
"redux-mock-store": "^1.5.4",
"sinon": "^9.0.2",
"source-map-support": "^0.5.16",
@ -312,24 +330,10 @@
"webpack-cli": "^4.8.0",
"webpack-dev-server": "^4.2.0",
"webpack-manifest-plugin": "^4.0.2",
"webpack-sources": "^3.2.0",
"yargs": "^15.4.1"
"webpack-sources": "^3.2.0"
},
"stylelint": {
"rules": {
"block-opening-brace-space-before": "always",
"no-missing-end-of-source-newline": "never",
"rule-empty-line-before": [
"always",
{
"except": [
"first-nested"
],
"ignore": [
"after-comment"
]
}
]
}
"engines": {
"node": "^16.9.1",
"npm": "^7.5.4"
}
}

View File

@ -65,7 +65,8 @@ export const getMockStoreWithChartsInTabsAndRoot = () =>
);
export const mockStoreWithTabs = getMockStoreWithTabs();
export const mockStoreWithChartsInTabsAndRoot = getMockStoreWithChartsInTabsAndRoot();
export const mockStoreWithChartsInTabsAndRoot =
getMockStoreWithChartsInTabsAndRoot();
export const sliceIdWithAppliedFilter = sliceId + 1;
export const sliceIdWithRejectedFilter = sliceId + 2;

View File

@ -93,9 +93,8 @@ describe('dashboardState actions', () => {
// mock redux work: dispatch an event, cause modify redux state
const mockParentsList = ['ROOT_ID'];
dispatch.callsFake(() => {
mockState.dashboardLayout.present[
DASHBOARD_GRID_ID
].parents = mockParentsList;
mockState.dashboardLayout.present[DASHBOARD_GRID_ID].parents =
mockParentsList;
});
// call saveDashboardRequest, it should post dashboard data with updated

View File

@ -183,7 +183,8 @@ describe('Tabs', () => {
expect(wrapper.state('tabIndex')).toBe(0);
// display child in directPathToChild list
const directPathToChild = dashboardLayoutWithTabs.present.ROW_ID2.parents.slice();
const directPathToChild =
dashboardLayoutWithTabs.present.ROW_ID2.parents.slice();
const directLinkProps = {
...props,
directPathToChild,

View File

@ -65,13 +65,13 @@ describe('getFormDataWithExtraFilters', () => {
nativeFilters: {
filterSets: {},
filters: {
[filterId]: ({
[filterId]: {
id: filterId,
scope: {
rootPath: [DASHBOARD_ROOT_ID],
excluded: [],
},
} as unknown) as Filter,
} as unknown as Filter,
},
},
dataMask: {
@ -82,7 +82,7 @@ describe('getFormDataWithExtraFilters', () => {
ownState: {},
},
},
layout: (dashboardLayout.present as unknown) as {
layout: dashboardLayout.present as unknown as {
[key: string]: LayoutItem;
},
};

View File

@ -29,9 +29,8 @@ describe('getLeafComponentIdFromPath', () => {
});
it('should not return label component', () => {
const updatedPath = dashboardFilters[filterId].directPathToFilter.concat(
'LABEL-test123',
);
const updatedPath =
dashboardFilters[filterId].directPathToFilter.concat('LABEL-test123');
expect(getLeafComponentIdFromPath(updatedPath)).toBe(leaf);
});
});

View File

@ -43,10 +43,10 @@ const getKnownControlState = (...args: Parameters<typeof getControlState>) =>
describe('controlUtils', () => {
const state: ControlPanelState = {
datasource: ({
datasource: {
columns: [{ column_name: 'a' }],
metrics: [{ metric_name: 'first' }, { metric_name: 'second' }],
} as unknown) as DatasourceMeta,
} as unknown as DatasourceMeta,
controls: {},
form_data: { datasource: '1__table', viz_type: 'table' },
};

View File

@ -68,7 +68,8 @@ export const controlPanelSectionsChartOptions: ControlPanelSectionConfig[] = [
},
];
export const controlPanelSectionsChartOptionsOnlyColorScheme: ControlPanelSectionConfig[] = [
export const controlPanelSectionsChartOptionsOnlyColorScheme: ControlPanelSectionConfig[] =
[
{
label: t('Chart Options'),
expanded: true,
@ -76,7 +77,8 @@ export const controlPanelSectionsChartOptionsOnlyColorScheme: ControlPanelSectio
},
];
export const controlPanelSectionsChartOptionsTable: ControlPanelSectionConfig[] = [
export const controlPanelSectionsChartOptionsTable: ControlPanelSectionConfig[] =
[
{
label: t('Chart Options'),
expanded: true,

View File

@ -252,9 +252,9 @@ export default class CRUDCollection extends React.PureComponent<
}
// newly ordered collection
const sorted = [
...this.state.collectionArray,
].sort((a: object, b: object) => compareSort(a[col], b[col]));
const sorted = [...this.state.collectionArray].sort(
(a: object, b: object) => compareSort(a[col], b[col]),
);
const newCollection =
sort === SortOrder.asc ? sorted : sorted.reverse();
@ -280,12 +280,8 @@ export default class CRUDCollection extends React.PureComponent<
renderHeaderRow() {
const cols = this.effectiveTableColumns();
const {
allowDeletes,
expandFieldset,
extraButtons,
sortColumns,
} = this.props;
const { allowDeletes, expandFieldset, extraButtons, sortColumns } =
this.props;
return (
<thead>
<tr>
@ -322,12 +318,8 @@ export default class CRUDCollection extends React.PureComponent<
}
renderItem(record: any) {
const {
allowAddItem,
allowDeletes,
expandFieldset,
tableColumns,
} = this.props;
const { allowAddItem, allowDeletes, expandFieldset, tableColumns } =
this.props;
/* eslint-disable no-underscore-dangle */
const isExpanded =
!!this.state.expandedColumns[record.id] || record.__expanded;

View File

@ -44,9 +44,8 @@ class ExploreResultsButton extends React.PureComponent {
constructor(props) {
super(props);
this.getInvalidColumns = this.getInvalidColumns.bind(this);
this.renderInvalidColumnMessage = this.renderInvalidColumnMessage.bind(
this,
);
this.renderInvalidColumnMessage =
this.renderInvalidColumnMessage.bind(this);
}
getColumns() {

View File

@ -221,7 +221,7 @@ function QuerySearch({ actions, displayLimit }: QuerySearchProps) {
value: xt,
label: xt,
}))}
value={(from as unknown) as undefined}
value={from as unknown as undefined}
autosize={false}
onChange={(selected: any) => setFrom(selected?.value)}
/>
@ -230,7 +230,7 @@ function QuerySearch({ actions, displayLimit }: QuerySearchProps) {
name="select-to"
placeholder={t('[To]-')}
options={TIME_OPTIONS.map(xt => ({ value: xt, label: xt }))}
value={(to as unknown) as undefined}
value={to as unknown as undefined}
autosize={false}
onChange={(selected: any) => setTo(selected?.value)}
/>
@ -242,7 +242,7 @@ function QuerySearch({ actions, displayLimit }: QuerySearchProps) {
value: s,
label: s,
}))}
value={(status as unknown) as undefined}
value={status as unknown as undefined}
isLoading={false}
autosize={false}
onChange={(selected: any) => setStatus(selected?.value)}

View File

@ -203,30 +203,25 @@ export default class ResultSet extends React.PureComponent<
this.fetchResults = this.fetchResults.bind(this);
this.popSelectStar = this.popSelectStar.bind(this);
this.reFetchQueryResults = this.reFetchQueryResults.bind(this);
this.toggleExploreResultsButton = this.toggleExploreResultsButton.bind(
this,
);
this.toggleExploreResultsButton =
this.toggleExploreResultsButton.bind(this);
this.handleSaveInDataset = this.handleSaveInDataset.bind(this);
this.handleHideSaveModal = this.handleHideSaveModal.bind(this);
this.handleDatasetNameChange = this.handleDatasetNameChange.bind(this);
this.handleSaveDatasetRadioBtnState = this.handleSaveDatasetRadioBtnState.bind(
this,
);
this.handleSaveDatasetRadioBtnState =
this.handleSaveDatasetRadioBtnState.bind(this);
this.handleOverwriteCancel = this.handleOverwriteCancel.bind(this);
this.handleOverwriteDataset = this.handleOverwriteDataset.bind(this);
this.handleOverwriteDatasetOption = this.handleOverwriteDatasetOption.bind(
this,
);
this.handleOverwriteDatasetOption =
this.handleOverwriteDatasetOption.bind(this);
this.handleSaveDatasetModalSearch = debounce(
this.handleSaveDatasetModalSearch.bind(this),
1000,
);
this.handleFilterAutocompleteOption = this.handleFilterAutocompleteOption.bind(
this,
);
this.handleOnChangeAutoComplete = this.handleOnChangeAutoComplete.bind(
this,
);
this.handleFilterAutocompleteOption =
this.handleFilterAutocompleteOption.bind(this);
this.handleOnChangeAutoComplete =
this.handleOnChangeAutoComplete.bind(this);
this.handleExploreBtnClick = this.handleExploreBtnClick.bind(this);
}

View File

@ -184,9 +184,8 @@ class SqlEditor extends React.PureComponent {
);
this.queryPane = this.queryPane.bind(this);
this.renderQueryLimit = this.renderQueryLimit.bind(this);
this.getAceEditorAndSouthPaneHeights = this.getAceEditorAndSouthPaneHeights.bind(
this,
);
this.getAceEditorAndSouthPaneHeights =
this.getAceEditorAndSouthPaneHeights.bind(this);
this.getSqlEditorHeight = this.getSqlEditorHeight.bind(this);
this.requestValidation = debounce(
this.requestValidation.bind(this),
@ -456,10 +455,8 @@ class SqlEditor extends React.PureComponent {
queryPane() {
const hotkeys = this.getHotkeyConfig();
const {
aceEditorHeight,
southPaneHeight,
} = this.getAceEditorAndSouthPaneHeights(
const { aceEditorHeight, southPaneHeight } =
this.getAceEditorAndSouthPaneHeights(
this.state.height,
this.state.northPercent,
this.state.southPercent,

View File

@ -84,9 +84,8 @@ class TabbedSqlEditors extends React.PureComponent {
this.removeQueryEditor = this.removeQueryEditor.bind(this);
this.renameTab = this.renameTab.bind(this);
this.toggleLeftBar = this.toggleLeftBar.bind(this);
this.removeAllOtherQueryEditors = this.removeAllOtherQueryEditors.bind(
this,
);
this.removeAllOtherQueryEditors =
this.removeAllOtherQueryEditors.bind(this);
this.duplicateQueryEditor = this.duplicateQueryEditor.bind(this);
this.handleSelect = this.handleSelect.bind(this);
this.handleEdit = this.handleEdit.bind(this);

View File

@ -110,9 +110,8 @@ const RefreshOverlayWrapper = styled.div`
class Chart extends React.PureComponent {
constructor(props) {
super(props);
this.handleRenderContainerFailure = this.handleRenderContainerFailure.bind(
this,
);
this.handleRenderContainerFailure =
this.handleRenderContainerFailure.bind(this);
}
componentDidMount() {

View File

@ -162,13 +162,8 @@ class ChartRenderer extends React.Component {
}
render() {
const {
chartAlert,
chartStatus,
vizType,
chartId,
refreshOverlayVisible,
} = this.props;
const { chartAlert, chartStatus, vizType, chartId, refreshOverlayVisible } =
this.props;
// Skip chart rendering
if (

View File

@ -574,8 +574,8 @@ export function redirectSQLLab(formData) {
export function refreshChart(chartKey, force, dashboardId) {
return (dispatch, getState) => {
const chart = (getState().charts || {})[chartKey];
const timeout = getState().dashboardInfo.common.conf
.SUPERSET_WEBSERVER_TIMEOUT;
const timeout =
getState().dashboardInfo.common.conf.SUPERSET_WEBSERVER_TIMEOUT;
if (
!chart.latestQueryFormData ||

View File

@ -70,12 +70,8 @@ class AnchorLink extends React.PureComponent {
}
render() {
const {
anchorLinkId,
filters,
showShortLinkButton,
placement,
} = this.props;
const { anchorLinkId, filters, showShortLinkButton, placement } =
this.props;
return (
<span className="anchor-link-container" id={anchorLinkId}>
{showShortLinkButton && (

View File

@ -53,7 +53,7 @@ function DefaultPlaceholder({
*/
export default function AsyncEsmComponent<
P = PlaceholderProps,
M = React.ComponentType<P> | { default: React.ComponentType<P> }
M = React.ComponentType<P> | { default: React.ComponentType<P> },
>(
/**
* A promise generator that returns the React component to render.

View File

@ -25,10 +25,12 @@ export interface BadgeProps extends AntdBadgeProps {
textColor?: string;
}
const Badge = styled((
const Badge = styled(
(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
{ textColor, ...props }: BadgeProps,
) => <AntdBadge {...props} />)`
) => <AntdBadge {...props} />,
)`
& > sup {
padding: 0 ${({ theme }) => theme.gridUnit * 2}px;
background: ${({ theme, color }) => color || theme.colors.primary.base};

View File

@ -93,8 +93,8 @@ test('renders with custom properties', () => {
});
const header = document.getElementsByClassName('ant-collapse-header')[0];
const arrow = document.getElementsByClassName('ant-collapse-arrow')[0]
.children[0];
const arrow =
document.getElementsByClassName('ant-collapse-arrow')[0].children[0];
const headerStyle = window.getComputedStyle(header);
const arrowStyle = window.getComputedStyle(arrow);

View File

@ -146,7 +146,8 @@ export default function DatabaseSelector({
const [refresh, setRefresh] = useState(0);
const loadDatabases = useMemo(
() => async (
() =>
async (
search: string,
page: number,
pageSize: number,

View File

@ -452,9 +452,8 @@ class DatasourceEditor extends React.PureComponent {
this.onChangeEditMode = this.onChangeEditMode.bind(this);
this.onDatasourcePropChange = this.onDatasourcePropChange.bind(this);
this.onDatasourceChange = this.onDatasourceChange.bind(this);
this.tableChangeAndSyncMetadata = this.tableChangeAndSyncMetadata.bind(
this,
);
this.tableChangeAndSyncMetadata =
this.tableChangeAndSyncMetadata.bind(this);
this.syncMetadata = this.syncMetadata.bind(this);
this.setColumns = this.setColumns.bind(this);
this.validateAndChange = this.validateAndChange.bind(this);

View File

@ -52,10 +52,8 @@ export default function EditableTitle({
const [isEditing, setIsEditing] = useState(editing);
const [currentTitle, setCurrentTitle] = useState(title);
const [lastTitle, setLastTitle] = useState(title);
const [
contentBoundingRect,
setContentBoundingRect,
] = useState<DOMRect | null>(null);
const [contentBoundingRect, setContentBoundingRect] =
useState<DOMRect | null>(null);
// Used so we can access the DOM element if a user clicks on this component.
const contentRef = useRef<any | HTMLInputElement | HTMLTextAreaElement>();

View File

@ -38,10 +38,9 @@ function TimeoutErrorMessage({
}: ErrorMessageComponentProps<TimeoutErrorExtra>) {
const { extra, level } = error;
const isVisualization = (['dashboard', 'explore'] as (
| string
| undefined
)[]).includes(source);
const isVisualization = (
['dashboard', 'explore'] as (string | undefined)[]
).includes(source);
const subtitle = isVisualization
? tn(

View File

@ -96,12 +96,12 @@ export type SupersetError<ExtraType = Record<string, any> | null> = {
message: string;
};
export type ErrorMessageComponentProps<
ExtraType = Record<string, any> | null
> = {
export type ErrorMessageComponentProps<ExtraType = Record<string, any> | null> =
{
error: SupersetError<ExtraType>;
source?: ErrorSource;
subtitle?: React.ReactNode;
};
export type ErrorMessageComponent = React.ComponentType<ErrorMessageComponentProps>;
export type ErrorMessageComponent =
React.ComponentType<ErrorMessageComponentProps>;

View File

@ -126,9 +126,8 @@ const ImportModelsModal: FunctionComponent<ImportModelsModalProps> = ({
}) => {
const [isHidden, setIsHidden] = useState<boolean>(true);
const [passwords, setPasswords] = useState<Record<string, string>>({});
const [needsOverwriteConfirm, setNeedsOverwriteConfirm] = useState<boolean>(
false,
);
const [needsOverwriteConfirm, setNeedsOverwriteConfirm] =
useState<boolean>(false);
const [confirmedOverwrite, setConfirmedOverwrite] = useState<boolean>(false);
const [fileList, setFileList] = useState<UploadFile[]>([]);
const [importingModel, setImportingModel] = useState<boolean>(false);

View File

@ -45,15 +45,8 @@ export default function Label(props: LabelProps) {
const theme = useTheme();
const { colors, transitionTiming } = theme;
const { type, onClick, children, ...rest } = props;
const {
primary,
secondary,
grayscale,
success,
warning,
error,
info,
} = colors;
const { primary, secondary, grayscale, success, warning, error, info } =
colors;
let backgroundColor = grayscale.light3;
let backgroundColorHover = onClick ? primary.light2 : grayscale.light3;

View File

@ -41,10 +41,9 @@ export const InteractivePopoverDropdown = (props: Props) => {
const { value, buttonType, optionType, ...rest } = props;
const [currentValue, setCurrentValue] = useState(value);
const newElementHandler = (type: ElementType) => ({
label,
value,
}: OptionProps) => {
const newElementHandler =
(type: ElementType) =>
({ label, value }: OptionProps) => {
if (type === 'button') {
return (
<button type="button" key={value}>

View File

@ -43,10 +43,8 @@ export default function HeaderReportActionsDropDown({
const reports = useSelector<any, AlertObject>(state => state.reports);
const reportsIds = Object.keys(reports);
const report = reports[reportsIds[0]];
const [
currentReportDeleting,
setCurrentReportDeleting,
] = useState<AlertObject | null>(null);
const [currentReportDeleting, setCurrentReportDeleting] =
useState<AlertObject | null>(null);
const theme = useTheme();
const toggleActiveKey = async (data: AlertObject, checked: boolean) => {

View File

@ -71,7 +71,7 @@ type AnyReactSelect<OptionType extends OptionTypeBase> =
export type SupersetStyledSelectProps<
OptionType extends OptionTypeBase,
T extends WindowedSelectProps<OptionType> = WindowedSelectProps<OptionType>
T extends WindowedSelectProps<OptionType> = WindowedSelectProps<OptionType>,
> = T & {
// additional props for easier usage or backward compatibility
labelKey?: string;
@ -103,7 +103,7 @@ function styled<
| WindowedSelectComponentType<OptionType>
| ComponentType<
SelectProps<OptionType>
> = WindowedSelectComponentType<OptionType>
> = WindowedSelectComponentType<OptionType>,
>(SelectComponent: SelectComponentType) {
type SelectProps = SupersetStyledSelectProps<OptionType>;
type Components = SelectComponents<OptionType>;
@ -113,7 +113,8 @@ function styled<
});
// default components for the given OptionType
const supersetDefaultComponents: SelectComponentsConfig<OptionType> = DEFAULT_COMPONENTS;
const supersetDefaultComponents: SelectComponentsConfig<OptionType> =
DEFAULT_COMPONENTS;
const getSortableMultiValue = (MultiValue: Components['MultiValue']) =>
SortableElement((props: MultiValueProps<OptionType>) => {

View File

@ -246,10 +246,8 @@ const defaultSortComparator = (a: AntdLabeledValue, b: AntdLabeledValue) => {
* It creates a comparator to check for a specific property.
* Can be used with string and number property values.
* */
export const propertyComparator = (property: string) => (
a: AntdLabeledValue,
b: AntdLabeledValue,
) => {
export const propertyComparator =
(property: string) => (a: AntdLabeledValue, b: AntdLabeledValue) => {
if (typeof a[property] === 'string' && typeof b[property] === 'string') {
return a[property].localeCompare(b[property]);
}
@ -300,9 +298,8 @@ const Select = ({
const shouldShowSearch = isAsync || allowNewOptions ? true : showSearch;
const initialOptions =
options && Array.isArray(options) ? options : EMPTY_OPTIONS;
const [selectOptions, setSelectOptions] = useState<OptionsType>(
initialOptions,
);
const [selectOptions, setSelectOptions] =
useState<OptionsType>(initialOptions);
const shouldUseChildrenOptions = !!selectOptions.find(
opt => opt?.customLabel,
);

View File

@ -59,9 +59,8 @@ type MenuListPropsChildren<OptionType> =
| Component<OptionProps<OptionType>>[]
| ReactElement[];
export type MenuListProps<
OptionType extends OptionTypeBase
> = MenuListComponentProps<OptionType> & {
export type MenuListProps<OptionType extends OptionTypeBase> =
MenuListComponentProps<OptionType> & {
children: MenuListPropsChildren<OptionType>;
// theme is not present with built-in @types/react-select, but is actually
// available via CommonProps.

View File

@ -29,15 +29,13 @@ const { MenuList: DefaultMenuList } = defaultComponents;
export const DEFAULT_WINDOW_THRESHOLD = 100;
export type WindowedSelectProps<
OptionType extends OptionTypeBase
> = SelectProps<OptionType> & {
export type WindowedSelectProps<OptionType extends OptionTypeBase> =
SelectProps<OptionType> & {
windowThreshold?: number;
} & WindowedMenuListProps['selectProps'];
export type WindowedSelectComponentType<
OptionType extends OptionTypeBase
> = FunctionComponent<WindowedSelectProps<OptionType>>;
export type WindowedSelectComponentType<OptionType extends OptionTypeBase> =
FunctionComponent<WindowedSelectProps<OptionType>>;
export function MenuList<OptionType extends OptionTypeBase>({
children,

View File

@ -71,8 +71,7 @@ export type ThemeConfig = {
colors: {
// add known colors
[key in keyof typeof reactSelectColors]: string;
} &
{
} & {
[key in keyof ReturnType<typeof colors>]: string;
} & {
[key: string]: string; // any other colors
@ -89,9 +88,8 @@ export type ThemeConfig = {
export type PartialThemeConfig = RecursivePartial<ThemeConfig>;
export const defaultTheme: (
theme: SupersetTheme,
) => PartialThemeConfig = theme => ({
export const defaultTheme: (theme: SupersetTheme) => PartialThemeConfig =
theme => ({
borderRadius: theme.borderRadius,
zIndex: 11,
colors: colors(theme),
@ -314,13 +312,8 @@ export type InputProps = ReactSelectInputProps & {
inputStyle?: object;
};
const {
ClearIndicator,
DropdownIndicator,
Option,
Input,
SelectContainer,
} = defaultComponents as Required<DeepNonNullable<SelectComponentsType>>;
const { ClearIndicator, DropdownIndicator, Option, Input, SelectContainer } =
defaultComponents as Required<DeepNonNullable<SelectComponentsType>>;
export const DEFAULT_COMPONENTS: SelectComponentsType = {
SelectContainer: ({ children, ...props }) => {

View File

@ -60,9 +60,9 @@ export interface SetChartConfigFail {
type: typeof SET_CHART_CONFIG_FAIL;
chartConfiguration: ChartConfiguration;
}
export const setChartConfiguration = (
chartConfiguration: ChartConfiguration,
) => async (dispatch: Dispatch, getState: () => any) => {
export const setChartConfiguration =
(chartConfiguration: ChartConfiguration) =>
async (dispatch: Dispatch, getState: () => any) => {
dispatch({
type: SET_CHART_CONFIG_BEGIN,
chartConfiguration,

View File

@ -38,7 +38,8 @@ export const UPDATE_COMPONENTS = 'UPDATE_COMPONENTS';
// an additional setUnsavedChanges(true) action after the dispatch in the case
// that dashboardState.hasUnsavedChanges is false.
function setUnsavedChangesAfterAction(action) {
return (...args) => (dispatch, getState) => {
return (...args) =>
(dispatch, getState) => {
const result = action(...args);
if (typeof result === 'function') {
dispatch(result(dispatch, getState));

View File

@ -62,11 +62,13 @@ import getNativeFilterConfig from '../util/filterboxMigrationHelper';
export const HYDRATE_DASHBOARD = 'HYDRATE_DASHBOARD';
export const hydrateDashboard = (
export const hydrateDashboard =
(
dashboardData,
chartData,
filterboxMigrationState = FILTER_BOX_MIGRATION_STATES.NOOP,
) => (dispatch, getState) => {
) =>
(dispatch, getState) => {
const { user, common } = getState();
const { metadata } = dashboardData;
@ -96,9 +98,8 @@ export const hydrateDashboard = (
const colorMap = isString(metadata.label_colors)
? JSON.parse(metadata.label_colors)
: metadata.label_colors;
const categoricalNamespace = CategoricalColorNamespace.getNamespace(
namespace,
);
const categoricalNamespace =
CategoricalColorNamespace.getNamespace(namespace);
Object.keys(colorMap).forEach(label => {
categoricalNamespace.setColor(label, colorMap[label]);
@ -363,7 +364,11 @@ export const hydrateDashboard = (
'Superset',
roles,
),
superset_can_explore: findPermission('can_explore', 'Superset', roles),
superset_can_explore: findPermission(
'can_explore',
'Superset',
roles,
),
superset_can_share: findPermission(
'can_share_chart',
'Superset',

View File

@ -111,9 +111,9 @@ export interface UpdateFilterSetFail {
type: typeof UPDATE_FILTER_SET_FAIL;
}
export const setFilterConfiguration = (
filterConfig: FilterConfiguration,
) => async (dispatch: Dispatch, getState: () => any) => {
export const setFilterConfiguration =
(filterConfig: FilterConfiguration) =>
async (dispatch: Dispatch, getState: () => any) => {
dispatch({
type: SET_FILTER_CONFIG_BEGIN,
filterConfig,
@ -169,13 +169,15 @@ export const setFilterConfiguration = (
}
};
export const setInScopeStatusOfFilters = (
export const setInScopeStatusOfFilters =
(
filterScopes: {
filterId: string;
chartsInScope: number[];
tabsInScope: string[];
}[],
) => async (dispatch: Dispatch, getState: () => any) => {
) =>
async (dispatch: Dispatch, getState: () => any) => {
const filters = getState().nativeFilters?.filters;
const filtersWithScopes = filterScopes.map(scope => ({
...filters[scope.filterId],
@ -201,10 +203,8 @@ export interface SetBootstrapData {
data: BootstrapData;
}
export const getFilterSets = () => async (
dispatch: Dispatch,
getState: () => RootState,
) => {
export const getFilterSets =
() => async (dispatch: Dispatch, getState: () => RootState) => {
const dashboardId = getState().dashboardInfo.id;
const fetchFilterSets = makeApi<
null,
@ -234,10 +234,9 @@ export const getFilterSets = () => async (
});
};
export const createFilterSet = (filterSet: Omit<FilterSet, 'id'>) => async (
dispatch: Function,
getState: () => RootState,
) => {
export const createFilterSet =
(filterSet: Omit<FilterSet, 'id'>) =>
async (dispatch: Function, getState: () => RootState) => {
const dashboardId = getState().dashboardInfo.id;
const postFilterSets = makeApi<
Partial<FilterSetFullData & { json_metadata: any }>,
@ -255,7 +254,8 @@ export const createFilterSet = (filterSet: Omit<FilterSet, 'id'>) => async (
type: CREATE_FILTER_SET_BEGIN,
});
const serverFilterSet: Omit<FilterSet, 'id' | 'name'> & { name?: string } = {
const serverFilterSet: Omit<FilterSet, 'id' | 'name'> & { name?: string } =
{
...filterSet,
};
@ -274,10 +274,9 @@ export const createFilterSet = (filterSet: Omit<FilterSet, 'id'>) => async (
dispatch(getFilterSets());
};
export const updateFilterSet = (filterSet: FilterSet) => async (
dispatch: Function,
getState: () => RootState,
) => {
export const updateFilterSet =
(filterSet: FilterSet) =>
async (dispatch: Function, getState: () => RootState) => {
const dashboardId = getState().dashboardInfo.id;
const postFilterSets = makeApi<
Partial<FilterSetFullData & { json_metadata: any }>,
@ -312,10 +311,9 @@ export const updateFilterSet = (filterSet: FilterSet) => async (
dispatch(getFilterSets());
};
export const deleteFilterSet = (filterSetId: number) => async (
dispatch: Function,
getState: () => RootState,
) => {
export const deleteFilterSet =
(filterSetId: number) =>
async (dispatch: Function, getState: () => RootState) => {
const dashboardId = getState().dashboardInfo.id;
const deleteFilterSets = makeApi<{}, {}>({
method: 'DELETE',

View File

@ -56,13 +56,8 @@ interface FilterBoxMigrationModalProps {
hideFooter: boolean;
}
const FilterBoxMigrationModal: FunctionComponent<FilterBoxMigrationModalProps> = ({
onClickReview,
onClickSnooze,
onHide,
show,
hideFooter = false,
}) => (
const FilterBoxMigrationModal: FunctionComponent<FilterBoxMigrationModalProps> =
({ onClickReview, onClickSnooze, onHide, show, hideFooter = false }) => (
<StyledFilterBoxMigrationModal
show={show}
onHide={onHide}

View File

@ -611,10 +611,8 @@ class Header extends React.PureComponent {
onHide={this.hidePropertiesModal}
colorScheme={this.props.colorScheme}
onSubmit={updates => {
const {
dashboardInfoChanged,
dashboardTitleChanged,
} = this.props;
const { dashboardInfoChanged, dashboardTitleChanged } =
this.props;
dashboardInfoChanged({
slug: updates.slug,
metadata: JSON.parse(updates.jsonMetadata),

View File

@ -85,7 +85,9 @@ const handleErrorResponse = async response => {
});
};
const loadAccessOptions = accessType => (input = '') => {
const loadAccessOptions =
accessType =>
(input = '') => {
const query = rison.encode({ filter: input });
return SupersetClient.get({
endpoint: `/api/v1/dashboard/related/${accessType}?q=${query}`,

View File

@ -30,7 +30,8 @@ const defaultProps = {
};
test('renders with unpublished status and readonly permissions', async () => {
const tooltip = /This dashboard is not published which means it will not show up in the list of dashboards/;
const tooltip =
/This dashboard is not published which means it will not show up in the list of dashboards/;
render(<PublishedStatus {...defaultProps} />);
expect(screen.getByText('Draft')).toBeInTheDocument();
userEvent.hover(screen.getByText('Draft'));
@ -38,7 +39,8 @@ test('renders with unpublished status and readonly permissions', async () => {
});
test('renders with unpublished status and write permissions', async () => {
const tooltip = /This dashboard is not published, it will not show up in the list of dashboards/;
const tooltip =
/This dashboard is not published, it will not show up in the list of dashboards/;
const savePublished = jest.fn();
render(
<PublishedStatus

View File

@ -179,11 +179,8 @@ export default class FilterScopeSelector extends React.PureComponent {
}
onCheckFilterScope(checked = []) {
const {
activeFilterField,
filterScopeMap,
checkedFilterFields,
} = this.state;
const { activeFilterField, filterScopeMap, checkedFilterFields } =
this.state;
const key = getKeyForFilterScopeTree({
activeFilterField,
@ -213,11 +210,8 @@ export default class FilterScopeSelector extends React.PureComponent {
}
onExpandFilterScope(expanded = []) {
const {
activeFilterField,
checkedFilterFields,
filterScopeMap,
} = this.state;
const { activeFilterField, checkedFilterFields, filterScopeMap } =
this.state;
const key = getKeyForFilterScopeTree({
activeFilterField,
checkedFilterFields,
@ -347,11 +341,8 @@ export default class FilterScopeSelector extends React.PureComponent {
// Reset nodes back to unfiltered state
if (!this.state.searchText) {
this.setState(prevState => {
const {
activeFilterField,
checkedFilterFields,
filterScopeMap,
} = prevState;
const { activeFilterField, checkedFilterFields, filterScopeMap } =
prevState;
const key = getKeyForFilterScopeTree({
activeFilterField,
checkedFilterFields,
@ -370,11 +361,8 @@ export default class FilterScopeSelector extends React.PureComponent {
});
} else {
const updater = prevState => {
const {
activeFilterField,
checkedFilterFields,
filterScopeMap,
} = prevState;
const { activeFilterField, checkedFilterFields, filterScopeMap } =
prevState;
const key = getKeyForFilterScopeTree({
activeFilterField,
checkedFilterFields,

View File

@ -167,10 +167,8 @@ class ChartHolder extends React.Component {
static getDerivedStateFromProps(props, state) {
const { component, directPathToChild, directPathLastUpdated } = props;
const {
label: columnName,
chart: chartComponentId,
} = getChartAndLabelComponentIdFromPath(directPathToChild);
const { label: columnName, chart: chartComponentId } =
getChartAndLabelComponentIdFromPath(directPathToChild);
if (
directPathLastUpdated !== state.directPathLastUpdated &&

View File

@ -83,8 +83,9 @@ describe('ChartHolder', () => {
it('should render full size', async () => {
renderWrapper();
const chart = (screen.getByTestId('slice-container')
.firstChild as HTMLElement).style;
const chart = (
screen.getByTestId('slice-container').firstChild as HTMLElement
).style;
await waitFor(() => expect(chart?.width).toBe('992px'));
expect(chart?.height).toBe('714px');

View File

@ -110,13 +110,8 @@ class Markdown extends React.PureComponent {
}
static getDerivedStateFromProps(nextProps, state) {
const {
hasError,
editorMode,
markdownSource,
undoLength,
redoLength,
} = state;
const { hasError, editorMode, markdownSource, undoLength, redoLength } =
state;
const {
component: nextComponent,
undoLength: nextUndoLength,

View File

@ -135,10 +135,10 @@ const CascadePopover: React.FC<CascadePopoverProps> = ({
};
const allFilters = getAllFilters(filter);
const activeFilters = useMemo(() => getActiveChildren(filter) || [filter], [
filter,
getActiveChildren,
]);
const activeFilters = useMemo(
() => getActiveChildren(filter) || [filter],
[filter, getActiveChildren],
);
useEffect(() => {
const focusedFilterId = currentPathToChild?.[0];

View File

@ -73,9 +73,8 @@ const FilterControls: FC<FilterControlsProps> = ({
}, [filterValues, dataMaskSelected]);
const cascadeFilterIds = new Set(cascadeFilters.map(item => item.id));
const [filtersInScope, filtersOutOfScope] = useSelectFiltersInScope(
cascadeFilters,
);
const [filtersInScope, filtersOutOfScope] =
useSelectFiltersInScope(cascadeFilters);
const dashboardHasTabs = useDashboardHasTabs();
const showCollapsePanel = dashboardHasTabs && cascadeFilters.length > 0;

View File

@ -213,9 +213,10 @@ const FilterValue: React.FC<FilterProps> = ({
() => dispatchFocusAction(dispatch, id),
[dispatch, id],
);
const unsetFocusedFilter = useCallback(() => dispatchFocusAction(dispatch), [
dispatch,
]);
const unsetFocusedFilter = useCallback(
() => dispatchFocusAction(dispatch),
[dispatch],
);
const hooks = useMemo(
() => ({ setDataMask, setFocusedFilter, unsetFocusedFilter }),

View File

@ -151,9 +151,8 @@ const FilterBar: React.FC<FiltersBarProps> = ({
const history = useHistory();
const dataMaskApplied: DataMaskStateWithId = useNativeFiltersDataMask();
const [editFilterSetId, setEditFilterSetId] = useState<number | null>(null);
const [dataMaskSelected, setDataMaskSelected] = useImmer<DataMaskStateWithId>(
dataMaskApplied,
);
const [dataMaskSelected, setDataMaskSelected] =
useImmer<DataMaskStateWithId>(dataMaskApplied);
const dispatch = useDispatch();
const filterSets = useFilterSets();
const filterSetFilterValues = Object.values(filterSets);
@ -267,9 +266,10 @@ const FilterBar: React.FC<FiltersBarProps> = ({
});
}, [dataMaskSelected, dispatch]);
const openFiltersBar = useCallback(() => toggleFiltersBar(true), [
toggleFiltersBar,
]);
const openFiltersBar = useCallback(
() => toggleFiltersBar(true),
[toggleFiltersBar],
);
useFilterUpdates(dataMaskSelected, setDataMaskSelected);
const isApplyDisabled = checkIsApplyDisabled(

View File

@ -27,9 +27,9 @@ export enum TabIds {
FilterSets = 'filterSets',
}
export function mapParentFiltersToChildren(
filters: Filter[],
): { [id: string]: Filter[] } {
export function mapParentFiltersToChildren(filters: Filter[]): {
[id: string]: Filter[];
} {
const cascadeChildren = {};
filters.forEach(filter => {
const [parentId] = filter.cascadeParentIds || [];

View File

@ -104,9 +104,8 @@ const FilterTitlePane: React.FC<Props> = ({
setTimeout(() => {
const element = document.getElementById('native-filters-tabs');
if (element) {
const navList = element.getElementsByClassName(
'ant-tabs-nav-list',
)[0];
const navList =
element.getElementsByClassName('ant-tabs-nav-list')[0];
navList.scrollTop = navList.scrollHeight;
}
}, 0);

View File

@ -77,8 +77,8 @@ export function ColumnSelect({
[columns, filterValues],
);
const currentFilterType = form.getFieldValue('filters')?.[filterId]
.filterType;
const currentFilterType =
form.getFieldValue('filters')?.[filterId].filterType;
const currentColumn = useMemo(
() => columns?.find(column => column.column_name === value),
[columns, value],

View File

@ -390,9 +390,9 @@ const FiltersConfigForm = (
return currentDataset ? hasTemporalColumns(currentDataset) : true;
}, [formFilter?.dataset?.value, loadedDatasets]);
const hasDataset =
// @ts-ignore
const hasDataset = !!nativeFilterItems[formFilter?.filterType]?.value
?.datasourceCount;
!!nativeFilterItems[formFilter?.filterType]?.value?.datasourceCount;
const datasetId =
formFilter?.dataset?.value ??
@ -514,12 +514,8 @@ const FiltersConfigForm = (
...formFilter,
});
const [
hasDefaultValue,
isRequired,
defaultValueTooltip,
setHasDefaultValue,
] = useDefaultValue(formFilter, filterToEdit);
const [hasDefaultValue, isRequired, defaultValueTooltip, setHasDefaultValue] =
useDefaultValue(formFilter, filterToEdit);
const showDataset =
!datasetId || datasetDetails || formFilter?.dataset?.label;

View File

@ -118,13 +118,15 @@ export const validateForm = async (
}
};
export const createHandleSave = (
export const createHandleSave =
(
filterConfigMap: Record<string, Filter>,
filterIds: string[],
removedFilters: Record<string, FilterRemoval>,
saveForm: Function,
values: NativeFiltersForm,
) => async () => {
) =>
async () => {
const newFilterConfig: FilterConfiguration = filterIds
.filter(id => !removedFilters[id])
.map(id => {
@ -208,7 +210,8 @@ export function buildFilterGroup(nodes: FilterHierarchyNode[]) {
}
return group;
}
export const createHandleTabEdit = (
export const createHandleTabEdit =
(
setRemovedFilters: (
value:
| ((
@ -221,11 +224,14 @@ export const createHandleTabEdit = (
val: string[][] | ((prevState: string[][]) => string[][]),
) => void,
setFilterHierarchy: (
state: FilterHierarchy | ((prevState: FilterHierarchy) => FilterHierarchy),
state:
| FilterHierarchy
| ((prevState: FilterHierarchy) => FilterHierarchy),
) => void,
addFilter: Function,
filterHierarchy: FilterHierarchy,
) => (filterId: string, action: 'add' | 'remove') => {
) =>
(filterId: string, action: 'add' | 'remove') => {
const completeFilterRemoval = (filterId: string) => {
const buildNewFilterHierarchy = (hierarchy: FilterHierarchy) =>
hierarchy

View File

@ -81,7 +81,8 @@ function mapStateToProps({
).text,
expandedSlices: dashboardState.expandedSlices,
refreshFrequency: dashboardState.refreshFrequency,
shouldPersistRefreshFrequency: !!dashboardState.shouldPersistRefreshFrequency,
shouldPersistRefreshFrequency:
!!dashboardState.shouldPersistRefreshFrequency,
customCss: dashboardState.css,
colorNamespace: dashboardState.colorNamespace,
colorScheme: dashboardState.colorScheme,

View File

@ -72,15 +72,12 @@ const DashboardPage: FC = () => {
);
const { addDangerToast } = useToasts();
const { idOrSlug } = useParams<{ idOrSlug: string }>();
const { result: dashboard, error: dashboardApiError } = useDashboard(
idOrSlug,
);
const { result: charts, error: chartsApiError } = useDashboardCharts(
idOrSlug,
);
const { result: datasets, error: datasetsApiError } = useDashboardDatasets(
idOrSlug,
);
const { result: dashboard, error: dashboardApiError } =
useDashboard(idOrSlug);
const { result: charts, error: chartsApiError } =
useDashboardCharts(idOrSlug);
const { result: datasets, error: datasetsApiError } =
useDashboardDatasets(idOrSlug);
const isDashboardHydrated = useRef(false);
const error = dashboardApiError || chartsApiError;

View File

@ -49,9 +49,9 @@ export function isFilterBox(chartId) {
export function getAppliedFilterValues(chartId) {
// use cached data if possible
if (!(chartId in appliedFilterValuesByChart)) {
const applicableFilters = Object.entries(
activeFilters,
).filter(([, { scope: chartIds }]) => chartIds.includes(chartId));
const applicableFilters = Object.entries(activeFilters).filter(
([, { scope: chartIds }]) => chartIds.includes(chartId),
);
appliedFilterValuesByChart[chartId] = flow(
keyBy(
([filterKey]) => getChartIdAndColumnFromFilterKey(filterKey).column,

View File

@ -103,10 +103,13 @@ enum FILTER_COMPONENT_FILTER_TYPES {
FILTER_RANGE = 'filter_range',
}
const getPreselectedValuesFromDashboard = (
preselectedFilters: PreselectedFiltersMeatadata,
) => (filterKey: string, column: string) => {
if (preselectedFilters[filterKey] && preselectedFilters[filterKey][column]) {
const getPreselectedValuesFromDashboard =
(preselectedFilters: PreselectedFiltersMeatadata) =>
(filterKey: string, column: string) => {
if (
preselectedFilters[filterKey] &&
preselectedFilters[filterKey][column]
) {
// overwrite default values by dashboard default_filters
return preselectedFilters[filterKey][column];
}
@ -218,9 +221,8 @@ export default function getNativeFilterConfig(
time_range,
} = slice.form_data;
const getDashboardDefaultValues = getPreselectedValuesFromDashboard(
preselectFilters,
);
const getDashboardDefaultValues =
getPreselectedValuesFromDashboard(preselectFilters);
if (date_filter) {
const { scope, immune }: FilterScopeType =
@ -488,9 +490,8 @@ export default function getNativeFilterConfig(
}
});
const dependencies: FilterBoxDependencyMap = getFilterboxDependencies(
filterScopes,
);
const dependencies: FilterBoxDependencyMap =
getFilterboxDependencies(filterScopes);
Object.entries(dependencies).forEach(([key, filterFields]) => {
Object.entries(filterFields).forEach(([field, childrenChartIds]) => {
const parentComponentId = filterBoxToFilterComponentMap[key][field];

View File

@ -37,18 +37,14 @@ export default function getComponentWidthFromDrop({
return component.meta.width;
}
const {
width: draggingWidth,
minimumWidth: minDraggingWidth,
} = getDetailedComponentWidth({
const { width: draggingWidth, minimumWidth: minDraggingWidth } =
getDetailedComponentWidth({
component,
components,
});
const {
width: destinationWidth,
occupiedWidth: draggingOccupiedWidth,
} = getDetailedComponentWidth({
const { width: destinationWidth, occupiedWidth: draggingOccupiedWidth } =
getDetailedComponentWidth({
id: destination.id,
components,
});
@ -56,10 +52,8 @@ export default function getComponentWidthFromDrop({
let destinationCapacity = Number(destinationWidth - draggingOccupiedWidth);
if (Number.isNaN(destinationCapacity)) {
const {
width: grandparentWidth,
occupiedWidth: grandparentOccupiedWidth,
} = getDetailedComponentWidth({
const { width: grandparentWidth, occupiedWidth: grandparentOccupiedWidth } =
getDetailedComponentWidth({
id: findParentId({
childId: destination.id,
layout: components,

View File

@ -57,12 +57,11 @@ function getTabChildrenScope({
))
) {
// get all charts from tabChildren that is not in scope
const immuneChartIdsFromTabsNotInScope = getImmuneChartIdsFromTabsNotInScope(
{
const immuneChartIdsFromTabsNotInScope =
getImmuneChartIdsFromTabsNotInScope({
tabs: tabChildren,
tabsInScope: flatMap(tabScopes, ({ scope }) => scope),
},
);
});
const immuneChartIdsFromTabsInScope = flatMap(
Object.values(tabScopes),
({ immune }) => immune,

View File

@ -40,7 +40,7 @@ export default function injectCustomCss(css: string) {
document.querySelector(`.${className}`) || createStyleElement(className);
if ('styleSheet' in style) {
((style as unknown) as MysteryStyleElement).styleSheet.cssText = css;
(style as unknown as MysteryStyleElement).styleSheet.cssText = css;
} else {
style.innerHTML = css;
}

View File

@ -49,9 +49,8 @@ export type ControlProps = {
/**
*
*/
export type ControlComponentProps<
ValueType extends JsonValue = JsonValue
> = Omit<ControlProps, 'value'> & BaseControlComponentProps<ValueType>;
export type ControlComponentProps<ValueType extends JsonValue = JsonValue> =
Omit<ControlProps, 'value'> & BaseControlComponentProps<ValueType>;
export default function Control(props: ControlProps) {
const {

View File

@ -49,14 +49,8 @@ type ExploreActionButtonsProps = {
};
const ActionButton = (props: ActionButtonProps) => {
const {
icon,
text,
tooltip,
className,
onTooltipVisibilityChange,
...rest
} = props;
const { icon, text, tooltip, className, onTooltipVisibilityChange, ...rest } =
props;
return (
<Tooltip
id={`${icon}-tooltip`}

View File

@ -48,7 +48,7 @@ const createProps = () => ({
},
chartStatus: 'rendered',
},
slice: ({
slice: {
cache_timeout: null,
changed_on: '2021-03-19T16:30:56.750230',
changed_on_humanized: '7 days ago',
@ -85,7 +85,7 @@ const createProps = () => ({
slice_id: 318,
slice_name: 'Age distribution of respondents',
slice_url: '/superset/explore/?form_data=%7B%22slice_id%22%3A%20318%7D',
} as unknown) as Slice,
} as unknown as Slice,
slice_name: 'Age distribution of respondents',
actions: {
postChartFormData: () => null,

View File

@ -25,7 +25,7 @@ import userEvent from '@testing-library/user-event';
import PropertiesModal from '.';
const createProps = () => ({
slice: ({
slice: {
cache_timeout: null,
changed_on: '2021-03-19T16:30:56.750230',
changed_on_humanized: '7 days ago',
@ -62,7 +62,7 @@ const createProps = () => ({
slice_id: 318,
slice_name: 'Age distribution of respondents',
slice_url: '/superset/explore/?form_data=%7B%22slice_id%22%3A%20318%7D',
} as unknown) as Slice,
} as unknown as Slice,
show: true,
onHide: jest.fn(),
onSave: jest.fn(),

View File

@ -88,8 +88,13 @@ export default function PropertiesModal({
);
const loadOptions = useMemo(
() => (input = '', page: number, pageSize: number) => {
const query = rison.encode({ filter: input, page, page_size: pageSize });
() =>
(input = '', page: number, pageSize: number) => {
const query = rison.encode({
filter: input,
page,
page_size: pageSize,
});
return SupersetClient.get({
endpoint: `/api/v1/chart/related/owners?q=${query}`,
}).then(response => ({
@ -115,10 +120,12 @@ export default function PropertiesModal({
cache_timeout: cacheTimeout || null,
};
if (selectedOwners) {
payload.owners = (selectedOwners as {
payload.owners = (
selectedOwners as {
value: number;
label: string;
}[]).map(o => o.value);
}[]
).map(o => o.value);
}
try {
const res = await SupersetClient.put({

View File

@ -164,9 +164,8 @@ export default class AnnotationLayer extends React.PureComponent {
this.applyAnnotation = this.applyAnnotation.bind(this);
this.fetchOptions = this.fetchOptions.bind(this);
this.handleAnnotationType = this.handleAnnotationType.bind(this);
this.handleAnnotationSourceType = this.handleAnnotationSourceType.bind(
this,
);
this.handleAnnotationSourceType =
this.handleAnnotationSourceType.bind(this);
this.handleValue = this.handleValue.bind(this);
this.isValidForm = this.isValidForm.bind(this);
}

View File

@ -74,10 +74,8 @@ const ConditionalFormattingControl = ({
...props
}: ConditionalFormattingControlProps) => {
const theme = useTheme();
const [
conditionalFormattingConfigs,
setConditionalFormattingConfigs,
] = useState<ConditionalFormattingConfig[]>(value ?? []);
const [conditionalFormattingConfigs, setConditionalFormattingConfigs] =
useState<ConditionalFormattingConfig[]>(value ?? []);
useEffect(() => {
if (onChange) {

View File

@ -57,13 +57,13 @@ const operatorOptions = [
{ value: COMPARATOR.BETWEEN_OR_RIGHT_EQUAL, label: '< x ≤', order: 10 },
];
const targetValueValidator = (
const targetValueValidator =
(
compare: (targetValue: number, compareValue: number) => boolean,
rejectMessage: string,
) => (targetValue: number | string) => (
_: any,
compareValue: number | string,
) => {
) =>
(targetValue: number | string) =>
(_: any, compareValue: number | string) => {
if (
!targetValue ||
!compareValue ||

View File

@ -116,9 +116,8 @@ class DatasourceControl extends React.PureComponent {
showChangeDatasourceModal: false,
};
this.onDatasourceSave = this.onDatasourceSave.bind(this);
this.toggleChangeDatasourceModal = this.toggleChangeDatasourceModal.bind(
this,
);
this.toggleChangeDatasourceModal =
this.toggleChangeDatasourceModal.bind(this);
this.toggleEditDatasourceModal = this.toggleEditDatasourceModal.bind(this);
this.toggleShowDatasource = this.toggleShowDatasource.bind(this);
this.handleMenuItemClick = this.handleMenuItemClick.bind(this);

View File

@ -93,7 +93,8 @@ export const SINCE_MODE_OPTIONS: SelectOptionType[] = [
{ value: 'today', label: t('Midnight'), order: 3 },
];
export const UNTIL_MODE_OPTIONS: SelectOptionType[] = SINCE_MODE_OPTIONS.slice();
export const UNTIL_MODE_OPTIONS: SelectOptionType[] =
SINCE_MODE_OPTIONS.slice();
export const COMMON_RANGE_SET: Set<CommonRangeType> = new Set([
'Last day',

View File

@ -32,9 +32,9 @@ export const formatTimeRange = (
) => {
const splitDateRange = timeRange.split(SEPARATOR);
if (splitDateRange.length === 1) return timeRange;
const formattedEndpoints = (
endpoints || ['unknown', 'unknown']
).map((endpoint: string) => (endpoint === 'inclusive' ? '≤' : '<'));
const formattedEndpoints = (endpoints || ['unknown', 'unknown']).map(
(endpoint: string) => (endpoint === 'inclusive' ? '≤' : '<'),
);
return `${formatDateEndpoint(splitDateRange[0], true)} ${
formattedEndpoints[0]

View File

@ -84,12 +84,12 @@ export const customTimeRangeDecode = (
// specific : specific
if (ISO8601_AND_CONSTANT.test(since) && ISO8601_AND_CONSTANT.test(until)) {
const sinceMode = (DATETIME_CONSTANT.includes(since)
? since
: 'specific') as DateTimeModeType;
const untilMode = (DATETIME_CONSTANT.includes(until)
? until
: 'specific') as DateTimeModeType;
const sinceMode = (
DATETIME_CONSTANT.includes(since) ? since : 'specific'
) as DateTimeModeType;
const untilMode = (
DATETIME_CONSTANT.includes(until) ? until : 'specific'
) as DateTimeModeType;
return {
customRange: {
...defaultCustomRange,
@ -110,9 +110,9 @@ export const customTimeRangeDecode = (
since.includes(until)
) {
const [dttm, grainValue, grain] = sinceCapturedGroup.slice(1);
const untilMode = (DATETIME_CONSTANT.includes(until)
? until
: 'specific') as DateTimeModeType;
const untilMode = (
DATETIME_CONSTANT.includes(until) ? until : 'specific'
) as DateTimeModeType;
return {
customRange: {
...defaultCustomRange,
@ -135,9 +135,9 @@ export const customTimeRangeDecode = (
until.includes(since)
) {
const [dttm, grainValue, grain] = [...untilCapturedGroup.slice(1)];
const sinceMode = (DATETIME_CONSTANT.includes(since)
? since
: 'specific') as DateTimeModeType;
const sinceMode = (
DATETIME_CONSTANT.includes(since) ? since : 'specific'
) as DateTimeModeType;
return {
customRange: {
...defaultCustomRange,

View File

@ -88,11 +88,8 @@ const ColumnSelectPopover = ({
isAdhocColumnsEnabled,
}: ColumnSelectPopoverProps) => {
const [initialLabel] = useState(label);
const [
initialAdhocColumn,
initialCalculatedColumn,
initialSimpleColumn,
] = getInitialColumnValues(editedColumn);
const [initialAdhocColumn, initialCalculatedColumn, initialSimpleColumn] =
getInitialColumnValues(editedColumn);
const [adhocColumn, setAdhocColumn] = useState<AdhocColumn | undefined>(
initialAdhocColumn,

View File

@ -81,11 +81,8 @@ const ColumnSelectPopoverTrigger = ({
setPopoverVisible(false);
}, []);
const {
visible,
handleTogglePopover,
handleClosePopover,
} = isControlledComponent
const { visible, handleTogglePopover, handleClosePopover } =
isControlledComponent
? {
visible: props.visible,
handleTogglePopover: props.togglePopover!,

View File

@ -28,7 +28,7 @@ import {
DndFilterSelectProps,
} from 'src/explore/components/controls/DndColumnSelectControl/DndFilterSelect';
import { PLACEHOLDER_DATASOURCE } from 'src/dashboard/constants';
import { DEFAULT_FORM_DATA } from '@superset-ui/plugin-chart-echarts/lib/Timeseries/types';
import { TimeseriesDefaultFormData } from '@superset-ui/plugin-chart-echarts';
const defaultProps: DndFilterSelectProps = {
type: 'DndFilterSelect',
@ -70,7 +70,7 @@ test('renders options with saved metric', () => {
{...defaultProps}
formData={{
...baseFormData,
...DEFAULT_FORM_DATA,
...TimeseriesDefaultFormData,
metrics: ['saved_metric'],
}}
/>,
@ -111,7 +111,7 @@ test('renders options with adhoc metric', () => {
{...defaultProps}
formData={{
...baseFormData,
...DEFAULT_FORM_DATA,
...TimeseriesDefaultFormData,
metrics: [adhocMetric],
}}
/>,

View File

@ -41,9 +41,8 @@ export interface OptionItemInterface {
/**
* Shared control props for all DnD control.
*/
export type DndControlProps<
ValueType extends JsonValue
> = ControlComponentProps<ValueType | ValueType[] | null> & {
export type DndControlProps<ValueType extends JsonValue> =
ControlComponentProps<ValueType | ValueType[] | null> & {
multi?: boolean;
canDelete?: boolean;
ghostButtonText?: string;

View File

@ -121,9 +121,9 @@ export default class AdhocFilter {
this.filterOptionName =
adhocFilter.filterOptionName ||
`filter_${Math.random()
`filter_${Math.random().toString(36).substring(2, 15)}_${Math.random()
.toString(36)
.substring(2, 15)}_${Math.random().toString(36).substring(2, 15)}`;
.substring(2, 15)}`;
}
duplicateWith(nextFields) {

View File

@ -227,10 +227,8 @@ const AdhocFilterEditPopoverSimpleTabContent: React.FC<Props> = props => {
} = useSimpleTabFilterProps(props);
const [suggestions, setSuggestions] = useState<Record<string, any>>([]);
const [comparator, setComparator] = useState(props.adhocFilter.comparator);
const [
loadingComparatorSuggestions,
setLoadingComparatorSuggestions,
] = useState(false);
const [loadingComparatorSuggestions, setLoadingComparatorSuggestions] =
useState(false);
const onInputComparatorChange = (
event: React.ChangeEvent<HTMLInputElement>,

View File

@ -55,9 +55,8 @@ export default class AdhocFilterEditPopoverSqlTabContent extends React.Component
constructor(props) {
super(props);
this.onSqlExpressionChange = this.onSqlExpressionChange.bind(this);
this.onSqlExpressionClauseChange = this.onSqlExpressionClauseChange.bind(
this,
);
this.onSqlExpressionClauseChange =
this.onSqlExpressionClauseChange.bind(this);
this.handleAceEditorRef = this.handleAceEditorRef.bind(this);
this.selectProps = {

View File

@ -80,9 +80,9 @@ export default class AdhocMetric {
this.optionName =
adhocMetric.optionName ||
`metric_${Math.random()
`metric_${Math.random().toString(36).substring(2, 15)}_${Math.random()
.toString(36)
.substring(2, 15)}_${Math.random().toString(36).substring(2, 15)}`;
.substring(2, 15)}`;
}
getDefaultLabel() {

View File

@ -207,19 +207,20 @@ const MetricsControl = ({
[value],
);
const isAddNewMetricDisabled = useCallback(() => !multi && value.length > 0, [
multi,
value.length,
]);
const isAddNewMetricDisabled = useCallback(
() => !multi && value.length > 0,
[multi, value.length],
);
const savedMetricOptions = useMemo(
() => getOptionsForSavedMetrics(savedMetrics, propsValue, null),
[propsValue, savedMetrics],
);
const newAdhocMetric = useMemo(() => new AdhocMetric({ isNew: true }), [
value,
]);
const newAdhocMetric = useMemo(
() => new AdhocMetric({ isNew: true }),
[value],
);
const addNewMetricPopoverTrigger = useCallback(
trigger => {
if (isAddNewMetricDisabled()) {
@ -271,10 +272,10 @@ const MetricsControl = ({
setValue(coerceAdhocMetrics(propsValue));
}, [propsValue]);
const onDropLabel = useCallback(() => handleChange(value), [
handleChange,
value,
]);
const onDropLabel = useCallback(
() => handleChange(value),
[handleChange, value],
);
const valueRenderer = useCallback(
(option, index) => (

View File

@ -46,7 +46,7 @@ const safeStringify = (value?: InputValueType | null) =>
value == null ? '' : String(value);
export default class TextControl<
T extends InputValueType = InputValueType
T extends InputValueType = InputValueType,
> extends React.Component<TextControlProps<T>, TextControlState> {
initialValue?: TextControlProps['value'];

View File

@ -31,8 +31,8 @@ import { testWithId } from 'src/utils/testUtils';
import {
EchartsMixedTimeseriesChartPlugin,
EchartsTimeseriesChartPlugin,
} from '@superset-ui/plugin-chart-echarts/lib';
import { LineChartPlugin } from '@superset-ui/preset-chart-xy/lib';
} from '@superset-ui/plugin-chart-echarts';
import { LineChartPlugin } from '@superset-ui/preset-chart-xy';
import TimeTableChartPlugin from '../../../../visualizations/TimeTable/TimeTableChartPlugin';
import VizTypeControl, { VIZ_TYPE_CONTROL_TEST_ID } from './index';

View File

@ -102,9 +102,12 @@ export const DISABLE_INPUT_OPERATORS = [
Operators.IS_FALSE,
];
export const sqlaAutoGeneratedMetricNameRegex = /^(sum|min|max|avg|count|count_distinct)__.*$/i;
export const sqlaAutoGeneratedMetricRegex = /^(LONG|DOUBLE|FLOAT)?(SUM|AVG|MAX|MIN|COUNT)\([A-Z0-9_."]*\)$/i;
export const druidAutoGeneratedMetricRegex = /^(LONG|DOUBLE|FLOAT)?(SUM|MAX|MIN|COUNT)\([A-Z0-9_."]*\)$/i;
export const sqlaAutoGeneratedMetricNameRegex =
/^(sum|min|max|avg|count|count_distinct)__.*$/i;
export const sqlaAutoGeneratedMetricRegex =
/^(LONG|DOUBLE|FLOAT)?(SUM|AVG|MAX|MIN|COUNT)\([A-Z0-9_."]*\)$/i;
export const druidAutoGeneratedMetricRegex =
/^(LONG|DOUBLE|FLOAT)?(SUM|MAX|MIN|COUNT)\([A-Z0-9_."]*\)$/i;
export const TIME_FILTER_LABELS = {
time_range: t('Time range'),

View File

@ -47,10 +47,8 @@ export function findControlItem(
const getMemoizedControlConfig = memoizeOne(
(controlKey, controlPanelConfig) => {
const {
controlOverrides = {},
controlPanelSections = [],
} = controlPanelConfig;
const { controlOverrides = {}, controlPanelSections = [] } =
controlPanelConfig;
const control = expandControlConfig(
findControlItem(controlPanelSections, controlKey),
controlOverrides,

View File

@ -20,14 +20,8 @@ import { ChartProps } from '@superset-ui/core';
import { DEFAULT_FORM_DATA } from './types';
export default function transformProps(chartProps: ChartProps) {
const {
formData,
height,
hooks,
queriesData,
width,
filterState,
} = chartProps;
const { formData, height, hooks, queriesData, width, filterState } =
chartProps;
const {
setDataMask = () => {},
setFocusedFilter = () => {},

View File

@ -68,12 +68,8 @@ const loggerMiddleware = store => next => action => {
return next(action);
}
const {
dashboardInfo,
explore,
impressionId,
dashboardLayout,
} = store.getState();
const { dashboardInfo, explore, impressionId, dashboardLayout } =
store.getState();
let logMetadata = {
impression_id: impressionId,
version: 'v2',

View File

@ -17,11 +17,13 @@
* under the License.
*/
export const cacheWrapper = <T extends Array<any>, U>(
export const cacheWrapper =
<T extends Array<any>, U>(
fn: (...args: T) => U,
cache: Map<string, any>,
keyFn: (...args: T) => string = (...args: T) => JSON.stringify([...args]),
) => (...args: T): U => {
) =>
(...args: T): U => {
const key = keyFn(...args);
if (cache.has(key)) {
return cache.get(key);

View File

@ -21,15 +21,17 @@ import { JsonObject } from '@superset-ui/core';
type TestWithIdType<T> = T extends string ? string : { 'data-test': string };
// Using bem standard
export const testWithId = <T extends string | JsonObject = JsonObject>(
export const testWithId =
<T extends string | JsonObject = JsonObject>(
prefix?: string,
idOnly = false,
) => (id?: string, localIdOnly = false): TestWithIdType<T> => {
) =>
(id?: string, localIdOnly = false): TestWithIdType<T> => {
const resultIdOnly = localIdOnly || idOnly;
if (!id && prefix) {
return (resultIdOnly
? prefix
: { 'data-test': prefix }) as TestWithIdType<T>;
return (
resultIdOnly ? prefix : { 'data-test': prefix }
) as TestWithIdType<T>;
}
if (id && !prefix) {
return (resultIdOnly ? id : { 'data-test': id }) as TestWithIdType<T>;

View File

@ -123,10 +123,8 @@ function AlertList({
const [currentAlert, setCurrentAlert] = useState<Partial<AlertObject> | null>(
null,
);
const [
currentAlertDeleting,
setCurrentAlertDeleting,
] = useState<AlertObject | null>(null);
const [currentAlertDeleting, setCurrentAlertDeleting] =
useState<AlertObject | null>(null);
// Actions
function handleAlertEdit(alert: AlertObject | null) {

View File

@ -408,10 +408,8 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
conf?.ALERT_REPORTS_NOTIFICATION_METHODS || DEFAULT_NOTIFICATION_METHODS;
const [disableSave, setDisableSave] = useState<boolean>(true);
const [
currentAlert,
setCurrentAlert,
] = useState<Partial<AlertObject> | null>();
const [currentAlert, setCurrentAlert] =
useState<Partial<AlertObject> | null>();
const [isHidden, setIsHidden] = useState<boolean>(true);
const [contentType, setContentType] = useState<string>('dashboard');
const [reportFormat, setReportFormat] = useState<string>(
@ -432,10 +430,8 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
contentType === 'chart' &&
(isFeatureEnabled(FeatureFlag.ALERTS_ATTACH_REPORTS) || isReport);
const [
notificationAddState,
setNotificationAddState,
] = useState<NotificationAddStatus>('active');
const [notificationAddState, setNotificationAddState] =
useState<NotificationAddStatus>('active');
const [notificationSettings, setNotificationSettings] = useState<
NotificationSetting[]
>([]);
@ -581,8 +577,13 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
// Fetch data to populate form dropdowns
const loadOwnerOptions = useMemo(
() => (input = '', page: number, pageSize: number) => {
const query = rison.encode({ filter: input, page, page_size: pageSize });
() =>
(input = '', page: number, pageSize: number) => {
const query = rison.encode({
filter: input,
page,
page_size: pageSize,
});
return SupersetClient.get({
endpoint: `/api/v1/report/related/owners?q=${query}`,
}).then(response => ({
@ -629,8 +630,13 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
};
const loadSourceOptions = useMemo(
() => (input = '', page: number, pageSize: number) => {
const query = rison.encode({ filter: input, page, page_size: pageSize });
() =>
(input = '', page: number, pageSize: number) => {
const query = rison.encode({
filter: input,
page,
page_size: pageSize,
});
return SupersetClient.get({
endpoint: `/api/v1/report/related/database?q=${query}`,
}).then(response => {
@ -657,8 +663,13 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
}, [databaseLabel, getSourceData]);
const loadDashboardOptions = useMemo(
() => (input = '', page: number, pageSize: number) => {
const query = rison.encode({ filter: input, page, page_size: pageSize });
() =>
(input = '', page: number, pageSize: number) => {
const query = rison.encode({
filter: input,
page,
page_size: pageSize,
});
return SupersetClient.get({
endpoint: `/api/v1/report/related/dashboard?q=${query}`,
}).then(response => {
@ -726,8 +737,13 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
}, [getChartData, noChartLabel]);
const loadChartOptions = useMemo(
() => (input = '', page: number, pageSize: number) => {
const query = rison.encode({ filter: input, page, page_size: pageSize });
() =>
(input = '', page: number, pageSize: number) => {
const query = rison.encode({
filter: input,
page,
page_size: pageSize,
});
return SupersetClient.get({
endpoint: `/api/v1/report/related/chart?q=${query}`,
}).then(response => {

Some files were not shown because too many files have changed in this diff Show More