chore: upgrade eslint, babel, and prettier (#12393)

This commit is contained in:
Jesse Yang 2021-01-10 17:26:35 -08:00 committed by GitHub
parent 6bee3a0581
commit 9acf48fd1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
69 changed files with 4563 additions and 1964 deletions

View File

@ -135,6 +135,7 @@ module.exports = {
'react/no-unused-prop-types': 0,
'react/prop-types': 0,
'react/require-default-props': 0,
'react/sort-comp': 0, // TODO: re-enable in separate PR
'react/static-property-placement': 0, // re-enable up for discussion
'prettier/prettier': 'error',
},
@ -246,6 +247,7 @@ module.exports = {
'react/no-unused-prop-types': 0,
'react/prop-types': 0,
'react/require-default-props': 0,
'react/sort-comp': 0, // TODO: re-enable in separate PR
'react/static-property-placement': 0, // disabled temporarily
'prettier/prettier': 'error',
},

View File

@ -42,8 +42,9 @@ module.exports = {
plugins: [
'lodash',
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-optional-chaining',
['@babel/plugin-proposal-class-properties', { loose: true }],
['@babel/plugin-proposal-optional-chaining', { loose: true }],
['@babel/plugin-proposal-private-methods', { loose: true }],
['@babel/plugin-transform-runtime', { corejs: 3 }],
'react-hot-loader/babel',
],

View File

@ -40,9 +40,7 @@ describe('Dashboard filter', () => {
let filterId: number;
let aliases: string[];
const getAlias = (id: number) => {
return `@${DASHBOARD_CHART_ALIAS_PREFIX}${id}`;
};
const getAlias = (id: number) => `@${DASHBOARD_CHART_ALIAS_PREFIX}${id}`;
beforeEach(() => {
cy.server();
@ -87,8 +85,8 @@ describe('Dashboard filter', () => {
});
cy.get('.filter_box button').click({ force: true });
cy.wait(aliases.filter(x => x !== getAlias(filterId))).then(requests => {
return Promise.all(
cy.wait(aliases.filter(x => x !== getAlias(filterId))).then(requests =>
Promise.all(
requests.map(async xhr => {
expect(xhr.status).to.eq(200);
const responseBody = await readResponseBlob(xhr.response.body);
@ -108,8 +106,8 @@ describe('Dashboard filter', () => {
val: 'South Asia',
});
}),
);
});
),
);
// TODO add test with South Asia{enter} type action to select filter
});

View File

@ -44,8 +44,8 @@ describe('Dashboard load', () => {
it('should load dashboard', () => {
// wait and verify one-by-one
cy.wait(aliases).then(requests => {
return Promise.all(
cy.wait(aliases).then(requests =>
Promise.all(
requests.map(async xhr => {
expect(xhr.status).to.eq(200);
const responseBody = await readResponseBlob(xhr.response.body);
@ -65,7 +65,7 @@ describe('Dashboard load', () => {
.find(`#chart-id-${sliceId}`)
.should('be.visible');
}),
);
});
),
);
});
});

View File

@ -39,8 +39,8 @@ describe('Dashboard form data', () => {
it('should apply url params to slice requests', () => {
const aliases = getChartAliases(dashboard.slices);
// wait and verify one-by-one
cy.wait(aliases).then(requests => {
return Promise.all(
cy.wait(aliases).then(requests =>
Promise.all(
requests.map(async xhr => {
expect(xhr.status).to.eq(200);
const responseBody = await readResponseBlob(xhr.response.body);
@ -55,7 +55,7 @@ describe('Dashboard form data', () => {
});
}
}),
);
});
),
);
});
});

View File

@ -24,9 +24,8 @@ import rison from 'rison';
import shortid from 'shortid';
import { HEALTH_POP_FORM_DATA_DEFAULTS } from './visualizations/shared.helper';
const apiURL = (endpoint, queryObject) => {
return `${endpoint}?q=${rison.encode(queryObject)}`;
};
const apiURL = (endpoint, queryObject) =>
`${endpoint}?q=${rison.encode(queryObject)}`;
describe('Test explore links', () => {
beforeEach(() => {

View File

@ -48,9 +48,9 @@ Cypress.Commands.add('visitChartByName', name => {
});
});
Cypress.Commands.add('visitChartById', chartId => {
return cy.visit(`${BASE_EXPLORE_URL}{"slice_id": ${chartId}}`);
});
Cypress.Commands.add('visitChartById', chartId =>
cy.visit(`${BASE_EXPLORE_URL}{"slice_id": ${chartId}}`),
);
Cypress.Commands.add('visitChartByParams', params => {
const queryString =

File diff suppressed because it is too large Load Diff

View File

@ -62,7 +62,7 @@
"homepage": "https://superset.apache.org/",
"dependencies": {
"@ant-design/icons": "^4.2.2",
"@babel/runtime-corejs3": "^7.8.4",
"@babel/runtime-corejs3": "^7.12.5",
"@data-ui/sparkline": "^0.0.84",
"@emotion/core": "^10.0.35",
"@superset-ui/chart-controls": "^0.16.4",
@ -176,18 +176,18 @@
"use-query-params": "^1.1.9"
},
"devDependencies": {
"@babel/cli": "^7.11.5",
"@babel/compat-data": "^7.9.6",
"@babel/core": "^7.8.7",
"@babel/node": "^7.8.7",
"@babel/plugin-proposal-class-properties": "^7.8.3",
"@babel/plugin-proposal-optional-chaining": "^7.8.3",
"@babel/cli": "^7.12.10",
"@babel/compat-data": "^7.12.7",
"@babel/core": "^7.12.10",
"@babel/node": "^7.12.10",
"@babel/plugin-proposal-class-properties": "^7.12.1",
"@babel/plugin-proposal-optional-chaining": "^7.12.7",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-runtime": "^7.8.3",
"@babel/preset-env": "^7.8.7",
"@babel/preset-react": "^7.8.3",
"@babel/register": "^7.8.6",
"@emotion/babel-preset-css-prop": "^10.0.27",
"@babel/plugin-transform-runtime": "^7.12.10",
"@babel/preset-env": "^7.12.11",
"@babel/preset-react": "^7.12.10",
"@babel/register": "^7.12.10",
"@emotion/babel-preset-css-prop": "^10.2.1",
"@hot-loader/react-dom": "^16.13.0",
"@istanbuljs/nyc-config-typescript": "^1.0.1",
"@storybook/addon-actions": "^6.0.13",
@ -231,10 +231,10 @@
"@typescript-eslint/eslint-plugin": "^4.1.0",
"@typescript-eslint/parser": "^4.1.0",
"babel-eslint": "^10.1.0",
"babel-jest": "^26.1.0",
"babel-loader": "^8.0.6",
"babel-plugin-dynamic-import-node": "^2.3.0",
"babel-plugin-emotion": "^10.0.29",
"babel-jest": "^26.6.3",
"babel-loader": "^8.2.2",
"babel-plugin-dynamic-import-node": "^2.3.3",
"babel-plugin-emotion": "^10.0.33",
"babel-plugin-jsx-remove-data-test-id": "^2.1.3",
"babel-plugin-lodash": "^3.3.4",
"cache-loader": "^1.2.2",
@ -245,20 +245,20 @@
"emotion-ts-plugin": "^0.5.3",
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0",
"eslint": "^7.8.1",
"eslint-config-airbnb": "^18.2.0",
"eslint-config-prettier": "^6.11.0",
"eslint": "^7.17.0",
"eslint-config-airbnb": "^18.2.1",
"eslint-config-prettier": "^7.1.0",
"eslint-import-resolver-typescript": "^2.3.0",
"eslint-import-resolver-webpack": "^0.12.2",
"eslint-plugin-cypress": "^2.11.1",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-jest": "^23.17.1",
"eslint-plugin-jest-dom": "^3.2.4",
"eslint-plugin-jsx-a11y": "^6.3.1",
"eslint-plugin-no-only-tests": "^2.0.1",
"eslint-plugin-prettier": "^3.1.3",
"eslint-plugin-react": "^7.20.6",
"eslint-plugin-react-hooks": "^4.1.2",
"eslint-import-resolver-webpack": "^0.13.0",
"eslint-plugin-cypress": "^2.11.2",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jest": "^24.1.3",
"eslint-plugin-jest-dom": "^3.6.5",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-no-only-tests": "^2.4.0",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.2.0",
"eslint-plugin-testing-library": "^3.10.1",
"exports-loader": "^0.7.0",
"fetch-mock": "^7.7.3",
@ -276,7 +276,7 @@
"node-fetch": "^2.6.1",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"po2json": "^0.4.5",
"prettier": "^2.1.1",
"prettier": "^2.2.1",
"react-test-renderer": "^16.9.0",
"redux-mock-store": "^1.5.4",
"sinon": "^9.0.2",

View File

@ -62,8 +62,8 @@ describe('AsyncSelect', () => {
});
describe('auto select', () => {
it('should not call onChange if autoSelect=false', () => {
return new Promise(done => {
it('should not call onChange if autoSelect=false', () =>
new Promise(done => {
expect.assertions(2);
const onChangeSpy = jest.fn();
@ -74,11 +74,10 @@ describe('AsyncSelect', () => {
expect(onChangeSpy.mock.calls).toHaveLength(0);
done();
});
});
});
}));
it('should auto select the first option if autoSelect=true', () => {
return new Promise(done => {
it('should auto select the first option if autoSelect=true', () =>
new Promise(done => {
expect.assertions(3);
const onChangeSpy = jest.fn();
@ -94,11 +93,10 @@ describe('AsyncSelect', () => {
);
done();
});
});
});
}));
it('should not auto select when value prop is set and autoSelect=true', () => {
return new Promise(done => {
it('should not auto select when value prop is set and autoSelect=true', () =>
new Promise(done => {
expect.assertions(3);
const onChangeSpy = jest.fn();
@ -117,8 +115,7 @@ describe('AsyncSelect', () => {
expect(wrapper.find(Select)).toExist();
done();
});
});
});
}));
it('should call onAsyncError if there is an error fetching options', () => {
expect.assertions(3);

View File

@ -489,7 +489,7 @@ describe('dashboardLayout actions', () => {
});
describe('undoLayoutAction', () => {
it('should dispatch a redux-undo .undo() action ', () => {
it('should dispatch a redux-undo .undo() action', () => {
const { getState, dispatch } = setup({
dashboardLayout: { past: ['non-empty'] },
});
@ -513,7 +513,7 @@ describe('dashboardLayout actions', () => {
});
describe('redoLayoutAction', () => {
it('should dispatch a redux-undo .redo() action ', () => {
it('should dispatch a redux-undo .redo() action', () => {
const { getState, dispatch } = setup();
const thunk = redoLayoutAction();
thunk(dispatch, getState);

View File

@ -26,7 +26,7 @@ describe('FilterConfigurationButton', () => {
const mockedProps = {
createNewOnOpen: false,
};
it('it is valid', () => {
it('is valid', () => {
expect(
React.isValidElement(<FilterConfigurationLink {...mockedProps} />),
).toBe(true);

View File

@ -64,8 +64,8 @@ describe('DatasourceEditor', () => {
expect(wrapper.find(Tabs)).toExist();
});
it('makes an async request', () => {
return new Promise(done => {
it('makes an async request', () =>
new Promise(done => {
wrapper.setState({ activeTabKey: 2 });
const syncButton = wrapper.find('.sync-from-source');
expect(syncButton).toHaveLength(1);
@ -76,8 +76,7 @@ describe('DatasourceEditor', () => {
fetchMock.reset();
done();
}, 0);
});
});
}));
it('to add, remove and modify columns accordingly', () => {
const columns = [

View File

@ -201,8 +201,8 @@ describe('SaveModal', () => {
Object.defineProperty(window, 'location', windowLocation);
});
it('Save & go to dashboard', () => {
return new Promise(done => {
it('Save & go to dashboard', () =>
new Promise(done => {
wrapper.instance().saveOrOverwrite(true);
defaultProps.actions.saveSlice().then(() => {
expect(window.location.assign.callCount).toEqual(1);
@ -211,11 +211,10 @@ describe('SaveModal', () => {
);
done();
});
});
});
}));
it('saveas new slice', () => {
return new Promise(done => {
it('saveas new slice', () =>
new Promise(done => {
wrapper.setState({
action: 'saveas',
newSliceName: 'new slice name',
@ -228,11 +227,10 @@ describe('SaveModal', () => {
);
done();
});
});
});
}));
it('overwrite original slice', () => {
return new Promise(done => {
it('overwrite original slice', () =>
new Promise(done => {
wrapper.setState({ action: 'overwrite' });
wrapper.instance().saveOrOverwrite(false);
defaultProps.actions.saveSlice().then(() => {
@ -242,8 +240,7 @@ describe('SaveModal', () => {
);
done();
});
});
});
}));
});
});

View File

@ -57,9 +57,9 @@ const defaultProps = {
function verify(sourceProp: string) {
const mock = jest.fn();
mock.mockImplementation(async (props: ControlPropsWithExtras) => {
return { [sourceProp]: props.validMetrics || [VALID_METRIC] };
});
mock.mockImplementation(async (props: ControlPropsWithExtras) => ({
[sourceProp]: props.validMetrics || [VALID_METRIC],
}));
return mock;
}

View File

@ -43,8 +43,8 @@ describe('Toast', () => {
expect(alert.childAt(0).childAt(1).text()).toBe(props.toast.text);
});
it('should call onCloseToast upon alert dismissal', () => {
return new Promise(done => {
it('should call onCloseToast upon alert dismissal', () =>
new Promise(done => {
const onCloseToast = id => {
expect(id).toBe(props.toast.id);
done();
@ -57,6 +57,5 @@ describe('Toast', () => {
const alertProps = wrapper.find(Alert).props();
expect(alertProps.onDismiss).toBe(handleClosePress);
handleClosePress(); // there is a timeout for onCloseToast to be called
});
});
}));
});

View File

@ -50,7 +50,7 @@ describe('SaveDatasetModal', () => {
const wrapper = shallow(<SaveDatasetModal {...mockedProps} />);
expect(wrapper.find(AutoComplete)).toExist();
});
it('renders an input form ', () => {
it('renders an input form', () => {
// @ts-ignore
const wrapper = shallow(<SaveDatasetModal {...mockedProps} />);
expect(wrapper.find(Input)).toExist();

View File

@ -86,7 +86,7 @@ describe('sqlLabReducer', () => {
newState = sqlLabReducer(newState, action);
expect(newState.queryEditors[1].schema).toBe(schema);
});
it('should not fail while setting autorun ', () => {
it('should not fail while setting autorun', () => {
const action = {
type: actions.QUERY_EDITOR_SET_AUTORUN,
queryEditor: qe,

View File

@ -21,9 +21,7 @@ import parseCookie from 'src/utils/parseCookie';
describe('parseCookie', () => {
let cookieVal = '';
Object.defineProperty(document, 'cookie', {
get: jest.fn().mockImplementation(() => {
return cookieVal;
}),
get: jest.fn().mockImplementation(() => cookieVal),
});
it('parses cookie strings', () => {
cookieVal = 'val1=foo; val2=bar';

View File

@ -70,13 +70,13 @@ describe('ActivityTable', () => {
await waitForComponentToPaint(wrapper);
});
it('the component renders ', () => {
it('the component renders', () => {
expect(wrapper.find(ActivityTable)).toExist();
});
it('renders tabs with three buttons', () => {
expect(wrapper.find('li')).toHaveLength(3);
});
it('it renders ActivityCards', async () => {
it('renders ActivityCards', async () => {
expect(wrapper.find('ListViewCard')).toExist();
});
});

View File

@ -58,11 +58,11 @@ describe('ChartTable', () => {
},
};
const wrapper = mount(<ChartTable store={store} {...mockedProps} />);
it('it renders', () => {
it('renders', () => {
expect(wrapper.find(ChartTable)).toExist();
});
it('fetches chart favorites and renders chart cards ', async () => {
it('fetches chart favorites and renders chart cards', async () => {
act(() => {
const handler = wrapper.find('li.no-router a').at(0).prop('onClick');
if (handler) {

View File

@ -103,7 +103,7 @@ describe('SavedQueries', () => {
expect(wrapper.find('ListViewCard')).toExist();
});
it('it renders a submenu with clickable tables and buttons', async () => {
it('renders a submenu with clickable tables and buttons', async () => {
expect(wrapper.find(SubMenu)).toExist();
expect(wrapper.find('li')).toHaveLength(1);
expect(wrapper.find('button')).toHaveLength(2);

View File

@ -184,9 +184,8 @@ export default class ResultSet extends React.PureComponent<
}
}
getDefaultDatasetName = () => {
return `${this.props.query.tab} ${moment().format('MM/DD/YYYY HH:mm:ss')}`;
};
getDefaultDatasetName = () =>
`${this.props.query.tab} ${moment().format('MM/DD/YYYY HH:mm:ss')}`;
handleOnChangeAutoComplete = () => {
this.setState({ datasetToOverwrite: {} });
@ -341,9 +340,7 @@ export default class ResultSet extends React.PureComponent<
handleFilterAutocompleteOption = (
inputValue: string,
option: { value: string; datasetId: number },
) => {
return option.value.toLowerCase().includes(inputValue.toLowerCase());
};
) => option.value.toLowerCase().includes(inputValue.toLowerCase());
clearQueryResults(query: Query) {
this.props.actions.clearQueryResults(query);

View File

@ -91,84 +91,82 @@ export const SaveDatasetModal: FunctionComponent<SaveDatasetModalProps> = ({
filterAutocompleteOption,
userDatasetOptions,
onChangeAutoComplete,
}) => {
return (
<StyledModal
show={visible}
title="Save or Overwrite Dataset"
onHide={onHide}
footer={
<>
{!shouldOverwriteDataset && (
<Button
disabled={disableSaveAndExploreBtn}
buttonSize="medium"
buttonStyle="primary"
onClick={onOk}
>
{t('Save & Explore')}
</Button>
)}
{shouldOverwriteDataset && (
<>
<Button buttonSize="medium" onClick={handleOverwriteCancel}>
Back
</Button>
<Button
className="md"
buttonSize="medium"
buttonStyle="primary"
onClick={handleOverwriteDataset}
disabled={disableSaveAndExploreBtn}
>
{t('Overwrite & Explore')}
</Button>
</>
)}
</>
}
>
<Styles>
}) => (
<StyledModal
show={visible}
title="Save or Overwrite Dataset"
onHide={onHide}
footer={
<>
{!shouldOverwriteDataset && (
<div className="smd-body">
<div className="smd-prompt">
Save this query as virtual dataset to continue exploring.
</div>
<Radio.Group
onChange={handleSaveDatasetRadioBtnState}
value={saveDatasetRadioBtnState}
>
<Radio className="smd-radio" value={1}>
Save as new
<Input
className="smd-input"
defaultValue={defaultCreateDatasetValue}
onChange={handleDatasetNameChange}
disabled={saveDatasetRadioBtnState !== 1}
/>
</Radio>
<Radio className="smd-radio" value={2}>
Overwrite existing
<AutoComplete
className="smd-autocomplete"
options={userDatasetOptions}
onSelect={handleOverwriteDatasetOption}
onSearch={handleSaveDatasetModalSearch}
onChange={onChangeAutoComplete}
placeholder="Select or type dataset name"
filterOption={filterAutocompleteOption}
disabled={saveDatasetRadioBtnState !== 2}
/>
</Radio>
</Radio.Group>
</div>
<Button
disabled={disableSaveAndExploreBtn}
buttonSize="medium"
buttonStyle="primary"
onClick={onOk}
>
{t('Save & Explore')}
</Button>
)}
{shouldOverwriteDataset && (
<div className="smd-overwrite-msg">
Are you sure you want to overwrite this dataset?
</div>
<>
<Button buttonSize="medium" onClick={handleOverwriteCancel}>
Back
</Button>
<Button
className="md"
buttonSize="medium"
buttonStyle="primary"
onClick={handleOverwriteDataset}
disabled={disableSaveAndExploreBtn}
>
{t('Overwrite & Explore')}
</Button>
</>
)}
</Styles>
</StyledModal>
);
};
</>
}
>
<Styles>
{!shouldOverwriteDataset && (
<div className="smd-body">
<div className="smd-prompt">
Save this query as virtual dataset to continue exploring.
</div>
<Radio.Group
onChange={handleSaveDatasetRadioBtnState}
value={saveDatasetRadioBtnState}
>
<Radio className="smd-radio" value={1}>
Save as new
<Input
className="smd-input"
defaultValue={defaultCreateDatasetValue}
onChange={handleDatasetNameChange}
disabled={saveDatasetRadioBtnState !== 1}
/>
</Radio>
<Radio className="smd-radio" value={2}>
Overwrite existing
<AutoComplete
className="smd-autocomplete"
options={userDatasetOptions}
onSelect={handleOverwriteDatasetOption}
onSearch={handleSaveDatasetModalSearch}
onChange={onChangeAutoComplete}
placeholder="Select or type dataset name"
filterOption={filterAutocompleteOption}
disabled={saveDatasetRadioBtnState !== 2}
/>
</Radio>
</Radio.Group>
</div>
)}
{shouldOverwriteDataset && (
<div className="smd-overwrite-msg">
Are you sure you want to overwrite this dataset?
</div>
)}
</Styles>
</StyledModal>
);

View File

@ -79,13 +79,11 @@ export default function SaveQuery({
const [showSave, setShowSave] = useState<boolean>(false);
const isSaved = !!query.remoteId;
const queryPayload = () => {
return {
...query,
title: label,
description,
};
};
const queryPayload = () => ({
...query,
title: label,
description,
});
const close = () => {
setShowSave(false);
@ -113,47 +111,45 @@ export default function SaveQuery({
setShowSave(!showSave);
};
const renderModalBody = () => {
return (
<FormGroup bsSize="small">
<Row>
<Col md={12}>
<small>
<FormLabel htmlFor="embed-height">{t('Name')}</FormLabel>
</small>
<FormControl type="text" value={label} onChange={onLabelChange} />
</Col>
</Row>
<br />
<Row>
<Col md={12}>
<small>
<FormLabel htmlFor="embed-height">{t('Description')}</FormLabel>
</small>
<FormControl
rows={5}
componentClass="textarea"
value={description}
onChange={onDescriptionChange}
/>
</Col>
</Row>
{saveQueryWarning && (
<>
const renderModalBody = () => (
<FormGroup bsSize="small">
<Row>
<Col md={12}>
<small>
<FormLabel htmlFor="embed-height">{t('Name')}</FormLabel>
</small>
<FormControl type="text" value={label} onChange={onLabelChange} />
</Col>
</Row>
<br />
<Row>
<Col md={12}>
<small>
<FormLabel htmlFor="embed-height">{t('Description')}</FormLabel>
</small>
<FormControl
rows={5}
componentClass="textarea"
value={description}
onChange={onDescriptionChange}
/>
</Col>
</Row>
{saveQueryWarning && (
<>
<br />
<div>
<Row>
<Col md={12}>
<small>{saveQueryWarning}</small>
</Col>
</Row>
<br />
<div>
<Row>
<Col md={12}>
<small>{saveQueryWarning}</small>
</Col>
</Row>
<br />
</div>
</>
)}
</FormGroup>
);
};
</div>
</>
)}
</FormGroup>
);
return (
<Styles className="SaveQuery">

View File

@ -148,13 +148,13 @@ const legacyChartDataRequest = async (
'GET' && isFeatureEnabled(FeatureFlag.CLIENT_CACHE)
? SupersetClient.get
: SupersetClient.post;
return clientMethod(querySettings).then(({ json }) => {
return clientMethod(querySettings).then(({ json }) =>
// Make the legacy endpoint return a payload that corresponds to the
// V1 chart data endpoint response signature.
return {
({
result: [json],
};
});
}),
);
};
const v1ChartDataRequest = async (
@ -195,9 +195,7 @@ const v1ChartDataRequest = async (
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
};
return SupersetClient.post(querySettings).then(({ json }) => {
return json;
});
return SupersetClient.post(querySettings).then(({ json }) => json);
};
export async function getChartDataRequest({

View File

@ -70,6 +70,4 @@ export type ErrorMessageComponentProps<
source?: ErrorSource;
};
export type ErrorMessageComponent = React.ComponentType<
ErrorMessageComponentProps
>;
export type ErrorMessageComponent = React.ComponentType<ErrorMessageComponentProps>;

View File

@ -55,6 +55,6 @@ const users = [...new Array(10)].map((_, i) => ({
id: i,
}));
export const SupersetFacePile = () => {
return <FacePile users={users} maxCount={number('maxCount', 4)} />;
};
export const SupersetFacePile = () => (
<FacePile users={users} maxCount={number('maxCount', 4)} />
);

View File

@ -61,26 +61,24 @@ const IconBlock = styled.div`
}
`;
export const SupersetIcon = () => {
return (
<IconSet>
{Object.keys(iconsRegistry)
.sort()
.map(iconName => (
<IconBlock key={iconName}>
<Icon
name={iconName}
key={iconName}
color={select(
colorKnob.label,
colorKnob.options,
colorKnob.defaultValue,
colorKnob.groupId,
)}
/>
<div>{iconName}</div>
</IconBlock>
))}
</IconSet>
);
};
export const SupersetIcon = () => (
<IconSet>
{Object.keys(iconsRegistry)
.sort()
.map(iconName => (
<IconBlock key={iconName}>
<Icon
name={iconName}
key={iconName}
color={select(
colorKnob.label,
colorKnob.options,
colorKnob.defaultValue,
colorKnob.groupId,
)}
/>
<div>{iconName}</div>
</IconBlock>
))}
</IconSet>
);

View File

@ -68,9 +68,9 @@ export default function CardCollection({
<CardContainer>
{loading &&
rows.length === 0 &&
[...new Array(25)].map((e, i) => {
return <div key={i}>{renderCard({ loading })}</div>;
})}
[...new Array(25)].map((e, i) => (
<div key={i}>{renderCard({ loading })}</div>
))}
{rows.length > 0 &&
rows.map(row => {
if (!renderCard) return null;

View File

@ -174,34 +174,32 @@ const ViewModeToggle = ({
}: {
mode: 'table' | 'card';
setMode: (mode: 'table' | 'card') => void;
}) => {
return (
<ViewModeContainer>
<div
role="button"
tabIndex={0}
onClick={e => {
e.currentTarget.blur();
setMode('card');
}}
className={cx('toggle-button', { active: mode === 'card' })}
>
<Icon name="card-view" />
</div>
<div
role="button"
tabIndex={0}
onClick={e => {
e.currentTarget.blur();
setMode('table');
}}
className={cx('toggle-button', { active: mode === 'table' })}
>
<Icon name="list-view" />
</div>
</ViewModeContainer>
);
};
}) => (
<ViewModeContainer>
<div
role="button"
tabIndex={0}
onClick={e => {
e.currentTarget.blur();
setMode('card');
}}
className={cx('toggle-button', { active: mode === 'card' })}
>
<Icon name="card-view" />
</div>
<div
role="button"
tabIndex={0}
onClick={e => {
e.currentTarget.blur();
setMode('table');
}}
className={cx('toggle-button', { active: mode === 'table' })}
>
<Icon name="list-view" />
</div>
</ViewModeContainer>
);
export interface ListViewProps<T extends object = any> {
columns: any[];

View File

@ -41,49 +41,43 @@ const imgFallbackKnob = {
defaultValue: DashboardImg,
};
export const SupersetListViewCard = () => {
return (
<ListViewCard
title="Superset Card Title"
loading={boolean('loading', false)}
url="/superset/dashboard/births/"
imgURL={text('imgURL', 'https://picsum.photos/800/600')}
imgFallbackURL={select(
imgFallbackKnob.label,
imgFallbackKnob.options,
imgFallbackKnob.defaultValue,
)}
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit..."
coverLeft="Left Section"
coverRight="Right Section"
actions={
<ListViewCard.Actions>
<FaveStar
itemId={0}
fetchFaveStar={action('fetchFaveStar')}
saveFaveStar={action('saveFaveStar')}
isStarred={boolean('isStarred', false)}
/>
<Dropdown
overlay={
<Menu>
<Menu.Item
role="button"
tabIndex={0}
onClick={action('Delete')}
>
<ListViewCard.MenuIcon name="trash" /> Delete
</Menu.Item>
<Menu.Item role="button" tabIndex={0} onClick={action('Edit')}>
<ListViewCard.MenuIcon name="edit-alt" /> Edit
</Menu.Item>
</Menu>
}
>
<Icon name="more-horiz" />
</Dropdown>
</ListViewCard.Actions>
}
/>
);
};
export const SupersetListViewCard = () => (
<ListViewCard
title="Superset Card Title"
loading={boolean('loading', false)}
url="/superset/dashboard/births/"
imgURL={text('imgURL', 'https://picsum.photos/800/600')}
imgFallbackURL={select(
imgFallbackKnob.label,
imgFallbackKnob.options,
imgFallbackKnob.defaultValue,
)}
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit..."
coverLeft="Left Section"
coverRight="Right Section"
actions={
<ListViewCard.Actions>
<FaveStar
itemId={0}
fetchFaveStar={action('fetchFaveStar')}
saveFaveStar={action('saveFaveStar')}
isStarred={boolean('isStarred', false)}
/>
<Dropdown
overlay={
<Menu>
<Menu.Item role="button" tabIndex={0} onClick={action('Delete')}>
<ListViewCard.MenuIcon name="trash" /> Delete
</Menu.Item>
<Menu.Item role="button" tabIndex={0} onClick={action('Edit')}>
<ListViewCard.MenuIcon name="edit-alt" /> Edit
</Menu.Item>
</Menu>
}
>
<Icon name="more-horiz" />
</Dropdown>
</ListViewCard.Actions>
}
/>
);

View File

@ -49,45 +49,43 @@ export default {
},
};
export const SelectGallery = ({ value }: { value: OptionTypeBase }) => {
return (
<>
<h4>With default value</h4>
<Select
value={OPTIONS[0]}
ignoreAccents={false}
name="select-datasource"
onChange={() => {}}
options={OPTIONS}
placeholder="choose one"
width={600}
/>
<hr />
<h4>With no value</h4>
<Select
ignoreAccents={false}
name="select-datasource"
onChange={() => {}}
options={OPTIONS}
placeholder="choose one"
width={600}
value={value}
/>
<hr />
<h4>Multi select</h4>
<Select
ignoreAccents={false}
name="select-datasource"
onChange={() => {}}
options={OPTIONS}
placeholder="choose one or more values"
width={600}
value={[OPTIONS[0]]}
multi
/>
</>
);
};
export const SelectGallery = ({ value }: { value: OptionTypeBase }) => (
<>
<h4>With default value</h4>
<Select
value={OPTIONS[0]}
ignoreAccents={false}
name="select-datasource"
onChange={() => {}}
options={OPTIONS}
placeholder="choose one"
width={600}
/>
<hr />
<h4>With no value</h4>
<Select
ignoreAccents={false}
name="select-datasource"
onChange={() => {}}
options={OPTIONS}
placeholder="choose one"
width={600}
value={value}
/>
<hr />
<h4>Multi select</h4>
<Select
ignoreAccents={false}
name="select-datasource"
onChange={() => {}}
options={OPTIONS}
placeholder="choose one or more values"
width={600}
value={[OPTIONS[0]]}
multi
/>
</>
);
SelectGallery.args = {
value: '',

View File

@ -99,9 +99,9 @@ function styled<
OptionType extends OptionTypeBase,
SelectComponentType extends
| WindowedSelectComponentType<OptionType>
| ComponentType<SelectProps<OptionType>> = WindowedSelectComponentType<
OptionType
>
| ComponentType<
SelectProps<OptionType>
> = WindowedSelectComponentType<OptionType>
>(SelectComponent: SelectComponentType) {
type SelectProps = SupersetStyledSelectProps<OptionType>;
type Components = SelectComponents<OptionType>;
@ -113,8 +113,8 @@ function styled<
// default components for the given OptionType
const supersetDefaultComponents: SelectComponentsConfig<OptionType> = DEFAULT_COMPONENTS;
const getSortableMultiValue = (MultiValue: Components['MultiValue']) => {
return SortableElement((props: MultiValueProps<OptionType>) => {
const getSortableMultiValue = (MultiValue: Components['MultiValue']) =>
SortableElement((props: MultiValueProps<OptionType>) => {
const onMouseDown = (e: SyntheticEvent) => {
e.preventDefault();
e.stopPropagation();
@ -122,7 +122,6 @@ function styled<
const innerProps = { onMouseDown };
return <MultiValue {...props} innerProps={innerProps} />;
});
};
/**
* Superset styled `Select` component. Apply Superset themed stylesheets and

View File

@ -125,9 +125,7 @@ export default function WindowedMenuList<OptionType extends OptionTypeBase>({
data,
index,
style,
}) => {
return <div style={style}>{data[index]}</div>;
};
}) => <div style={style}>{data[index]}</div>;
useEffect(() => {
const lastSelected = getLastSelected(children);

View File

@ -91,21 +91,19 @@ export type PartialThemeConfig = RecursivePartial<ThemeConfig>;
export const defaultTheme: (
theme: SupersetTheme,
) => PartialThemeConfig = theme => {
return {
borderRadius: theme.borderRadius,
zIndex: 11,
colors: colors(theme),
spacing: {
baseUnit: 3,
menuGutter: 0,
controlHeight: 28,
lineHeight: 19,
fontSize: 14,
minWidth: '7.5em', // just enough to display 'No options'
},
};
};
) => PartialThemeConfig = theme => ({
borderRadius: theme.borderRadius,
zIndex: 11,
colors: colors(theme),
spacing: {
baseUnit: 3,
menuGutter: 0,
controlHeight: 28,
lineHeight: 19,
fontSize: 14,
minWidth: '7.5em', // just enough to display 'No options'
},
});
// let styles accept serialized CSS, too
type CSSStyles = CSSProperties | SerializedStyles;

View File

@ -90,11 +90,10 @@ export default function SupersetResourceSelect<T, V>({
return cachedSupersetGet({
endpoint: `/api/v1/${resource}/?q=${query}`,
}).then(
response => {
return response.json.result
response =>
response.json.result
.map(transformItem)
.sort((a: Value<V>, b: Value<V>) => a.label.localeCompare(b.label));
},
.sort((a: Value<V>, b: Value<V>) => a.label.localeCompare(b.label)),
async badResponse => {
onError(await getClientErrorObject(badResponse));
return [];

View File

@ -43,56 +43,52 @@ const BuilderComponentPaneTabs = styled(Tabs)`
margin-top: ${({ theme }) => theme.gridUnit * 2}px;
`;
const BuilderComponentPane: React.FC<BCPProps> = ({ topOffset = 0 }) => {
return (
<div
className="dashboard-builder-sidepane"
style={{
height: `calc(100vh - ${topOffset + SUPERSET_HEADER_HEIGHT}px)`,
}}
>
<ParentSize>
{({ height }) => (
<StickyContainer>
<Sticky topOffset={-topOffset} bottomOffset={Infinity}>
{({ style, isSticky }: { style: any; isSticky: boolean }) => (
<div
className="viewport"
style={isSticky ? { ...style, top: topOffset } : null}
const BuilderComponentPane: React.FC<BCPProps> = ({ topOffset = 0 }) => (
<div
className="dashboard-builder-sidepane"
style={{
height: `calc(100vh - ${topOffset + SUPERSET_HEADER_HEIGHT}px)`,
}}
>
<ParentSize>
{({ height }) => (
<StickyContainer>
<Sticky topOffset={-topOffset} bottomOffset={Infinity}>
{({ style, isSticky }: { style: any; isSticky: boolean }) => (
<div
className="viewport"
style={isSticky ? { ...style, top: topOffset } : null}
>
<BuilderComponentPaneTabs
id="tabs"
className="tabs-components"
data-test="dashboard-builder-component-pane-tabs-navigation"
>
<BuilderComponentPaneTabs
id="tabs"
className="tabs-components"
data-test="dashboard-builder-component-pane-tabs-navigation"
<Tabs.TabPane key={1} tab={t('Components')}>
<NewTabs />
<NewRow />
<NewColumn />
<NewHeader />
<NewMarkdown />
<NewDivider />
</Tabs.TabPane>
<Tabs.TabPane
key={2}
tab={t('Charts')}
className="tab-charts"
>
<Tabs.TabPane key={1} tab={t('Components')}>
<NewTabs />
<NewRow />
<NewColumn />
<NewHeader />
<NewMarkdown />
<NewDivider />
</Tabs.TabPane>
<Tabs.TabPane
key={2}
tab={t('Charts')}
className="tab-charts"
>
<SliceAdder
height={
height + (isSticky ? SUPERSET_HEADER_HEIGHT : 0)
}
/>
</Tabs.TabPane>
</BuilderComponentPaneTabs>
</div>
)}
</Sticky>
</StickyContainer>
)}
</ParentSize>
</div>
);
};
<SliceAdder
height={height + (isSticky ? SUPERSET_HEADER_HEIGHT : 0)}
/>
</Tabs.TabPane>
</BuilderComponentPaneTabs>
</div>
)}
</Sticky>
</StickyContainer>
)}
</ParentSize>
</div>
);
export default BuilderComponentPane;

View File

@ -96,9 +96,10 @@ const StyledDashboardContent = styled.div`
margin: ${({ theme }) => theme.gridUnit * 2}px
${({ theme }) => theme.gridUnit * 8}px
${({ theme }) => theme.gridUnit * 6}px
${({ theme, dashboardFiltersOpen }) =>
// eslint-disable-next-line prettier/prettier
(dashboardFiltersOpen ? theme.gridUnit * 4 : 0)}px;
${({ theme, dashboardFiltersOpen }) => {
if (dashboardFiltersOpen) return theme.gridUnit * 4;
return 0;
}}px;
}
.dashboard-component-chart-holder {

View File

@ -45,20 +45,18 @@ export interface IndicatorProps {
const Indicator = ({
indicator: { column, name, value = [], path },
onClick,
}: IndicatorProps) => {
return (
<Item onClick={() => onClick([...path, `LABEL-${column}`])}>
<Title bold>
<ItemIcon>
<SearchOutlined />
</ItemIcon>
{name.toUpperCase()}
{value.length ? ': ' : ''}
</Title>
<FilterValue>{value.length ? value.join(', ') : ''}</FilterValue>
</Item>
);
};
}: IndicatorProps) => (
<Item onClick={() => onClick([...path, `LABEL-${column}`])}>
<Title bold>
<ItemIcon>
<SearchOutlined />
</ItemIcon>
{name.toUpperCase()}
{value.length ? ': ' : ''}
</Title>
<FilterValue>{value.length ? value.join(', ') : ''}</FilterValue>
</Item>
);
export interface DetailsPanelProps {
appliedIndicators: Indicator[];

View File

@ -91,7 +91,8 @@ export const Title = styled.span<TitleProps>`
position: relative;
margin-right: ${({ theme }) => theme.gridUnit}px;
font-weight: ${({ bold, theme }) => {
return bold ? theme.typography.weights.bold : 'auto';
if (bold) return theme.typography.weights.bold;
return 'auto';
}};
color: ${({ color, theme }) => color || theme.colors.grayscale.light5};
`;

View File

@ -90,12 +90,11 @@ const loadOwnerOptions = (input = '') => {
return SupersetClient.get({
endpoint: `/api/v1/dashboard/related/owners?q=${query}`,
}).then(
response => {
return response.json.result.map(item => ({
response =>
response.json.result.map(item => ({
value: item.value,
label: item.text,
}));
},
})),
badResponse => {
handleErrorResponse(badResponse);
return [];

View File

@ -181,9 +181,13 @@ class SliceHeaderControls extends React.PureComponent {
);
const updatedWhen = updatedDttm ? moment.utc(updatedDttm).fromNow() : '';
const getCachedTitle = itemCached => {
return itemCached
? t('Cached %s', cachedWhen)
: updatedWhen && t('Fetched %s', updatedWhen);
if (itemCached) {
return t('Cached %s', cachedWhen);
}
if (updatedWhen) {
return t('Fetched %s', updatedWhen);
}
return '';
};
const refreshTooltipData = isCached.map(getCachedTitle) || '';
// If all queries have same cache time we can unit them to one

View File

@ -32,8 +32,7 @@ const Wrapper = styled.div`
/* keeping these for posterity, in case we can improve that resizing performance */
/* &.animated {
transition: width 0;
transition-delay: ${({ theme }) =>
theme.transitionTiming * 2}s;
transition-delay: ${({ theme }) => theme.transitionTiming * 2}s;
} */
&.open {
width: 250px;
@ -68,38 +67,36 @@ export const StickyVerticalBar: React.FC<SVBProps> = ({
topOffset,
children,
filtersOpen,
}) => {
return (
<Wrapper className={cx({ open: filtersOpen })}>
<StickyContainer>
<Sticky topOffset={-topOffset} bottomOffset={Infinity}>
{({
style,
isSticky,
distanceFromTop,
}: {
style: any;
isSticky: boolean;
distanceFromTop: number;
}) => (
<Contents
style={
isSticky
? {
...style,
top: topOffset,
height: `calc(100vh - ${topOffset}px)`,
}
: {
height: `calc(100vh - ${distanceFromTop}px)`,
}
}
>
{children}
</Contents>
)}
</Sticky>
</StickyContainer>
</Wrapper>
);
};
}) => (
<Wrapper className={cx({ open: filtersOpen })}>
<StickyContainer>
<Sticky topOffset={-topOffset} bottomOffset={Infinity}>
{({
style,
isSticky,
distanceFromTop,
}: {
style: any;
isSticky: boolean;
distanceFromTop: number;
}) => (
<Contents
style={
isSticky
? {
...style,
top: topOffset,
height: `calc(100vh - ${topOffset}px)`,
}
: {
height: `calc(100vh - ${distanceFromTop}px)`,
}
}
>
{children}
</Contents>
)}
</Sticky>
</StickyContainer>
</Wrapper>
);

View File

@ -204,28 +204,26 @@ export default class Tab extends React.PureComponent {
onDrop={this.handleDrop}
editMode={editMode}
>
{({ dropIndicatorProps, dragSourceRef }) => {
return (
<div className="dragdroppable-tab" ref={dragSourceRef}>
<EditableTitle
title={component.meta.text}
canEdit={editMode && isFocused}
onSaveTitle={this.handleChangeText}
showTooltip={false}
{({ dropIndicatorProps, dragSourceRef }) => (
<div className="dragdroppable-tab" ref={dragSourceRef}>
<EditableTitle
title={component.meta.text}
canEdit={editMode && isFocused}
onSaveTitle={this.handleChangeText}
showTooltip={false}
/>
{!editMode && (
<AnchorLink
anchorLinkId={component.id}
filters={filters}
showShortLinkButton
placement={index >= 5 ? 'left' : 'right'}
/>
{!editMode && (
<AnchorLink
anchorLinkId={component.id}
filters={filters}
showShortLinkButton
placement={index >= 5 ? 'left' : 'right'}
/>
)}
)}
{dropIndicatorProps && <div {...dropIndicatorProps} />}
</div>
);
}}
{dropIndicatorProps && <div {...dropIndicatorProps} />}
</div>
)}
</DragDroppable>
);
}

View File

@ -73,11 +73,10 @@ export function ColumnSelect({
return cachedSupersetGet({
endpoint: `/api/v1/dataset/${datasetId}`,
}).then(
({ json: { result } }) => {
return result.columns
({ json: { result } }) =>
result.columns
.map((col: any) => col.column_name)
.sort((a: string, b: string) => a.localeCompare(b));
},
.sort((a: string, b: string) => a.localeCompare(b)),
async badResponse => {
const { error, message } = await getClientErrorObject(badResponse);
let errorText = message || error || t('An error has occurred');

View File

@ -67,18 +67,14 @@ const Bar = styled.div`
/* &.animated {
display: flex;
transform: translateX(-100%);
transition: transform ${({
theme,
}) => theme.transitionTiming}s;
transition: transform ${({ theme }) => theme.transitionTiming}s;
transition-delay: 0s;
} */
&.open {
display: flex;
/* &.animated {
transform: translateX(0);
transition-delay: ${({
theme,
}) => theme.transitionTiming * 2}s;
transition-delay: ${({ theme }) => theme.transitionTiming * 2}s;
} */
}
`;
@ -95,9 +91,7 @@ const CollapsedBar = styled.div`
/* &.animated {
display: block;
transform: translateX(-100%);
transition: transform ${({
theme,
}) => theme.transitionTiming}s;
transition: transform ${({ theme }) => theme.transitionTiming}s;
transition-delay: 0s;
} */
&.open {
@ -107,9 +101,7 @@ const CollapsedBar = styled.div`
padding: ${({ theme }) => theme.gridUnit * 2}px;
/* &.animated {
transform: translateX(0);
transition-delay: ${({
theme,
}) => theme.transitionTiming * 3}s;
transition-delay: ${({ theme }) => theme.transitionTiming * 3}s;
} */
}
svg {
@ -321,30 +313,28 @@ interface CascadeFilterControlProps {
export const CascadeFilterControl: React.FC<CascadeFilterControlProps> = ({
filter,
onExtraFormDataChange,
}) => {
return (
<>
<StyledFilterControlBox>
<StyledCaretIcon name="caret-down" />
<FilterControl
filter={filter}
onExtraFormDataChange={onExtraFormDataChange}
/>
</StyledFilterControlBox>
}) => (
<>
<StyledFilterControlBox>
<StyledCaretIcon name="caret-down" />
<FilterControl
filter={filter}
onExtraFormDataChange={onExtraFormDataChange}
/>
</StyledFilterControlBox>
<StyledCascadeChildrenList>
{filter.cascadeChildren?.map(childFilter => (
<li key={childFilter.id}>
<CascadeFilterControl
filter={childFilter}
onExtraFormDataChange={onExtraFormDataChange}
/>
</li>
))}
</StyledCascadeChildrenList>
</>
);
};
<StyledCascadeChildrenList>
{filter.cascadeChildren?.map(childFilter => (
<li key={childFilter.id}>
<CascadeFilterControl
filter={childFilter}
onExtraFormDataChange={onExtraFormDataChange}
/>
</li>
))}
</StyledCascadeChildrenList>
</>
);
const FilterBar: React.FC<FiltersBarProps> = ({
filtersOpen,

View File

@ -60,9 +60,9 @@ export function useFilterConfigMap() {
}
export function useFilterState(id: string) {
return useSelector<any, FilterState>(state => {
return state.nativeFilters.filtersState[id] || getInitialFilterState(id);
});
return useSelector<any, FilterState>(
state => state.nativeFilters.filtersState[id] || getInitialFilterState(id),
);
}
export function useSetExtraFormData() {

View File

@ -343,7 +343,9 @@ class DatasourceEditor extends React.PureComponent {
onDatasourcePropChange(attr, value) {
const datasource = { ...this.state.datasource, [attr]: value };
this.setState(
prevState => ({ datasource: { ...prevState.datasource, [attr]: value } }),
prevState => ({
datasource: { ...prevState.datasource, [attr]: value },
}),
this.onDatasourceChange(datasource),
);
}

View File

@ -42,9 +42,8 @@ const OPERATORS_TO_SQL = {
REGEX: 'REGEX',
'IS NOT NULL': 'IS NOT NULL',
'IS NULL': 'IS NULL',
'LATEST PARTITION': ({ datasource }) => {
return `= '{{ presto.latest_partition('${datasource.schema}.${datasource.datasource_name}') }}'`;
},
'LATEST PARTITION': ({ datasource }) =>
`= '{{ presto.latest_partition('${datasource.schema}.${datasource.datasource_name}') }}'`,
};
function translateToSql(adhocMetric, { useSimple } = {}) {

View File

@ -96,7 +96,10 @@ export const DataTablesPane = ({
const getData = useCallback(
(resultType: string) => {
setIsLoading(prevIsLoading => ({ ...prevIsLoading, [resultType]: true }));
setIsLoading(prevIsLoading => ({
...prevIsLoading,
[resultType]: true,
}));
return getChartDataRequest({
formData: queryFormData,
resultFormat: 'json',

View File

@ -218,11 +218,9 @@ const ExploreChartPanel = props => {
/>
);
const elementStyle = (dimension, elementSize, gutterSize) => {
return {
[dimension]: `calc(${elementSize}% - ${gutterSize + gutterMargin}px)`,
};
};
const elementStyle = (dimension, elementSize, gutterSize) => ({
[dimension]: `calc(${elementSize}% - ${gutterSize + gutterMargin}px)`,
});
const panelBody = <div className="panel-body">{renderChart()}</div>;

View File

@ -198,12 +198,16 @@ export const customTimeRangeEncode = (customRange: CustomRangeType): string => {
// relative : specific
if (sinceMode === 'relative' && SPECIFIC_MODE.includes(untilMode)) {
const until = untilMode === 'specific' ? untilDatetime : untilMode;
const since = `DATEADD(DATETIME("${until}"), ${-Math.abs(sinceGrainValue)}, ${sinceGrain})`; // eslint-disable-line
const since = `DATEADD(DATETIME("${until}"), ${-Math.abs(
sinceGrainValue,
)}, ${sinceGrain})`; // eslint-disable-line
return `${since} : ${until}`;
}
// relative : relative
const since = `DATEADD(DATETIME("${anchorValue}"), ${-Math.abs(sinceGrainValue)}, ${sinceGrain})`; // eslint-disable-line
const since = `DATEADD(DATETIME("${anchorValue}"), ${-Math.abs(
sinceGrainValue,
)}, ${sinceGrain})`; // eslint-disable-line
const until = `DATEADD(DATETIME("${anchorValue}"), ${untilGrainValue}, ${untilGrain})`;
return `${since} : ${until}`;
};

View File

@ -222,9 +222,8 @@ export const buildV1ChartDataPayload = ({
});
};
export const getLegacyEndpointType = ({ resultType, resultFormat }) => {
return resultFormat === 'csv' ? resultFormat : resultType;
};
export const getLegacyEndpointType = ({ resultType, resultFormat }) =>
resultFormat === 'csv' ? resultFormat : resultType;
export function postForm(url, payload, target = '_blank') {
if (!url) {

View File

@ -39,36 +39,34 @@ import {
export default function buildQuery(formData: QueryFormData) {
const { groupby } = formData;
const [column] = groupby || [];
return buildQueryContext(formData, baseQueryObject => {
return [
{
...baseQueryObject,
groupby: [],
metrics: [
{
aggregate: 'MIN',
column: {
columnName: column,
id: 1,
type: ColumnType.FLOAT,
},
expressionType: 'SIMPLE',
hasCustomLabel: true,
label: 'min',
return buildQueryContext(formData, baseQueryObject => [
{
...baseQueryObject,
groupby: [],
metrics: [
{
aggregate: 'MIN',
column: {
columnName: column,
id: 1,
type: ColumnType.FLOAT,
},
{
aggregate: 'MAX',
column: {
columnName: column,
id: 2,
type: ColumnType.FLOAT,
},
expressionType: 'SIMPLE',
hasCustomLabel: true,
label: 'max',
expressionType: 'SIMPLE',
hasCustomLabel: true,
label: 'min',
},
{
aggregate: 'MAX',
column: {
columnName: column,
id: 2,
type: ColumnType.FLOAT,
},
],
},
];
});
expressionType: 'SIMPLE',
hasCustomLabel: true,
label: 'max',
},
],
},
]);
}

View File

@ -33,11 +33,9 @@ import { buildQueryContext, QueryFormData } from '@superset-ui/core';
* if a viz needs multiple different result sets.
*/
export default function buildQuery(formData: QueryFormData) {
return buildQueryContext(formData, baseQueryObject => {
return [
{
...baseQueryObject,
},
];
});
return buildQueryContext(formData, baseQueryObject => [
{
...baseQueryObject,
},
]);
}

View File

@ -21,14 +21,12 @@ 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]),
) => {
return (...args: T): U => {
const key = keyFn(...args);
if (cache.has(key)) {
return cache.get(key);
}
const result = fn(...args);
cache.set(key, result);
return result;
};
) => (...args: T): U => {
const key = keyFn(...args);
if (cache.has(key)) {
return cache.get(key);
}
const result = fn(...args);
cache.set(key, result);
return result;
};

View File

@ -34,11 +34,8 @@ const GRAY_BACKGROUND_COLOR = '#F5F5F5';
* @param description title or description of content of file
* @param date date when file was generated
*/
const generateFileStem = (description: string, date = new Date()) => {
return `${kebabCase(description)}-${date
.toISOString()
.replace(/[: ]/g, '-')}`;
};
const generateFileStem = (description: string, date = new Date()) =>
`${kebabCase(description)}-${date.toISOString().replace(/[: ]/g, '-')}`;
/**
* Create an event handler for turning an element into an image

View File

@ -205,11 +205,10 @@ function AlertList({
row: {
original: { last_eval_dttm: lastEvalDttm },
},
}: any) => {
return lastEvalDttm
}: any) =>
lastEvalDttm
? moment.utc(lastEvalDttm).local().format(DATETIME_WITH_TIME_ZONE)
: '';
},
: '',
accessor: 'last_eval_dttm',
Header: t('Last Run'),
size: 'lg',

View File

@ -415,13 +415,11 @@ const NotificationMethod: FunctionComponent<NotificationMethodProps> = ({
setRecipientValue(recipients);
}
const methodOptions = (options || []).map((method: NotificationMethod) => {
return (
<Select.Option key={method} value={method}>
{t(method)}
</Select.Option>
);
});
const methodOptions = (options || []).map((method: NotificationMethod) => (
<Select.Option key={method} value={method}>
{t(method)}
</Select.Option>
));
return (
<StyledNotificationMethod>
@ -477,9 +475,10 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
isReport = false,
}) => {
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');
@ -491,9 +490,10 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
const isEditMode = alert !== null;
const [notificationAddState, setNotificationAddState] = useState<
NotificationAddStatus
>('active');
const [
notificationAddState,
setNotificationAddState,
] = useState<NotificationAddStatus>('active');
const [notificationSettings, setNotificationSettings] = useState<
NotificationSetting[]
>([]);
@ -636,15 +636,12 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
return SupersetClient.get({
endpoint: `/api/v1/report/related/owners?q=${query}`,
}).then(
response => {
return response.json.result.map((item: any) => ({
response =>
response.json.result.map((item: any) => ({
value: item.value,
label: item.text,
}));
},
badResponse => {
return [];
},
})),
badResponse => [],
);
};
@ -672,9 +669,7 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
return list;
},
badResponse => {
return [];
},
badResponse => [],
);
};
@ -721,9 +716,7 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
return list;
},
badResponse => {
return [];
},
badResponse => [],
);
};
@ -766,9 +759,7 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
return list;
},
badResponse => {
return [];
},
badResponse => [],
);
};
@ -1029,21 +1020,17 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
}
// Dropdown options
const conditionOptions = CONDITIONS.map(condition => {
return (
<Select.Option key={condition.value} value={condition.value}>
{condition.label}
</Select.Option>
);
});
const conditionOptions = CONDITIONS.map(condition => (
<Select.Option key={condition.value} value={condition.value}>
{condition.label}
</Select.Option>
));
const retentionOptions = RETENTION_OPTIONS.map(option => {
return (
<Select.Option key={option.value} value={option.value}>
{option.label}
</Select.Option>
);
});
const retentionOptions = RETENTION_OPTIONS.map(option => (
<Select.Option key={option.value} value={option.value}>
{option.label}
</Select.Option>
));
return (
<Modal

View File

@ -68,9 +68,10 @@ function AnnotationLayersList({
addDangerToast,
);
const [annotationLayerModalOpen, setAnnotationLayerModalOpen] = useState<
boolean
>(false);
const [
annotationLayerModalOpen,
setAnnotationLayerModalOpen,
] = useState<boolean>(false);
const [
currentAnnotationLayer,
setCurrentAnnotationLayer,

View File

@ -536,13 +536,12 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({
);
};
const handleBulkDatasetExport = (datasetsToExport: Dataset[]) => {
return window.location.assign(
const handleBulkDatasetExport = (datasetsToExport: Dataset[]) =>
window.location.assign(
`/api/v1/dataset/export/?q=${rison.encode(
datasetsToExport.map(({ id }) => id),
)}`,
);
};
return (
<>

View File

@ -102,9 +102,10 @@ function QueryList({ addDangerToast, addSuccessToast }: QueryListProps) {
false,
);
const [queryCurrentlyPreviewing, setQueryCurrentlyPreviewing] = useState<
QueryObject
>();
const [
queryCurrentlyPreviewing,
setQueryCurrentlyPreviewing,
] = useState<QueryObject>();
const handleQueryPreview = useCallback(
(id: number) => {
@ -298,20 +299,18 @@ function QueryList({ addDangerToast, addSuccessToast }: QueryListProps) {
{
accessor: QueryObjectColumns.sql,
Header: t('SQL'),
Cell: ({ row: { original, id } }: any) => {
return (
<div
tabIndex={0}
role="button"
data-test={`open-sql-preview-${id}`}
onClick={() => setQueryCurrentlyPreviewing(original)}
>
<StyledSyntaxHighlighter language="sql" style={github}>
{shortenSQL(original.sql, SQL_PREVIEW_MAX_LINES)}
</StyledSyntaxHighlighter>
</div>
);
},
Cell: ({ row: { original, id } }: any) => (
<div
tabIndex={0}
role="button"
data-test={`open-sql-preview-${id}`}
onClick={() => setQueryCurrentlyPreviewing(original)}
>
<StyledSyntaxHighlighter language="sql" style={github}>
{shortenSQL(original.sql, SQL_PREVIEW_MAX_LINES)}
</StyledSyntaxHighlighter>
</div>
),
},
{
Header: t('Actions'),
@ -321,15 +320,13 @@ function QueryList({ addDangerToast, addSuccessToast }: QueryListProps) {
row: {
original: { id },
},
}: any) => {
return (
<Tooltip title={t('Open query in SQL Lab')} placement="bottom">
<a href={`/superset/sqllab?queryId=${id}`}>
<Icon name="full" />
</a>
</Tooltip>
);
},
}: any) => (
<Tooltip title={t('Open query in SQL Lab')} placement="bottom">
<a href={`/superset/sqllab?queryId=${id}`}>
<Icon name="full" />
</a>
</Tooltip>
),
},
],
[],

View File

@ -146,28 +146,26 @@ export default function ActivityTable({
}
return e.sql ? `/superset/sqllab?savedQueryId=${e.id}` : e.url;
};
return activityData[activeChild].map((e: ActivityObjects) => {
return (
<CardStyles
onClick={() => {
window.location.href = getRecentRef(e);
}}
key={e.id}
>
<ListViewCard
loading={loading}
cover={<></>}
url={e.sql ? `/superset/sqllab?savedQueryId=${e.id}` : e.url}
title={getFilterTitle(e)}
description={`Last Edited: ${moment(e.changed_on_utc).format(
'MM/DD/YYYY HH:mm:ss',
)}`}
avatar={getIconName(e)}
actions={null}
/>
</CardStyles>
);
});
return activityData[activeChild].map((e: ActivityObjects) => (
<CardStyles
onClick={() => {
window.location.href = getRecentRef(e);
}}
key={e.id}
>
<ListViewCard
loading={loading}
cover={<></>}
url={e.sql ? `/superset/sqllab?savedQueryId=${e.id}` : e.url}
title={getFilterTitle(e)}
description={`Last Edited: ${moment(e.changed_on_utc).format(
'MM/DD/YYYY HH:mm:ss',
)}`}
avatar={getIconName(e)}
actions={null}
/>
</CardStyles>
));
};
if (loading) return <Loading position="inline" />;
return (

View File

@ -100,8 +100,8 @@ function ChartTable({
return filters;
};
const getData = (filter: string) => {
return fetchData({
const getData = (filter: string) =>
fetchData({
pageIndex: 0,
pageSize: PAGE_SIZE,
sortBy: [
@ -112,7 +112,6 @@ function ChartTable({
],
filters: getFilters(filter),
});
};
return (
<ErrorBoundary>

View File

@ -66,8 +66,8 @@ function DashboardTable({
const [editModal, setEditModal] = useState<Dashboard>();
const [dashboardFilter, setDashboardFilter] = useState('Mine');
const handleDashboardEdit = (edits: Dashboard) => {
return SupersetClient.get({
const handleDashboardEdit = (edits: Dashboard) =>
SupersetClient.get({
endpoint: `/api/v1/dashboard/${edits.id}`,
}).then(
({ json = {} }) => {
@ -86,7 +86,6 @@ function DashboardTable({
),
),
);
};
const getFilters = (filterName: string) => {
const filters = [];
@ -114,8 +113,8 @@ function DashboardTable({
});
}
const getData = (filter: string) => {
return fetchData({
const getData = (filter: string) =>
fetchData({
pageIndex: 0,
pageSize: PAGE_SIZE,
sortBy: [
@ -126,7 +125,6 @@ function DashboardTable({
],
filters: getFilters(filter),
});
};
return (
<>

View File

@ -187,8 +187,8 @@ const SavedQueries = ({
return filters;
};
const getData = (filter: string) => {
return fetchData({
const getData = (filter: string) =>
fetchData({
pageIndex: 0,
pageSize: PAGE_SIZE,
sortBy: [
@ -199,7 +199,6 @@ const SavedQueries = ({
],
filters: getFilters(filter),
});
};
const renderMenu = (query: Query) => (
<Menu>

View File

@ -130,9 +130,7 @@ class FilterBox extends React.PureComponent {
return this.onFilterMenuOpen(TIME_RANGE);
}
onCloseDateFilterControl = () => {
return this.onFilterMenuClose(TIME_RANGE);
};
onCloseDateFilterControl = () => this.onFilterMenuClose(TIME_RANGE);
getControlData(controlName) {
const { selectedValues } = this.state;

View File

@ -173,7 +173,7 @@ const babelLoader = {
[
'@emotion/babel-preset-css-prop',
{
autoLabel: true,
autoLabel: 'dev-only',
labelFormat: '[local]',
},
],
@ -441,9 +441,7 @@ if (isDevMode) {
// and proxy everything else to Superset backend
proxy: [
// functions are called for every request
() => {
return proxyConfig;
},
() => proxyConfig,
],
contentBase: path.join(process.cwd(), '../static/assets'),
};