Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(explore): convert ControlPanelsContainer to typescript #13221

Merged
merged 18 commits into from
Feb 28, 2021

Conversation

ktmud
Copy link
Member

@ktmud ktmud commented Feb 18, 2021

SUMMARY

Convert ControlPanelsContainer and some other related components to TypeScript.

Big refactoring are coming to chart controls and the Explore page, in order to support reading query results in controls, which is needed for things like ad-hoc column formatting in table chart.

Also did some refactoring to redo #12782 and #12609 . See comments for details.

Upgraded superset-ui to v0.17.11 to bring in:
apache-superset/superset-ui#962
apache-superset/superset-ui#969

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

N/A

There should be no visible change.

TEST PLAN

CI and manual testing the chart control area.

ADDITIONAL INFORMATION

export const REMOVE_CONTROL_PANEL_ALERT = 'REMOVE_CONTROL_PANEL_ALERT';
export function removeControlPanelAlert() {
return { type: REMOVE_CONTROL_PANEL_ALERT };
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleaning up dead code.

alert-deprecated

This is the alert this action is trying to clear, which we are not using anymore.

@@ -161,29 +178,39 @@ class ControlPanelsContainer extends React.Component {
validationErrors={validationErrors}
actions={actions}
formData={provideFormDataToProps ? formData : null}
datasource={formData?.datasource}
Copy link
Member Author

@ktmud ktmud Feb 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this exposed datasource prop from #12609 since it's already available in formData, plus The typing would not conform with datasource for DatasourceControl, which uses the assigns datasource prop with the whole metadata of a datasource in mapStateToProps.

cc @pkdotson @zhaoyongjie

@junlincc junlincc added the explore:control Related to the controls panel of Explore label Feb 18, 2021
@junlincc
Copy link
Member

yeah, you are getting ready to work on dynamic controls thanks! ♥️

@ktmud
Copy link
Member Author

ktmud commented Feb 20, 2021

Moved debounce delay updates to another PR: #13250

Will rebase once merged.

name: string;
onChange: (timeRange: string) => void;
value?: string;
endpoints?: TimeRangeEndpoints;
datasource?: string;
datasource?: DatasourceMeta;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will update the shared control to pass in datasource object instead of datasource string from form_data.

@@ -270,7 +262,7 @@ class AdhocFilterControl extends React.Component {
optionsForSelect(props) {
const options = [
...props.columns,
...[...(props.formData.metrics || []), props.formData.metric].map(
...[...(props.selectedMetrics || [])].map(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is used for allowing selecting adhoc metrics in adhoc filters, but it has stopping working:
#13249

The new selectedMetrics will be added by a superset-ui PR.

const { value } = event.target as HTMLInputElement;
this.setState({ value }, () => {
this.debouncedOnChange(value);
});
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did more refactoring based on: #13211 (comment)

@@ -226,6 +227,7 @@ module.exports = {
'no-mixed-operators': 0,
'no-multi-assign': 0,
'no-multi-spaces': 0,
'no-nested-ternary': 0,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disabling as we have seen fairly often nested-ternary in TypeScript extends. It should not be that hard to understand the code with prettier's help.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nested ternary was used in this code:

        const controlName =
          typeof item === 'string'
            ? item
            : item && 'name' in item
            ? item.name
            : null;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm a fan of nested ternaries when used sparingly. however, couldn't this be simplified to:

        const controlName =
          typeof item === 'string'
            ? item
            : (item || {})?.name ?? null;

or something like that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if that's really cleaner, but it doesn't use a nested ternary

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'name' in item is needed for type inference so to avoid forced type conversion as item can be of many types, otherwise this could also be as simple as item?.name || item || null.

Here's the error with your approach:

Screen Shot 2021-02-25 at 6 10 55 PM

@codecov-io
Copy link

codecov-io commented Feb 24, 2021

Codecov Report

Merging #13221 (0af0aab) into master (b4ca39c) will decrease coverage by 4.39%.
The diff coverage is 84.76%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #13221      +/-   ##
==========================================
- Coverage   77.12%   72.73%   -4.40%     
==========================================
  Files         894      595     -299     
  Lines       45672    21247   -24425     
  Branches     5492     5490       -2     
==========================================
- Hits        35223    15453   -19770     
+ Misses      10325     5668    -4657     
- Partials      124      126       +2     
Flag Coverage Δ
cypress 57.69% <81.11%> (-0.40%) ⬇️
hive ?
javascript 62.48% <58.09%> (+0.08%) ⬆️
mysql ?
postgres ?
presto ?
python ?
sqlite ?

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
superset-frontend/src/constants.ts 100.00% <ø> (ø)
...nd/src/explore/components/ExploreViewContainer.jsx 78.04% <ø> (-0.14%) ⬇️
.../explore/components/controls/CollectionControl.jsx 45.45% <ø> (+3.78%) ⬆️
.../controls/MetricControl/AdhocMetricEditPopover.jsx 79.54% <ø> (+0.44%) ⬆️
...nents/controls/MetricControl/AdhocMetricOption.jsx 100.00% <ø> (ø)
...ntrols/MetricControl/AdhocMetricPopoverTrigger.tsx 94.73% <ø> (ø)
...uperset-frontend/src/explore/controlUtils/index.js 95.41% <ø> (ø)
superset-frontend/src/explore/controls.jsx 27.16% <0.00%> (+0.33%) ⬆️
...et-frontend/src/explore/reducers/exploreReducer.js 36.23% <0.00%> (-8.77%) ⬇️
...ents/controls/FilterControl/AdhocFilterControl.jsx 60.00% <50.00%> (+0.90%) ⬆️
... and 318 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b4ca39c...430874c. Read the comment docs.

Copy link
Member Author

@ktmud ktmud left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@villebro @pkdotson @zhaoyongjie @kgabryje could you take a look at this when you have time?

Thanks!

@@ -28,7 +28,7 @@ describe('Visualization > Pivot Table', () => {
adhoc_filters: [],
groupby: ['name'],
columns: ['state'],
row_limit: 50000,
row_limit: 5000,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reduce row limit to speed up the test (a little bit)

// for direct column select controls
controlState.valueKey === 'column_name' ||
// for all other controls
'columns' in controlState
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of check control types, I check whether the control uses column select.

controls: explore.controls,
exploreState: explore,
};
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move to inline function to use inferred types.

@@ -69,12 +69,6 @@ export default class CollectionControl extends React.Component {
this.onAdd = this.onAdd.bind(this);
}

componentDidUpdate(prevProps) {
if (prevProps.datasource.name !== this.props.datasource.name) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one does not work anyway (i.e. change datasource will not reset Time-series Table columns, and the filters collection in FilterBox) since previously props.datasource is passed as a string.

I don't plan to implement this reset because these control values should not be reset when changing datasource.

frame === 'No filter'
guessedFrame === 'Common' ||
guessedFrame === 'Calendar' ||
guessedFrame === 'No filter'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Always use guessedFrame to tooltip and actual time range display because when passing in a new value and the popover is not open, the current frame may be inconsistent with the actual value.

This makes sure Last week is always displayed in the pill instead of tooltip.

@@ -123,9 +123,6 @@ export default class AdhocMetricEditPopover extends React.PureComponent {
adhocMetricLabel: this.state.adhocMetric?.getDefaultLabel(),
});
}
if (prevProps.datasource !== this.props.datasource) {
this.props.onChange(null);
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean up the datasource prop from adhoc metric popovers as they don't seem to affect the ability of the controls to reset values when changing datasource.

@pkdotson do you remember what was these for when you added them?

@@ -55,12 +55,7 @@ export const HAVING_OPERATORS = [
OPERATORS['>='],
OPERATORS['<='],
];
export const MULTI_OPERATORS = new Set([
OPERATORS.in,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OPERATORS.in and OPERATORS['not in'] are undefined, as identified by converting to typescript, so cleaning them up. AchocFilter already always convert the operator into uppercase.

formData[controlName] = control.value;
});
return formData;
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Split functions in controlUtils to TypeScript one by one...

action.datasource.type !== state.datasource.type
) {
newFormData.time_range = DEFAULT_TIME_RANGE;
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of checking control types, I now check whether a control depends on datasource columns.

}
});
}
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the resetting logic to reducers as each of these setControlValue call here will cause another re-rendering.

@ktmud
Copy link
Member Author

ktmud commented Feb 25, 2021

Close to re-trigger full CI to fix test coverage report.

@ktmud ktmud closed this Feb 25, 2021
@ktmud ktmud reopened this Feb 25, 2021
@ktmud
Copy link
Member Author

ktmud commented Feb 26, 2021

I also noticed a few usages of type assertion throughout. I assume they were there for a good reason, but it makes me a bit nervous. Maybe go through one more time to ensure they're all needed?

Good call. I did a sweep and managed to find one place that I could optimize: caf3b60

@ktmud ktmud merged commit 3c62069 into apache:master Feb 28, 2021
@ktmud ktmud deleted the ts-control-panel branch February 28, 2021 18:10
@michael-s-molina
Copy link
Member

@ktmud I found this typescript error:

Screen Shot 2021-03-01 at 8 17 06 AM

Screen Shot 2021-03-01 at 8 17 23 AM

Screen Shot 2021-03-01 at 8 17 46 AM

It's happening because tooltip is declared as a string in InfoTooltipWithTrigger but the description is declared as ReactNode in ControlPanelSectionConfig.

I was going to fix it, but I was afraid of not having all the necessary context since this touches superset-ui plugins.

Shouldn't CI catch this?

@ktmud
Copy link
Member Author

ktmud commented Mar 1, 2021

@michael-s-molina Did you run npm install or was your superset-ui/chart-controls linked to a different version? CI didn't catch it because it was actually working?

I'm pretty sure this was updated here: https://github.com/apache-superset/superset-ui/pull/962/files#diff-efc1b32a915b3738e7689b97eab6576ac7b206bc95d46e1ecaac6c8646287a65R27

The superset-ui change was supposed to be added in this PR but another PR has upgraded them anyway.

@michael-s-molina
Copy link
Member

@ktmud Strangely I ran npm install and it didn't work. It only worked after deleting @superset-ui in node_modules and reinstalling it. At least it's working now. Thanks.

allanco91 pushed a commit to allanco91/superset that referenced this pull request May 21, 2021
@mistercrunch mistercrunch added 🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels 🚢 1.2.0 labels Mar 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels explore:control Related to the controls panel of Explore size/XL 🚢 1.2.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants