From e28f3d62208d266873ab2aeb70708fb8d6cc0818 Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Tue, 15 Sep 2020 00:41:32 +0200 Subject: [PATCH] Re-enable rule line-between-class-members (#10862) --- superset-frontend/.eslintrc.js | 2 -- .../src/CRUD/CollectionTable.tsx | 16 ++++++++++++ superset-frontend/src/CRUD/Field.jsx | 2 ++ superset-frontend/src/CRUD/Fieldset.jsx | 2 ++ .../SqlLab/components/AceEditorWrapper.tsx | 10 +++++++ .../src/SqlLab/components/App.jsx | 8 ++++++ .../components/ExploreCtasResultsButton.jsx | 3 +++ .../components/ExploreResultsButton.jsx | 10 +++++++ .../src/SqlLab/components/HighlightedSql.jsx | 4 +++ .../SqlLab/components/QueryAutoRefresh.jsx | 8 ++++++ .../src/SqlLab/components/QueryTable.jsx | 4 +++ .../src/SqlLab/components/ResultSet.tsx | 11 ++++++++ .../src/SqlLab/components/SaveQuery.jsx | 10 +++++++ .../SqlLab/components/ScheduleQueryButton.jsx | 7 +++++ .../src/SqlLab/components/SouthPane.jsx | 4 +++ .../src/SqlLab/components/SqlEditor.jsx | 26 +++++++++++++++++++ .../SqlLab/components/SqlEditorLeftBar.jsx | 8 ++++++ .../SqlLab/components/TabbedSqlEditors.jsx | 12 +++++++++ .../src/SqlLab/components/TableElement.jsx | 4 +++ .../components/TemplateParamsEditor.jsx | 5 ++++ .../FilterableTable/FilterableTable.tsx | 5 ++++ .../src/components/FlashProvider.tsx | 1 + superset-frontend/src/components/Hotkeys.jsx | 2 ++ .../src/components/ModalTrigger.jsx | 1 + .../src/components/Pagination.tsx | 4 +++ .../components/BuilderComponentPane.jsx | 1 + .../components/ColorSchemeControlWrapper.jsx | 1 + .../dashboard/components/PropertiesModal.jsx | 1 + .../src/datasource/DatasourceEditor.jsx | 1 + .../src/explore/components/Control.jsx | 3 +++ .../src/explore/components/ControlHeader.jsx | 1 + .../components/ControlPanelSection.jsx | 2 ++ .../explore/components/DisplayQueryButton.jsx | 10 +++++++ .../explore/components/EmbedCodeButton.jsx | 1 + .../components/ExploreViewContainer.jsx | 3 +++ .../src/explore/components/SaveModal.jsx | 7 +++++ .../components/controls/BoundsControl.jsx | 4 +++ .../components/controls/CheckboxControl.jsx | 2 ++ .../components/controls/CollectionControl.jsx | 6 +++++ .../controls/ColorPickerControl.jsx | 3 +++ .../components/controls/DateFilterControl.jsx | 11 ++++++++ .../controls/FilterBoxItemControl.jsx | 7 +++++ .../controls/FixedOrMetricControl.jsx | 4 +++ .../components/controls/SpatialControl.jsx | 10 +++++++ .../components/controls/TextAreaControl.jsx | 4 +++ .../components/controls/TextControl.tsx | 2 ++ .../controls/TimeSeriesColumnControl.jsx | 12 +++++++++ .../components/controls/ViewportControl.jsx | 5 ++++ .../src/profile/components/CreatedContent.tsx | 2 ++ .../src/profile/components/Favorites.tsx | 2 ++ .../src/utils/DebouncedMessageQueue.js | 2 ++ .../CRUD/data/database/DatabaseModal.tsx | 2 +- .../visualizations/FilterBox/FilterBox.jsx | 2 ++ 53 files changed, 277 insertions(+), 3 deletions(-) diff --git a/superset-frontend/.eslintrc.js b/superset-frontend/.eslintrc.js index d1cbd2ce0..591539b62 100644 --- a/superset-frontend/.eslintrc.js +++ b/superset-frontend/.eslintrc.js @@ -84,7 +84,6 @@ module.exports = { 'jsx-a11y/anchor-is-valid': 0, // disabled temporarily 'jsx-a11y/click-events-have-key-events': 0, // re-enable up for discussion 'jsx-a11y/mouse-events-have-key-events': 0, // re-enable up for discussion - 'lines-between-class-members': 0, // disabled temporarily 'new-cap': 0, 'no-bitwise': 0, 'no-continue': 0, @@ -197,7 +196,6 @@ module.exports = { 'jsx-a11y/anchor-is-valid': 0, // disabled temporarily 'jsx-a11y/click-events-have-key-events': 0, // re-enable up for discussion 'jsx-a11y/mouse-events-have-key-events': 0, // re-enable up for discussion - 'lines-between-class-members': 0, // disabled temporarily 'new-cap': 0, 'no-bitwise': 0, 'no-continue': 0, diff --git a/superset-frontend/src/CRUD/CollectionTable.tsx b/superset-frontend/src/CRUD/CollectionTable.tsx index 61a5477d8..661547fbe 100644 --- a/superset-frontend/src/CRUD/CollectionTable.tsx +++ b/superset-frontend/src/CRUD/CollectionTable.tsx @@ -78,6 +78,7 @@ export default class CRUDCollection extends React.PureComponent< this.renderTableBody = this.renderTableBody.bind(this); this.changeCollection = this.changeCollection.bind(this); } + UNSAFE_componentWillReceiveProps(nextProps: CRUDCollectionProps) { if (nextProps.collection !== this.props.collection) { this.setState({ @@ -85,6 +86,7 @@ export default class CRUDCollection extends React.PureComponent< }); } } + onCellChange(id: number, col: string, val: boolean) { this.changeCollection({ ...this.state.collection, @@ -94,6 +96,7 @@ export default class CRUDCollection extends React.PureComponent< }, }); } + onAddItem() { if (this.props.itemGenerator) { let newItem = this.props.itemGenerator(); @@ -106,12 +109,14 @@ export default class CRUDCollection extends React.PureComponent< }); } } + onFieldsetChange(item: any) { this.changeCollection({ ...this.state.collection, [item.id]: item, }); } + getLabel(col: any) { const { columnLabels } = this.props; let label = columnLabels && columnLabels[col] ? columnLabels[col] : col; @@ -121,17 +126,20 @@ export default class CRUDCollection extends React.PureComponent< } return label; } + changeCollection(collection: any) { this.setState({ collection }); if (this.props.onChange) { this.props.onChange(Object.keys(collection).map(k => collection[k])); } } + deleteItem(id: number) { const newColl = { ...this.state.collection }; delete newColl[id]; this.changeCollection(newColl); } + effectiveTableColumns() { const { tableColumns, allowDeletes, expandFieldset } = this.props; const cols = allowDeletes @@ -139,6 +147,7 @@ export default class CRUDCollection extends React.PureComponent< : tableColumns; return expandFieldset ? ['__expand'].concat(cols) : cols; } + toggleExpand(id: any) { this.onCellChange(id, '__expanded', false); this.setState({ @@ -148,6 +157,7 @@ export default class CRUDCollection extends React.PureComponent< }, }); } + renderHeaderRow() { const cols = this.effectiveTableColumns(); const { @@ -178,6 +188,7 @@ export default class CRUDCollection extends React.PureComponent< ); } + renderExpandableSection(item: any) { const propsGenerator = () => ({ item, onChange: this.onFieldsetChange }); return recurseReactClone( @@ -186,12 +197,14 @@ export default class CRUDCollection extends React.PureComponent< propsGenerator, ); } + renderCell(record: any, col: any) { const renderer = this.props.itemRenderers && this.props.itemRenderers[col]; const val = record[col]; const onChange = this.onCellChange.bind(this, record.id, col); return renderer ? renderer(val, onChange, this.getLabel(col), record) : val; } + renderItem(record: any) { const { allowAddItem, @@ -258,6 +271,7 @@ export default class CRUDCollection extends React.PureComponent< } return trs; } + renderEmptyCell() { return ( @@ -265,6 +279,7 @@ export default class CRUDCollection extends React.PureComponent< ); } + renderTableBody() { const data = Object.keys(this.state.collection).map( k => this.state.collection[k], @@ -274,6 +289,7 @@ export default class CRUDCollection extends React.PureComponent< : this.renderEmptyCell(); return {content}; } + render() { return (
diff --git a/superset-frontend/src/CRUD/Field.jsx b/superset-frontend/src/CRUD/Field.jsx index 7b249b439..3d56019fa 100644 --- a/superset-frontend/src/CRUD/Field.jsx +++ b/superset-frontend/src/CRUD/Field.jsx @@ -50,9 +50,11 @@ export default class Field extends React.PureComponent { super(props); this.onChange = this.onChange.bind(this); } + onChange(newValue) { this.props.onChange(this.props.fieldKey, newValue); } + render() { const { compact, diff --git a/superset-frontend/src/CRUD/Fieldset.jsx b/superset-frontend/src/CRUD/Fieldset.jsx index f73cd7928..15eb1a7cb 100644 --- a/superset-frontend/src/CRUD/Fieldset.jsx +++ b/superset-frontend/src/CRUD/Fieldset.jsx @@ -40,12 +40,14 @@ export default class Fieldset extends React.PureComponent { super(props); this.onChange = this.onChange.bind(this); } + onChange(fieldKey, val) { return this.props.onChange({ ...this.props.item, [fieldKey]: val, }); } + render() { const { title } = this.props; const propExtender = field => ({ diff --git a/superset-frontend/src/SqlLab/components/AceEditorWrapper.tsx b/superset-frontend/src/SqlLab/components/AceEditorWrapper.tsx index f3779b90a..a05ef3cdf 100644 --- a/superset-frontend/src/SqlLab/components/AceEditorWrapper.tsx +++ b/superset-frontend/src/SqlLab/components/AceEditorWrapper.tsx @@ -83,11 +83,13 @@ class AceEditorWrapper extends React.PureComponent { }; this.onChange = this.onChange.bind(this); } + componentDidMount() { // Making sure no text is selected from previous mount this.props.actions.queryEditorSetSelectedText(this.props.queryEditor, null); this.setAutoCompleter(this.props); } + UNSAFE_componentWillReceiveProps(nextProps: Props) { if ( !areArraysShallowEqual(this.props.tables, nextProps.tables) || @@ -103,12 +105,15 @@ class AceEditorWrapper extends React.PureComponent { this.setState({ sql: nextProps.sql }); } } + onBlur() { this.props.onBlur(this.state.sql); } + onAltEnter() { this.props.onBlur(this.state.sql); } + onEditorLoad(editor: any) { editor.commands.addCommand({ name: 'runQuery', @@ -140,10 +145,12 @@ class AceEditorWrapper extends React.PureComponent { } }); } + onChange(text: string) { this.setState({ sql: text }); this.props.onChange(text); } + getCompletions( aceEditor: any, session: any, @@ -180,6 +187,7 @@ class AceEditorWrapper extends React.PureComponent { }); callback(null, words); } + setAutoCompleter(props: Props) { // Loading schema, table and column names as auto-completable words const schemas = props.schemas || []; @@ -236,6 +244,7 @@ class AceEditorWrapper extends React.PureComponent { } }); } + getAceAnnotations() { const { validationResult } = this.props.queryEditor; const resultIsReady = validationResult && validationResult.completed; @@ -250,6 +259,7 @@ class AceEditorWrapper extends React.PureComponent { } return []; } + render() { return ( = @@ -64,13 +66,16 @@ class App extends React.PureComponent { ); } } + componentWillUnmount() { window.removeEventListener('hashchange', this.onHashChanged.bind(this)); window.removeEventListener('resize', this.handleResize.bind(this)); } + onHashChanged() { this.setState({ hash: window.location.hash }); } + getHeight() { const warningEl = $('#navbar-warning'); const tabsEl = $('.nav-tabs'); @@ -96,6 +101,7 @@ class App extends React.PureComponent { alertHeight }px`; } + showLocalStorageUsageWarning(currentUsage) { this.props.actions.addDangerToast( t( @@ -109,9 +115,11 @@ class App extends React.PureComponent { ), ); } + handleResize() { this.setState({ contentHeight: this.getHeight() }); } + render() { let content; if (this.state.hash) { diff --git a/superset-frontend/src/SqlLab/components/ExploreCtasResultsButton.jsx b/superset-frontend/src/SqlLab/components/ExploreCtasResultsButton.jsx index 5e11204b6..5c6f78f2f 100644 --- a/superset-frontend/src/SqlLab/components/ExploreCtasResultsButton.jsx +++ b/superset-frontend/src/SqlLab/components/ExploreCtasResultsButton.jsx @@ -47,6 +47,7 @@ class ExploreCtasResultsButton extends React.PureComponent { this.visualize = this.visualize.bind(this); this.onClick = this.onClick.bind(this); } + onClick() { this.visualize(); } @@ -59,6 +60,7 @@ class ExploreCtasResultsButton extends React.PureComponent { templateParams: this.props.templateParams, }; } + visualize() { this.props.actions .createCtasDatasource(this.buildVizOptions()) @@ -85,6 +87,7 @@ class ExploreCtasResultsButton extends React.PureComponent { ); }); } + render() { return ( <> diff --git a/superset-frontend/src/SqlLab/components/ExploreResultsButton.jsx b/superset-frontend/src/SqlLab/components/ExploreResultsButton.jsx index 2e5c1879e..0e3661d9a 100644 --- a/superset-frontend/src/SqlLab/components/ExploreResultsButton.jsx +++ b/superset-frontend/src/SqlLab/components/ExploreResultsButton.jsx @@ -52,6 +52,7 @@ class ExploreResultsButton extends React.PureComponent { this, ); } + onClick() { const { timeout } = this.props; const msg = this.renderInvalidColumnMessage(); @@ -85,6 +86,7 @@ class ExploreResultsButton extends React.PureComponent { this.visualize(); } } + getColumns() { const { props } = this; if ( @@ -96,11 +98,13 @@ class ExploreResultsButton extends React.PureComponent { } return []; } + getQueryDuration() { return moment .duration(this.props.query.endDttm - this.props.query.startDttm) .asSeconds(); } + getInvalidColumns() { const re1 = /__\d+$/; // duplicate column name pattern const re2 = /^__timestamp/i; // reserved temporal column alias @@ -109,6 +113,7 @@ class ExploreResultsButton extends React.PureComponent { .map(col => col.name) .filter(col => re1.test(col) || re2.test(col)); } + datasourceName() { const { query } = this.props; const uniqueId = shortid.generate(); @@ -119,6 +124,7 @@ class ExploreResultsButton extends React.PureComponent { } return datasourceName; } + buildVizOptions() { const { schema, sql, dbId, templateParams } = this.props.query; return { @@ -130,6 +136,7 @@ class ExploreResultsButton extends React.PureComponent { columns: this.getColumns(), }; } + visualize() { this.props.actions .createDatasource(this.buildVizOptions()) @@ -158,6 +165,7 @@ class ExploreResultsButton extends React.PureComponent { ); }); } + renderTimeoutWarning() { return ( @@ -181,6 +189,7 @@ class ExploreResultsButton extends React.PureComponent { ); } + renderInvalidColumnMessage() { const invalidColumns = this.getInvalidColumns(); if (invalidColumns.length === 0) { @@ -200,6 +209,7 @@ class ExploreResultsButton extends React.PureComponent {
); } + render() { const allowsSubquery = this.props.database && this.props.database.allows_subquery; diff --git a/superset-frontend/src/SqlLab/components/HighlightedSql.jsx b/superset-frontend/src/SqlLab/components/HighlightedSql.jsx index e2409fd91..57ce57910 100644 --- a/superset-frontend/src/SqlLab/components/HighlightedSql.jsx +++ b/superset-frontend/src/SqlLab/components/HighlightedSql.jsx @@ -50,6 +50,7 @@ class HighlightedSql extends React.Component { modalBody: null, }; } + shrinkSql() { const ssql = this.props.sql || ''; let lines = ssql.split('\n'); @@ -66,6 +67,7 @@ class HighlightedSql extends React.Component { }) .join('\n'); } + triggerNode() { const shownSql = this.props.shrink ? this.shrinkSql(this.props.sql) @@ -76,6 +78,7 @@ class HighlightedSql extends React.Component { ); } + generateModal() { let rawSql; if (this.props.rawSql && this.props.rawSql !== this.props.sql) { @@ -100,6 +103,7 @@ class HighlightedSql extends React.Component { ), }); } + render() { return ( isQueryRunning(q) && now - q.startDttm < MAX_QUERY_AGE_TO_POLL, ); } + startTimer() { if (!this.timer) { this.timer = setInterval(this.stopwatch.bind(this), QUERY_UPDATE_FREQ); } } + stopTimer() { clearInterval(this.timer); this.timer = null; } + stopwatch() { // only poll /superset/queries/ if there are started or running queries if (this.shouldCheckForQueries()) { @@ -89,6 +96,7 @@ class QueryAutoRefresh extends React.PureComponent { this.setState({ offline: false }); } } + render() { return null; } diff --git a/superset-frontend/src/SqlLab/components/QueryTable.jsx b/superset-frontend/src/SqlLab/components/QueryTable.jsx index 2a23acd4f..978427df7 100644 --- a/superset-frontend/src/SqlLab/components/QueryTable.jsx +++ b/superset-frontend/src/SqlLab/components/QueryTable.jsx @@ -60,15 +60,19 @@ class QueryTable extends React.PureComponent { openQueryInNewTab(query) { this.props.actions.cloneQueryToNewTab(query, true); } + openAsyncResults(query, displayLimit) { this.props.actions.fetchQueryResults(query, displayLimit); } + clearQueryResults(query) { this.props.actions.clearQueryResults(query); } + removeQuery(query) { this.props.actions.removeQuery(query); } + render() { const data = this.props.queries .map(query => { diff --git a/superset-frontend/src/SqlLab/components/ResultSet.tsx b/superset-frontend/src/SqlLab/components/ResultSet.tsx index 3b2c218d9..1846ddc1a 100644 --- a/superset-frontend/src/SqlLab/components/ResultSet.tsx +++ b/superset-frontend/src/SqlLab/components/ResultSet.tsx @@ -86,10 +86,12 @@ export default class ResultSet extends React.PureComponent< this, ); } + componentDidMount() { // only do this the first time the component is rendered/mounted this.reRunQueryIfSessionTimeoutErrorOnMount(); } + UNSAFE_componentWillReceiveProps(nextProps: ResultSetProps) { // when new results comes in, save them locally and clear in store if ( @@ -110,9 +112,11 @@ export default class ResultSet extends React.PureComponent< this.fetchResults(nextProps.query); } } + clearQueryResults(query: Query) { this.props.actions.clearQueryResults(query); } + popSelectStar(tempSchema: string | null, tempTable: string) { const qe = { id: shortid.generate(), @@ -123,20 +127,25 @@ export default class ResultSet extends React.PureComponent< }; this.props.actions.addQueryEditor(qe); } + toggleExploreResultsButton() { this.setState({ showExploreResultsButton: !this.state.showExploreResultsButton, }); } + changeSearch(event: React.ChangeEvent) { this.setState({ searchText: event.target.value }); } + fetchResults(query: Query) { this.props.actions.fetchQueryResults(query, this.props.displayLimit); } + reFetchQueryResults(query: Query) { this.props.actions.reFetchQueryResults(query); } + reRunQueryIfSessionTimeoutErrorOnMount() { const { query } = this.props; if ( @@ -146,6 +155,7 @@ export default class ResultSet extends React.PureComponent< this.props.actions.runQuery(query, true); } } + renderControls() { if (this.props.search || this.props.visualize || this.props.csv) { let { data } = this.props.query.results; @@ -198,6 +208,7 @@ export default class ResultSet extends React.PureComponent< } return
; } + render() { const { query } = this.props; const height = Math.max( diff --git a/superset-frontend/src/SqlLab/components/SaveQuery.jsx b/superset-frontend/src/SqlLab/components/SaveQuery.jsx index e7ed40883..cbda842dc 100644 --- a/superset-frontend/src/SqlLab/components/SaveQuery.jsx +++ b/superset-frontend/src/SqlLab/components/SaveQuery.jsx @@ -55,23 +55,29 @@ class SaveQuery extends React.PureComponent { this.onLabelChange = this.onLabelChange.bind(this); this.onDescriptionChange = this.onDescriptionChange.bind(this); } + onSave() { this.props.onSave(this.queryPayload()); this.close(); } + onUpdate() { this.props.onUpdate(this.queryPayload()); this.close(); } + onCancel() { this.close(); } + onLabelChange(e) { this.setState({ label: e.target.value }); } + onDescriptionChange(e) { this.setState({ description: e.target.value }); } + queryPayload() { return { ...this.props.query, @@ -79,12 +85,15 @@ class SaveQuery extends React.PureComponent { description: this.state.description, }; } + close() { if (this.saveModal) this.saveModal.close(); } + toggleSave() { this.setState({ showSave: !this.state.showSave }); } + renderModalBody() { const isSaved = !!this.props.query.remoteId; return ( @@ -157,6 +166,7 @@ class SaveQuery extends React.PureComponent { ); } + render() { return ( diff --git a/superset-frontend/src/SqlLab/components/ScheduleQueryButton.jsx b/superset-frontend/src/SqlLab/components/ScheduleQueryButton.jsx index 96d055efc..f9a778dd5 100644 --- a/superset-frontend/src/SqlLab/components/ScheduleQueryButton.jsx +++ b/superset-frontend/src/SqlLab/components/ScheduleQueryButton.jsx @@ -106,6 +106,7 @@ class ScheduleQueryButton extends React.PureComponent { this.onLabelChange = this.onLabelChange.bind(this); this.onDescriptionChange = this.onDescriptionChange.bind(this); } + onSchedule({ formData }) { const query = { label: this.state.label, @@ -118,18 +119,23 @@ class ScheduleQueryButton extends React.PureComponent { this.props.onSchedule(query); this.saveModal.close(); } + onCancel() { this.saveModal.close(); } + onLabelChange(e) { this.setState({ label: e.target.value }); } + onDescriptionChange(e) { this.setState({ description: e.target.value }); } + toggleSchedule() { this.setState({ showSchedule: !this.state.showSchedule }); } + renderModalBody() { return ( @@ -181,6 +187,7 @@ class ScheduleQueryButton extends React.PureComponent { ); } + render() { return ( diff --git a/superset-frontend/src/SqlLab/components/SouthPane.jsx b/superset-frontend/src/SqlLab/components/SouthPane.jsx index 92a3c4e4d..2b2b27052 100644 --- a/superset-frontend/src/SqlLab/components/SouthPane.jsx +++ b/superset-frontend/src/SqlLab/components/SouthPane.jsx @@ -68,19 +68,23 @@ export class SouthPane extends React.PureComponent { this.getSouthPaneHeight = this.getSouthPaneHeight.bind(this); this.switchTab = this.switchTab.bind(this); } + UNSAFE_componentWillReceiveProps() { // south pane expands the entire height of the tab content on mount this.setState({ height: this.getSouthPaneHeight() }); } + // One layer of abstraction for easy spying in unit tests getSouthPaneHeight() { return this.southPaneRef.current ? this.southPaneRef.current.clientHeight : 0; } + switchTab(id) { this.props.actions.setActiveSouthPaneTab(id); } + render() { if (this.props.offline) { return ( diff --git a/superset-frontend/src/SqlLab/components/SqlEditor.jsx b/superset-frontend/src/SqlLab/components/SqlEditor.jsx index c3757c79a..a95dbd038 100644 --- a/superset-frontend/src/SqlLab/components/SqlEditor.jsx +++ b/superset-frontend/src/SqlLab/components/SqlEditor.jsx @@ -128,6 +128,7 @@ class SqlEditor extends React.PureComponent { WINDOW_RESIZE_THROTTLE_MS, ); } + UNSAFE_componentWillMount() { if (this.state.autorun) { this.setState({ autorun: false }); @@ -135,6 +136,7 @@ class SqlEditor extends React.PureComponent { this.startQuery(); } } + componentDidMount() { // We need to measure the height of the sql editor post render to figure the height of // the south pane so it gets rendered properly @@ -143,14 +145,17 @@ class SqlEditor extends React.PureComponent { window.addEventListener('resize', this.handleWindowResize); } + componentWillUnmount() { window.removeEventListener('resize', this.handleWindowResize); } + onResizeStart() { // Set the heights on the ace editor and the ace content area after drag starts // to smooth out the visual transition to the new heights when drag ends document.getElementsByClassName('ace_content')[0].style.height = '100%'; } + onResizeEnd([northPercent, southPercent]) { this.setState({ northPercent, southPercent }); @@ -162,6 +167,7 @@ class SqlEditor extends React.PureComponent { ); } } + onSqlChanged(sql) { this.setState({ sql }); this.setQueryEditorSqlWithDebounce(sql); @@ -171,12 +177,14 @@ class SqlEditor extends React.PureComponent { this.requestValidation(); } } + // One layer of abstraction for easy spying in unit tests getSqlEditorHeight() { return this.sqlEditorRef.current ? this.sqlEditorRef.current.clientHeight - SQL_EDITOR_PADDING * 2 : 0; } + // Return the heights for the ace editor and the south pane as an object // given the height of the sql editor, north pane percent and south pane percent. getAceEditorAndSouthPaneHeights(height, northPercent, southPercent) { @@ -190,6 +198,7 @@ class SqlEditor extends React.PureComponent { (SQL_EDITOR_GUTTER_HEIGHT / 2 + SQL_EDITOR_GUTTER_MARGIN), }; } + getHotkeyConfig() { return [ { @@ -224,15 +233,18 @@ class SqlEditor extends React.PureComponent { }, ]; } + setQueryEditorSql(sql) { this.props.actions.queryEditorSetSql(this.props.queryEditor, sql); } + setQueryLimit(queryLimit) { this.props.actions.queryEditorSetQueryLimit( this.props.queryEditor, queryLimit, ); } + getQueryCostEstimate() { if (this.props.database) { const qe = this.props.queryEditor; @@ -246,12 +258,15 @@ class SqlEditor extends React.PureComponent { this.props.actions.estimateQueryCost(query); } } + handleToggleAutocompleteEnabled = () => { this.setState({ autocompleteEnabled: !this.state.autocompleteEnabled }); }; + handleWindowResize() { this.setState({ height: this.getSqlEditorHeight() }); } + elementStyle(dimension, elementSize, gutterSize) { return { [dimension]: `calc(${elementSize}% - ${ @@ -259,6 +274,7 @@ class SqlEditor extends React.PureComponent { }px)`, }; } + requestValidation() { if (this.props.database) { const qe = this.props.queryEditor; @@ -272,6 +288,7 @@ class SqlEditor extends React.PureComponent { this.props.actions.validateQuery(query); } } + canValidateQuery() { // Check whether or not we can validate the current query based on whether // or not the backend has a validator configured for it. @@ -281,11 +298,13 @@ class SqlEditor extends React.PureComponent { } return false; } + runQuery() { if (this.props.database) { this.startQuery(); } } + startQuery(ctas = false, ctas_method = CtasEnum.TABLE) { const qe = this.props.queryEditor; const query = { @@ -307,6 +326,7 @@ class SqlEditor extends React.PureComponent { this.props.actions.runQuery(query); this.props.actions.setActiveSouthPaneTab('Results'); } + stopQuery() { if ( this.props.latestQuery && @@ -315,15 +335,19 @@ class SqlEditor extends React.PureComponent { this.props.actions.postStopQuery(this.props.latestQuery); } } + createTableAs() { this.startQuery(true, CtasEnum.TABLE); } + createViewAs() { this.startQuery(true, CtasEnum.VIEW); } + ctasChanged(event) { this.setState({ ctas: event.target.value }); } + queryPane() { const hotkeys = this.getHotkeyConfig(); const { @@ -376,6 +400,7 @@ class SqlEditor extends React.PureComponent { ); } + renderEditorBottomBar(hotkeys) { let ctasControls; if ( @@ -560,6 +585,7 @@ class SqlEditor extends React.PureComponent {
); } + render() { return (
diff --git a/superset-frontend/src/SqlLab/components/SqlEditorLeftBar.jsx b/superset-frontend/src/SqlLab/components/SqlEditorLeftBar.jsx index dfd04e0a1..552ba4ce6 100644 --- a/superset-frontend/src/SqlLab/components/SqlEditorLeftBar.jsx +++ b/superset-frontend/src/SqlLab/components/SqlEditorLeftBar.jsx @@ -50,27 +50,33 @@ export default class SqlEditorLeftBar extends React.PureComponent { this.getDbList = this.getDbList.bind(this); this.onTableChange = this.onTableChange.bind(this); } + onSchemaChange(schema) { this.props.actions.queryEditorSetSchema(this.props.queryEditor, schema); } + onSchemasLoad(schemas) { this.props.actions.queryEditorSetSchemaOptions( this.props.queryEditor, schemas, ); } + onTablesLoad(tables) { this.props.actions.queryEditorSetTableOptions( this.props.queryEditor, tables, ); } + onDbChange(db) { this.props.actions.queryEditorSetDb(this.props.queryEditor, db.id); } + onTableChange(tableName, schemaName) { this.props.actions.addTable(this.props.queryEditor, tableName, schemaName); } + getDbList(dbs) { this.props.actions.setDatabases(dbs); } @@ -92,6 +98,7 @@ export default class SqlEditorLeftBar extends React.PureComponent { resetState() { this.props.actions.resetState(); } + changeTable(tableOpt) { if (!tableOpt) { return; @@ -105,6 +112,7 @@ export default class SqlEditorLeftBar extends React.PureComponent { closePopover(ref) { this.refs[ref].hide(); } + render() { const shouldShowReset = window.location.search === '?reset=1'; const tableMetaDataHeight = this.props.height - 130; // 130 is the height of the selects above diff --git a/superset-frontend/src/SqlLab/components/TabbedSqlEditors.jsx b/superset-frontend/src/SqlLab/components/TabbedSqlEditors.jsx index 9ab25012c..b97d28d81 100644 --- a/superset-frontend/src/SqlLab/components/TabbedSqlEditors.jsx +++ b/superset-frontend/src/SqlLab/components/TabbedSqlEditors.jsx @@ -75,6 +75,7 @@ class TabbedSqlEditors extends React.PureComponent { ); this.duplicateQueryEditor = this.duplicateQueryEditor.bind(this); } + componentDidMount() { // migrate query editor and associated tables state to server if (isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)) { @@ -168,6 +169,7 @@ class TabbedSqlEditors extends React.PureComponent { } } } + UNSAFE_componentWillReceiveProps(nextProps) { const nextActiveQeId = nextProps.tabHistory[nextProps.tabHistory.length - 1]; @@ -201,11 +203,13 @@ class TabbedSqlEditors extends React.PureComponent { this.setState({ dataPreviewQueries }); } } + popNewTab() { queryCount += 1; // Clean the url in browser history window.history.replaceState({}, document.title, this.state.sqlLabUrl); } + renameTab(qe) { /* eslint no-alert: 0 */ const newTitle = prompt(t('Enter a new title for the tab')); @@ -213,6 +217,7 @@ class TabbedSqlEditors extends React.PureComponent { this.props.actions.queryEditorSetTitle(qe, newTitle); } } + activeQueryEditor() { if (this.props.tabHistory.length === 0) { return this.props.queryEditors[0]; @@ -220,6 +225,7 @@ class TabbedSqlEditors extends React.PureComponent { const qeid = this.props.tabHistory[this.props.tabHistory.length - 1]; return this.props.queryEditors.find(qe => qe.id === qeid) || null; } + newQueryEditor() { queryCount += 1; const activeQueryEditor = this.activeQueryEditor(); @@ -244,6 +250,7 @@ class TabbedSqlEditors extends React.PureComponent { }; this.props.actions.addQueryEditor(qe); } + handleSelect(key) { if (key === 'add_tab') { this.newQueryEditor(); @@ -258,20 +265,25 @@ class TabbedSqlEditors extends React.PureComponent { } } } + removeQueryEditor(qe) { this.props.actions.removeQueryEditor(qe); } + removeAllOtherQueryEditors(cqe) { this.props.queryEditors.forEach( qe => qe !== cqe && this.removeQueryEditor(qe), ); } + duplicateQueryEditor(qe) { this.props.actions.cloneQueryToNewTab(qe, false); } + toggleLeftBar() { this.setState({ hideLeftBar: !this.state.hideLeftBar }); } + render() { const editors = this.props.queryEditors.map((qe, i) => { const isSelected = diff --git a/superset-frontend/src/SqlLab/components/TableElement.jsx b/superset-frontend/src/SqlLab/components/TableElement.jsx index ed7563ae5..5594f4194 100644 --- a/superset-frontend/src/SqlLab/components/TableElement.jsx +++ b/superset-frontend/src/SqlLab/components/TableElement.jsx @@ -83,6 +83,7 @@ class TableElement extends React.PureComponent { this.setState({ expanded: false }); this.props.actions.removeDataPreview(this.props.table); } + toggleSortColumns() { this.setState({ sortColumns: !this.state.sortColumns }); } @@ -127,6 +128,7 @@ class TableElement extends React.PureComponent { } return header; } + renderControls() { let keyLink; const { table } = this.props; @@ -190,6 +192,7 @@ class TableElement extends React.PureComponent { ); } + renderHeader() { const { table } = this.props; return ( @@ -228,6 +231,7 @@ class TableElement extends React.PureComponent {
); } + renderBody() { const { table } = this.props; let cols; diff --git a/superset-frontend/src/SqlLab/components/TemplateParamsEditor.jsx b/superset-frontend/src/SqlLab/components/TemplateParamsEditor.jsx index 85ea0cebf..75b317fe5 100644 --- a/superset-frontend/src/SqlLab/components/TemplateParamsEditor.jsx +++ b/superset-frontend/src/SqlLab/components/TemplateParamsEditor.jsx @@ -56,9 +56,11 @@ export default class TemplateParamsEditor extends React.Component { }; this.onChange = this.onChange.bind(this); } + componentDidMount() { this.onChange(this.state.codeText); } + onChange(value) { const codeText = value; let isValid; @@ -75,6 +77,7 @@ export default class TemplateParamsEditor extends React.Component { this.props.onChange(newValue); } } + renderDoc() { return (

@@ -96,6 +99,7 @@ export default class TemplateParamsEditor extends React.Component {

); } + renderModalBody() { return (
@@ -115,6 +119,7 @@ export default class TemplateParamsEditor extends React.Component {
); } + render() { const paramCount = this.state.parsedJSON ? Object.keys(this.state.parsedJSON).length diff --git a/superset-frontend/src/components/FilterableTable/FilterableTable.tsx b/superset-frontend/src/components/FilterableTable/FilterableTable.tsx index c58b4c12a..2df936f81 100644 --- a/superset-frontend/src/components/FilterableTable/FilterableTable.tsx +++ b/superset-frontend/src/components/FilterableTable/FilterableTable.tsx @@ -124,10 +124,15 @@ export default class FilterableTable extends PureComponent< }; list: List; + complexColumns: Record; + widthsForColumnsByKey: Record; + totalTableWidth: number; + totalTableHeight: number; + container: React.RefObject; constructor(props: FilterableTableProps) { diff --git a/superset-frontend/src/components/FlashProvider.tsx b/superset-frontend/src/components/FlashProvider.tsx index 5504288e8..5ecbc3279 100644 --- a/superset-frontend/src/components/FlashProvider.tsx +++ b/superset-frontend/src/components/FlashProvider.tsx @@ -48,6 +48,7 @@ class FlashProvider extends React.PureComponent { } }); } + render() { return this.props.children; } diff --git a/superset-frontend/src/components/Hotkeys.jsx b/superset-frontend/src/components/Hotkeys.jsx index 52d5e4dc3..c0d4707bf 100644 --- a/superset-frontend/src/components/Hotkeys.jsx +++ b/superset-frontend/src/components/Hotkeys.jsx @@ -45,6 +45,7 @@ export default class Hotkeys extends React.PureComponent { } }); } + renderPopover() { const { header, hotkeys } = this.props; return ( @@ -70,6 +71,7 @@ export default class Hotkeys extends React.PureComponent { ); } + render() { return ( ({ showModal: true })); } + renderModal() { return ( { static Next = Next; + static Prev = Prev; + static Item = Item; + static Ellipsis = Ellipsis; + render() { return {this.props.children}; } diff --git a/superset-frontend/src/dashboard/components/BuilderComponentPane.jsx b/superset-frontend/src/dashboard/components/BuilderComponentPane.jsx index c697cdad2..0c9086f70 100644 --- a/superset-frontend/src/dashboard/components/BuilderComponentPane.jsx +++ b/superset-frontend/src/dashboard/components/BuilderComponentPane.jsx @@ -64,6 +64,7 @@ class BuilderComponentPane extends React.PureComponent { ); } + render() { const { topOffset } = this.props; return ( diff --git a/superset-frontend/src/dashboard/components/ColorSchemeControlWrapper.jsx b/superset-frontend/src/dashboard/components/ColorSchemeControlWrapper.jsx index 89d8e4d95..b2e14d103 100644 --- a/superset-frontend/src/dashboard/components/ColorSchemeControlWrapper.jsx +++ b/superset-frontend/src/dashboard/components/ColorSchemeControlWrapper.jsx @@ -41,6 +41,7 @@ class ColorSchemeControlWrapper extends React.PureComponent { this.choices = this.categoricalSchemeRegistry.keys().map(s => [s, s]); this.schemes = this.categoricalSchemeRegistry.getMap(); } + setHover(hovered) { this.setState({ hovered }); } diff --git a/superset-frontend/src/dashboard/components/PropertiesModal.jsx b/superset-frontend/src/dashboard/components/PropertiesModal.jsx index 838aac0e8..fe4ed2e7e 100644 --- a/superset-frontend/src/dashboard/components/PropertiesModal.jsx +++ b/superset-frontend/src/dashboard/components/PropertiesModal.jsx @@ -80,6 +80,7 @@ class PropertiesModal extends React.PureComponent { componentDidMount() { this.fetchDashboardDetails(); } + onColorSchemeChange(value) { this.updateFormState('colorScheme', value); } diff --git a/superset-frontend/src/datasource/DatasourceEditor.jsx b/superset-frontend/src/datasource/DatasourceEditor.jsx index b76370e7e..ce85ef725 100644 --- a/superset-frontend/src/datasource/DatasourceEditor.jsx +++ b/superset-frontend/src/datasource/DatasourceEditor.jsx @@ -280,6 +280,7 @@ export class DatasourceEditor extends React.PureComponent { }; this.props.onChange(datasource, this.state.errors); } + onDatasourceChange(datasource) { this.setState({ datasource }, this.validateAndChange); } diff --git a/superset-frontend/src/explore/components/Control.jsx b/superset-frontend/src/explore/components/Control.jsx index 1683b6ae0..68f0e656f 100644 --- a/superset-frontend/src/explore/components/Control.jsx +++ b/superset-frontend/src/explore/components/Control.jsx @@ -68,12 +68,15 @@ export default class Control extends React.PureComponent { this.onMouseEnter = this.setHover.bind(this, true); this.onMouseLeave = this.setHover.bind(this, false); } + onChange(value, errors) { this.props.actions.setControlValue(this.props.name, value, errors); } + setHover(hovered) { this.setState({ hovered }); } + render() { const { type, hidden } = this.props; if (!type) return null; diff --git a/superset-frontend/src/explore/components/ControlHeader.jsx b/superset-frontend/src/explore/components/ControlHeader.jsx index 579a47ba3..7bc6a3a2e 100644 --- a/superset-frontend/src/explore/components/ControlHeader.jsx +++ b/superset-frontend/src/explore/components/ControlHeader.jsx @@ -75,6 +75,7 @@ export default class ControlHeader extends React.Component { } return null; } + render() { if (!this.props.label) { return null; diff --git a/superset-frontend/src/explore/components/ControlPanelSection.jsx b/superset-frontend/src/explore/components/ControlPanelSection.jsx index c4ea64447..9913b7803 100644 --- a/superset-frontend/src/explore/components/ControlPanelSection.jsx +++ b/superset-frontend/src/explore/components/ControlPanelSection.jsx @@ -42,9 +42,11 @@ export default class ControlPanelSection extends React.Component { this.state = { expanded: this.props.startExpanded }; this.toggleExpand = this.toggleExpand.bind(this); } + toggleExpand() { this.setState({ expanded: !this.state.expanded }); } + renderHeader() { const { label, description, hasErrors } = this.props; return ( diff --git a/superset-frontend/src/explore/components/DisplayQueryButton.jsx b/superset-frontend/src/explore/components/DisplayQueryButton.jsx index 720026115..cc0ba2f87 100644 --- a/superset-frontend/src/explore/components/DisplayQueryButton.jsx +++ b/superset-frontend/src/explore/components/DisplayQueryButton.jsx @@ -90,6 +90,7 @@ export class DisplayQueryButton extends React.PureComponent { this.openPropertiesModal = this.openPropertiesModal.bind(this); this.closePropertiesModal = this.closePropertiesModal.bind(this); } + beforeOpen(resultType) { this.setState({ isLoading: true }); @@ -118,18 +119,23 @@ export class DisplayQueryButton extends React.PureComponent { }); }); } + changeFilterText(event) { this.setState({ filterText: event.target.value }); } + redirectSQLLab() { this.props.onOpenInEditor(this.props.latestQueryFormData); } + openPropertiesModal() { this.setState({ isPropertiesModalOpen: true }); } + closePropertiesModal() { this.setState({ isPropertiesModalOpen: false }); } + renderQueryModalBody() { if (this.state.isLoading) { return ; @@ -157,6 +163,7 @@ export class DisplayQueryButton extends React.PureComponent { } return null; } + renderResultsModalBody() { if (this.state.isLoading) { return ; @@ -172,6 +179,7 @@ export class DisplayQueryButton extends React.PureComponent { } return null; } + renderDataTable(data) { return (
@@ -213,6 +221,7 @@ export class DisplayQueryButton extends React.PureComponent {
); } + renderSamplesModalBody() { if (this.state.isLoading) { return ; @@ -225,6 +234,7 @@ export class DisplayQueryButton extends React.PureComponent { } return null; } + render() { const { animation, chartHeight, slice } = this.props; return ( diff --git a/superset-frontend/src/explore/components/EmbedCodeButton.jsx b/superset-frontend/src/explore/components/EmbedCodeButton.jsx index 0c7083e96..b28c32546 100644 --- a/superset-frontend/src/explore/components/EmbedCodeButton.jsx +++ b/superset-frontend/src/explore/components/EmbedCodeButton.jsx @@ -144,6 +144,7 @@ export default class EmbedCodeButton extends React.Component { ); } + render() { return ( ctrls[k].validationErrors && ctrls[k].validationErrors.length > 0, ); } + renderErrorMessage() { // Returns an error message as a node if any errors are in the store const errors = []; @@ -311,6 +313,7 @@ class ExploreViewContainer extends React.Component { } return errorMessage; } + renderChartContainer() { return ( { const dashboardIds = this.props.dashboards.map( @@ -72,18 +73,22 @@ class SaveModal extends React.Component { } }); } + onSliceNameChange(event) { this.setState({ newSliceName: event.target.value }); } + onDashboardSelectChange(event) { const newDashboardName = event ? event.label : null; const saveToDashboardId = event && typeof event.value === 'number' ? event.value : null; this.setState({ saveToDashboardId, newDashboardName }); } + changeAction(action) { this.setState({ action }); } + saveOrOverwrite(gotodash) { this.setState({ alert: null }); this.props.actions.removeSaveModalAlert(); @@ -117,12 +122,14 @@ class SaveModal extends React.Component { }); this.props.onHide(); } + removeAlert() { if (this.props.alert) { this.props.actions.removeSaveModalAlert(); } this.setState({ alert: null }); } + render() { return ( diff --git a/superset-frontend/src/explore/components/controls/BoundsControl.jsx b/superset-frontend/src/explore/components/controls/BoundsControl.jsx index 0815495b3..f52f43055 100644 --- a/superset-frontend/src/explore/components/controls/BoundsControl.jsx +++ b/superset-frontend/src/explore/components/controls/BoundsControl.jsx @@ -45,6 +45,7 @@ export default class BoundsControl extends React.Component { this.onMinChange = this.onMinChange.bind(this); this.onMaxChange = this.onMaxChange.bind(this); } + onMinChange(event) { this.setState( { @@ -53,6 +54,7 @@ export default class BoundsControl extends React.Component { this.onChange, ); } + onMaxChange(event) { this.setState( { @@ -61,6 +63,7 @@ export default class BoundsControl extends React.Component { this.onChange, ); } + onChange() { const mm = this.state.minMax; const errors = []; @@ -76,6 +79,7 @@ export default class BoundsControl extends React.Component { this.props.onChange([null, null], errors); } } + render() { return (
diff --git a/superset-frontend/src/explore/components/controls/CheckboxControl.jsx b/superset-frontend/src/explore/components/controls/CheckboxControl.jsx index 3d53e53fa..5b14f0d52 100644 --- a/superset-frontend/src/explore/components/controls/CheckboxControl.jsx +++ b/superset-frontend/src/explore/components/controls/CheckboxControl.jsx @@ -38,6 +38,7 @@ export default class CheckboxControl extends React.Component { onChange() { this.props.onChange(!this.props.value); } + renderCheckbox() { return ( ); } + render() { if (this.props.label) { return ( diff --git a/superset-frontend/src/explore/components/controls/CollectionControl.jsx b/superset-frontend/src/explore/components/controls/CollectionControl.jsx index 1c113ae9a..198df6d5c 100644 --- a/superset-frontend/src/explore/components/controls/CollectionControl.jsx +++ b/superset-frontend/src/explore/components/controls/CollectionControl.jsx @@ -68,19 +68,24 @@ export default class CollectionControl extends React.Component { super(props); this.onAdd = this.onAdd.bind(this); } + onChange(i, value) { Object.assign(this.props.value[i], value); this.props.onChange(this.props.value); } + onAdd() { this.props.onChange(this.props.value.concat([this.props.itemGenerator()])); } + onSortEnd({ oldIndex, newIndex }) { this.props.onChange(arrayMove(this.props.value, oldIndex, newIndex)); } + removeItem(i) { this.props.onChange(this.props.value.filter((o, ix) => i !== ix)); } + renderList() { if (this.props.value.length === 0) { return
{this.props.placeholder}
; @@ -126,6 +131,7 @@ export default class CollectionControl extends React.Component { ); } + render() { return (
diff --git a/superset-frontend/src/explore/components/controls/ColorPickerControl.jsx b/superset-frontend/src/explore/components/controls/ColorPickerControl.jsx index 54cf3b3b3..20641d816 100644 --- a/superset-frontend/src/explore/components/controls/ColorPickerControl.jsx +++ b/superset-frontend/src/explore/components/controls/ColorPickerControl.jsx @@ -69,9 +69,11 @@ export default class ColorPickerControl extends React.Component { super(props); this.onChange = this.onChange.bind(this); } + onChange(col) { this.props.onChange(col.rgb); } + renderPopover() { const presetColors = getCategoricalSchemeRegistry() .get() @@ -86,6 +88,7 @@ export default class ColorPickerControl extends React.Component { ); } + render() { const c = this.props.value || { r: 0, g: 0, b: 0, a: 0 }; const colStyle = { diff --git a/superset-frontend/src/explore/components/controls/DateFilterControl.jsx b/superset-frontend/src/explore/components/controls/DateFilterControl.jsx index 285770bb3..9682b7561 100644 --- a/superset-frontend/src/explore/components/controls/DateFilterControl.jsx +++ b/superset-frontend/src/explore/components/controls/DateFilterControl.jsx @@ -238,11 +238,13 @@ class DateFilterControl extends React.Component { componentWillUnmount() { document.removeEventListener('click', this.handleClick); } + onEnter(event) { if (event.key === 'Enter') { this.close(); } } + setCustomRange(key, value) { const updatedState = { ...this.state, [key]: value }; const combinedValue = [ @@ -252,6 +254,7 @@ class DateFilterControl extends React.Component { ].join(' '); this.setState(getStateFromCustomRange(combinedValue)); } + setCustomStartEnd(key, value) { const closeCalendar = (key === 'since' && this.state.sinceViewMode === 'days') || @@ -265,9 +268,11 @@ class DateFilterControl extends React.Component { untilViewMode: closeCalendar ? 'days' : this.state.untilViewMode, }); } + setTypeCustomRange() { this.setState({ type: TYPES.CUSTOM_RANGE }); } + setTypeCustomStartEnd() { this.setState({ type: TYPES.CUSTOM_START_END }); } @@ -325,18 +330,21 @@ class DateFilterControl extends React.Component { this.refs.trigger.hide(); this.setState({ showSinceCalendar: false, showUntilCalendar: false }); } + isValidSince(date) { return ( !isValidMoment(this.state.until) || date <= moment(this.state.until, MOMENT_FORMAT) ); } + isValidUntil(date) { return ( !isValidMoment(this.state.since) || date >= moment(this.state.since, MOMENT_FORMAT) ); } + toggleCalendar(key) { const nextState = {}; if (key === 'showSinceCalendar') { @@ -352,6 +360,7 @@ class DateFilterControl extends React.Component { } this.setState(nextState); } + renderInput(props, key) { return ( @@ -372,6 +381,7 @@ class DateFilterControl extends React.Component { ); } + renderPopover() { const grainOptions = TIME_GRAIN_OPTIONS.map(grain => ( ); } + render() { const timeRange = this.props.value || defaultProps.value; return ( diff --git a/superset-frontend/src/explore/components/controls/FilterBoxItemControl.jsx b/superset-frontend/src/explore/components/controls/FilterBoxItemControl.jsx index 5a82c39fe..237174ced 100644 --- a/superset-frontend/src/explore/components/controls/FilterBoxItemControl.jsx +++ b/superset-frontend/src/explore/components/controls/FilterBoxItemControl.jsx @@ -95,9 +95,11 @@ export default class FilterBoxItemControl extends React.Component { this.onChange = this.onChange.bind(this); this.onControlChange = this.onControlChange.bind(this); } + onChange() { this.props.onChange(this.state); } + onControlChange(attr, value) { let typedValue = value; const { column: selectedColumnName, multiple } = this.state; @@ -122,10 +124,13 @@ export default class FilterBoxItemControl extends React.Component { } this.setState({ [attr]: typedValue }, this.onChange); } + setType() {} + textSummary() { return this.state.column || 'N/A'; } + renderForm() { return (
@@ -257,6 +262,7 @@ export default class FilterBoxItemControl extends React.Component {
); } + renderPopover() { return ( @@ -264,6 +270,7 @@ export default class FilterBoxItemControl extends React.Component { ); } + render() { return ( diff --git a/superset-frontend/src/explore/components/controls/FixedOrMetricControl.jsx b/superset-frontend/src/explore/components/controls/FixedOrMetricControl.jsx index 299960856..6c8edfc4d 100644 --- a/superset-frontend/src/explore/components/controls/FixedOrMetricControl.jsx +++ b/superset-frontend/src/explore/components/controls/FixedOrMetricControl.jsx @@ -66,6 +66,7 @@ export default class FixedOrMetricControl extends React.Component { metricValue: type === controlTypes.metric ? value : null, }; } + onChange() { this.props.onChange({ type: this.state.type, @@ -75,12 +76,15 @@ export default class FixedOrMetricControl extends React.Component { : this.state.metricValue, }); } + setType(type) { this.setState({ type }, this.onChange); } + setFixedValue(fixedValue) { this.setState({ fixedValue }, this.onChange); } + setMetric(metricValue) { this.setState({ metricValue }, this.onChange); } diff --git a/superset-frontend/src/explore/components/controls/SpatialControl.jsx b/superset-frontend/src/explore/components/controls/SpatialControl.jsx index 21077053a..9cbfa45c6 100644 --- a/superset-frontend/src/explore/components/controls/SpatialControl.jsx +++ b/superset-frontend/src/explore/components/controls/SpatialControl.jsx @@ -70,9 +70,11 @@ export default class SpatialControl extends React.Component { this.onChange = this.onChange.bind(this); this.renderReverseCheckbox = this.renderReverseCheckbox.bind(this); } + componentDidMount() { this.onChange(); } + onChange() { const { type } = this.state; const value = { type }; @@ -101,18 +103,22 @@ export default class SpatialControl extends React.Component { this.setState({ value, errors }); this.props.onChange(value, errors); } + setType(type) { this.setState({ type }, this.onChange); } + close() { this.refs.trigger.hide(); } + toggleCheckbox() { this.setState( { reverseCheckbox: !this.state.reverseCheckbox }, this.onChange, ); } + renderLabelContent() { if (this.state.errors.length > 0) { return 'N/A'; @@ -128,6 +134,7 @@ export default class SpatialControl extends React.Component { } return null; } + renderSelect(name, type) { return ( ); } + renderReverseCheckbox() { return ( @@ -155,6 +163,7 @@ export default class SpatialControl extends React.Component { ); } + renderPopover() { return ( @@ -219,6 +228,7 @@ export default class SpatialControl extends React.Component { ); } + render() { return (
diff --git a/superset-frontend/src/explore/components/controls/TextAreaControl.jsx b/superset-frontend/src/explore/components/controls/TextAreaControl.jsx index 7ebe02fac..6ce32f25a 100644 --- a/superset-frontend/src/explore/components/controls/TextAreaControl.jsx +++ b/superset-frontend/src/explore/components/controls/TextAreaControl.jsx @@ -68,9 +68,11 @@ export default class TextAreaControl extends React.Component { onControlChange(event) { this.props.onChange(event.target.value); } + onAceChange(value) { this.props.onChange(value); } + renderEditor(inModal = false) { const value = this.props.value || ''; if (this.props.language) { @@ -103,6 +105,7 @@ export default class TextAreaControl extends React.Component { ); } + renderModalBody() { return (
@@ -111,6 +114,7 @@ export default class TextAreaControl extends React.Component {
); } + render() { const controlHeader = ; return ( diff --git a/superset-frontend/src/explore/components/controls/TextControl.tsx b/superset-frontend/src/explore/components/controls/TextControl.tsx index 7dbf634ea..0f0caf33f 100644 --- a/superset-frontend/src/explore/components/controls/TextControl.tsx +++ b/superset-frontend/src/explore/components/controls/TextControl.tsx @@ -36,6 +36,7 @@ export default class TextControl extends React.Component { super(props); this.onChange = this.onChange.bind(this); } + onChange(event: any) { let { value } = event.target; @@ -59,6 +60,7 @@ export default class TextControl extends React.Component { } this.props.onChange(value, errors); } + render() { const { value: rawValue } = this.props; const value = diff --git a/superset-frontend/src/explore/components/controls/TimeSeriesColumnControl.jsx b/superset-frontend/src/explore/components/controls/TimeSeriesColumnControl.jsx index dda54788f..ecd85f0dd 100644 --- a/superset-frontend/src/explore/components/controls/TimeSeriesColumnControl.jsx +++ b/superset-frontend/src/explore/components/controls/TimeSeriesColumnControl.jsx @@ -102,29 +102,39 @@ export default class TimeSeriesColumnControl extends React.Component { this.state = state; this.onChange = this.onChange.bind(this); } + onChange() { this.props.onChange(this.state); } + onSelectChange(attr, opt) { this.setState({ [attr]: opt.value }, this.onChange); } + onTextInputChange(attr, event) { this.setState({ [attr]: event.target.value }, this.onChange); } + onCheckboxChange(attr, value) { this.setState({ [attr]: value }, this.onChange); } + onBoundsChange(bounds) { this.setState({ bounds }, this.onChange); } + onYAxisBoundsChange(yAxisBounds) { this.setState({ yAxisBounds }, this.onChange); } + setType() {} + textSummary() { return `${this.state.label}`; } + edit() {} + formRow(label, tooltip, ttLabel, control) { return ( @@ -140,6 +150,7 @@ export default class TimeSeriesColumnControl extends React.Component { ); } + renderPopover() { return ( @@ -297,6 +308,7 @@ export default class TimeSeriesColumnControl extends React.Component { ); } + render() { return ( diff --git a/superset-frontend/src/explore/components/controls/ViewportControl.jsx b/superset-frontend/src/explore/components/controls/ViewportControl.jsx index 27f1b7afe..9aa6be166 100644 --- a/superset-frontend/src/explore/components/controls/ViewportControl.jsx +++ b/superset-frontend/src/explore/components/controls/ViewportControl.jsx @@ -60,12 +60,14 @@ export default class ViewportControl extends React.Component { super(props); this.onChange = this.onChange.bind(this); } + onChange(ctrl, value) { this.props.onChange({ ...this.props.value, [ctrl]: value, }); } + renderTextControl(ctrl) { return (
@@ -78,6 +80,7 @@ export default class ViewportControl extends React.Component {
); } + renderPopover() { return ( @@ -85,6 +88,7 @@ export default class ViewportControl extends React.Component { ); } + renderLabel() { if (this.props.value.longitude && this.props.value.latitude) { return `${decimal2sexagesimal( @@ -93,6 +97,7 @@ export default class ViewportControl extends React.Component { } return 'N/A'; } + render() { return (
diff --git a/superset-frontend/src/profile/components/CreatedContent.tsx b/superset-frontend/src/profile/components/CreatedContent.tsx index db9a2adca..b8335bfb2 100644 --- a/superset-frontend/src/profile/components/CreatedContent.tsx +++ b/superset-frontend/src/profile/components/CreatedContent.tsx @@ -47,6 +47,7 @@ class CreatedContent extends React.PureComponent { /> ); } + renderDashboardTable() { const mutator = (data: Dashboard[]) => data.map(dash => ({ @@ -65,6 +66,7 @@ class CreatedContent extends React.PureComponent { /> ); } + render() { return (
diff --git a/superset-frontend/src/profile/components/Favorites.tsx b/superset-frontend/src/profile/components/Favorites.tsx index 4d31b0b69..eb4622bf8 100644 --- a/superset-frontend/src/profile/components/Favorites.tsx +++ b/superset-frontend/src/profile/components/Favorites.tsx @@ -48,6 +48,7 @@ export default class Favorites extends React.PureComponent { /> ); } + renderDashboardTable() { const mutator = (data: Dashboard[]) => data.map(dash => ({ @@ -66,6 +67,7 @@ export default class Favorites extends React.PureComponent { /> ); } + render() { return (
diff --git a/superset-frontend/src/utils/DebouncedMessageQueue.js b/superset-frontend/src/utils/DebouncedMessageQueue.js index 2b6293c8b..031963dda 100644 --- a/superset-frontend/src/utils/DebouncedMessageQueue.js +++ b/superset-frontend/src/utils/DebouncedMessageQueue.js @@ -31,10 +31,12 @@ class DebouncedMessageQueue { this.trigger = debounce(this.trigger.bind(this), this.delayThrehold); this.callback = callback; } + append(eventData) { this.queue.push(eventData); this.trigger(); } + trigger() { if (this.queue.length > 0) { const events = this.queue.splice(0, this.sizeThreshold); diff --git a/superset-frontend/src/views/CRUD/data/database/DatabaseModal.tsx b/superset-frontend/src/views/CRUD/data/database/DatabaseModal.tsx index 50b8723d0..b7827bfcc 100644 --- a/superset-frontend/src/views/CRUD/data/database/DatabaseModal.tsx +++ b/superset-frontend/src/views/CRUD/data/database/DatabaseModal.tsx @@ -230,7 +230,7 @@ const DatabaseModal: FunctionComponent = ({ }; const onTextChange = (event: React.ChangeEvent) => { - const target = event.target; + const { target } = event; const data = { database_name: db ? db.database_name : '', sqlalchemy_uri: db ? db.sqlalchemy_uri : '', diff --git a/superset-frontend/src/visualizations/FilterBox/FilterBox.jsx b/superset-frontend/src/visualizations/FilterBox/FilterBox.jsx index 79f42ef26..51dfc417c 100644 --- a/superset-frontend/src/visualizations/FilterBox/FilterBox.jsx +++ b/superset-frontend/src/visualizations/FilterBox/FilterBox.jsx @@ -163,6 +163,7 @@ class FilterBox extends React.Component { this.props.onChange(selectedValues, false); }); } + changeFilter(filter, options) { const fltr = TIME_FILTER_MAP[filter] || filter; let vals = null; @@ -320,6 +321,7 @@ class FilterBox extends React.Component { } return datasourceFilters; } + renderSelect(filterConfig) { const { filtersChoices } = this.props; const { selectedValues } = this.state;