From c1b3a49db1e4802d84562f8e9d6ac2c3db20655d Mon Sep 17 00:00:00 2001 From: Jesse Yang Date: Sat, 21 Mar 2020 00:14:29 -0700 Subject: [PATCH] feat: add timeRangeFixed and increase font size for Big Number chart --- superset-frontend/package-lock.json | 19 ++++-- superset-frontend/package.json | 2 +- .../components/ControlPanelsContainer.jsx | 7 +- .../{BigNumber.js => BigNumber.jsx} | 3 +- superset-frontend/src/explore/controlUtils.js | 66 ++++++++----------- superset-frontend/src/explore/controls.jsx | 42 ++++++++---- superset/viz.py | 2 + 7 files changed, 85 insertions(+), 56 deletions(-) rename superset-frontend/src/explore/controlPanels/{BigNumber.js => BigNumber.jsx} (97%) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index ca4ca8e8b343c..6a332cf1c1b5c 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -8113,13 +8113,14 @@ } }, "@superset-ui/legacy-preset-chart-big-number": { - "version": "0.11.15", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-preset-chart-big-number/-/legacy-preset-chart-big-number-0.11.15.tgz", - "integrity": "sha512-Nd1ezgdzBfHIxUlGbYZ8Je3rklHvlygq1LE2dYGCKuOQkSDSpGLHU9Y9CMDOkurnmC46hMIxNe3DkVtY7xzTNQ==", + "version": "0.11.21", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-preset-chart-big-number/-/legacy-preset-chart-big-number-0.11.21.tgz", + "integrity": "sha512-LvDrCfpNTUGaXFUvrd1vHFJqPsBZlva97Z/Wy8izn7ZRv7PrrsvxJ584mh+JBfPg2YiklYB7E2F18MN1NaJEmw==", "requires": { "@data-ui/xy-chart": "^0.0.84", + "@types/d3-color": "^1.2.2", + "@types/shortid": "^0.0.29", "d3-color": "^1.2.3", - "prop-types": "^15.6.2", "shortid": "^2.2.14" } }, @@ -8540,6 +8541,11 @@ "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-2.0.0.tgz", "integrity": "sha512-rGqfPVowNDTszSFvwoZIXvrPG7s/qKzm9piCRIH6xwTTRu7pPZ3ootULFnPkTt74B6i5lN0FpLQL24qGOw1uZA==" }, + "@types/d3-color": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-1.2.2.tgz", + "integrity": "sha512-6pBxzJ8ZP3dYEQ4YjQ+NVbQaOflfgXq/JbDiS99oLobM2o72uAST4q6yPxHv6FOTCRC/n35ktuo8pvw/S4M7sw==" + }, "@types/d3-format": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-1.3.1.tgz", @@ -8843,6 +8849,11 @@ "@types/react": "*" } }, + "@types/shortid": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/shortid/-/shortid-0.0.29.tgz", + "integrity": "sha1-gJPuBBam4r8qpjOBCRFLP7/6Dps=" + }, "@types/sizzle": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 81504191f4371..01597d607d628 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -81,7 +81,7 @@ "@superset-ui/legacy-plugin-chart-treemap": "^0.11.15", "@superset-ui/legacy-plugin-chart-word-cloud": "^0.11.15", "@superset-ui/legacy-plugin-chart-world-map": "^0.11.15", - "@superset-ui/legacy-preset-chart-big-number": "^0.11.15", + "@superset-ui/legacy-preset-chart-big-number": "^0.11.21", "@superset-ui/legacy-preset-chart-deckgl": "^0.2.3", "@superset-ui/legacy-preset-chart-nvd3": "^0.11.15", "@superset-ui/number-format": "^0.12.10", diff --git a/superset-frontend/src/explore/components/ControlPanelsContainer.jsx b/superset-frontend/src/explore/components/ControlPanelsContainer.jsx index e377ab00ddbac..2e0affdc3a164 100644 --- a/superset-frontend/src/explore/components/ControlPanelsContainer.jsx +++ b/superset-frontend/src/explore/components/ControlPanelsContainer.jsx @@ -97,6 +97,12 @@ class ControlPanelsContainer extends React.Component { renderControl(name, config, lookupControlData) { const { actions, controls, exploreState, form_data: formData } = this.props; + const { visibility } = config; + + // if visibility check says the config is not visible, don't render it + if (visibility && !visibility.call(config, this.props)) { + return null; + } // Looking to find mapStateToProps override for this viz type const controlPanelConfig = @@ -179,7 +185,6 @@ class ControlPanelsContainer extends React.Component { // is not specified directly. Have to look up the config from // centralized configs. const name = controlItem; - return this.renderControl(name, controlConfigs[name], true); } return null; diff --git a/superset-frontend/src/explore/controlPanels/BigNumber.js b/superset-frontend/src/explore/controlPanels/BigNumber.jsx similarity index 97% rename from superset-frontend/src/explore/controlPanels/BigNumber.js rename to superset-frontend/src/explore/controlPanels/BigNumber.jsx index 4a708f92b8078..940eae8caa80a 100644 --- a/superset-frontend/src/explore/controlPanels/BigNumber.js +++ b/superset-frontend/src/explore/controlPanels/BigNumber.jsx @@ -31,8 +31,9 @@ export default { expanded: true, controlSetRows: [ ['compare_lag', 'compare_suffix'], - ['y_axis_format', null], + ['y_axis_format'], ['show_trend_line', 'start_y_axis_at_zero'], + ['time_range_fixed'], ], }, { diff --git a/superset-frontend/src/explore/controlUtils.js b/superset-frontend/src/explore/controlUtils.js index 361e162c2e83d..f4506a8412b8a 100644 --- a/superset-frontend/src/explore/controlUtils.js +++ b/superset-frontend/src/explore/controlUtils.js @@ -17,8 +17,8 @@ * under the License. */ import { getChartControlPanelRegistry } from '@superset-ui/chart'; -import controls from './controls'; -import * as sections from './controlPanels/sections'; +import { controls as SHARED_CONTROLS } from './controls'; +import * as SECTIONS from './controlPanels/sections'; export function getFormDataFromControls(controlsState) { const formData = {}; @@ -45,38 +45,36 @@ export function validateControl(control) { return control; } -function isGlobalControl(controlKey) { - return controlKey in controls; +function findCustomControl(controlPanelSections, controlKey) { + // find custom control in `controlPanelSections` and apply `controlOverrides` if needed. + for (const section of controlPanelSections) { + for (const controlArr of section.controlSetRows) { + for (const control of controlArr) { + if (control != null && typeof control === 'object') { + if (control.config && control.name === controlKey) { + return control.config; + } + } + } + } + } + return null; } export function getControlConfig(controlKey, vizType) { - // Gets the control definition, applies overrides, and executes - // the mapStatetoProps const controlPanelConfig = getChartControlPanelRegistry().get(vizType) || {}; const { controlOverrides = {}, controlPanelSections = [], } = controlPanelConfig; - if (!isGlobalControl(controlKey)) { - for (const section of controlPanelSections) { - for (const controlArr of section.controlSetRows) { - for (const control of controlArr) { - if (control != null && typeof control === 'object') { - if (control.config && control.name === controlKey) { - return { - ...control.config, - ...controlOverrides[controlKey], - }; - } - } - } - } - } - } + const config = + controlKey in SHARED_CONTROLS + ? SHARED_CONTROLS[controlKey] + : findCustomControl(controlPanelSections, controlKey); return { - ...controls[controlKey], + ...config, ...controlOverrides[controlKey], }; } @@ -150,31 +148,25 @@ export function sectionsToRender(vizType, datasourceType) { controlPanelSections = [], } = controlPanelConfig; - const sectionsCopy = { ...sections }; + const sections = { ...SECTIONS }; Object.entries(sectionOverrides).forEach(([section, overrides]) => { if (typeof overrides === 'object' && overrides.constructor === Object) { - sectionsCopy[section] = { - ...sectionsCopy[section], + sections[section] = { + ...sections[section], ...overrides, }; } else { - sectionsCopy[section] = overrides; + sections[section] = overrides; } }); - const { - datasourceAndVizType, - sqlaTimeSeries, - druidTimeSeries, - } = sectionsCopy; + const { datasourceAndVizType, sqlaTimeSeries, druidTimeSeries } = sections; + const timeSection = + datasourceType === 'table' ? sqlaTimeSeries : druidTimeSeries; return [] - .concat( - datasourceAndVizType, - datasourceType === 'table' ? sqlaTimeSeries : druidTimeSeries, - controlPanelSections, - ) + .concat(datasourceAndVizType, timeSection, controlPanelSections) .filter(section => section); } diff --git a/superset-frontend/src/explore/controls.jsx b/superset-frontend/src/explore/controls.jsx index b781ec42a4b9b..0c14116fc8294 100644 --- a/superset-frontend/src/explore/controls.jsx +++ b/superset-frontend/src/explore/controls.jsx @@ -843,7 +843,7 @@ export const controls = { type: 'DateFilterControl', freeForm: true, label: TIME_FILTER_LABELS.time_range, - default: t('Last week'), + default: t('Last week'), // this value is translated, but the backend wouldn't understand a translated value? description: t( 'The time range for the visualization. All relative times, e.g. "Last month", ' + '"Last 7 days", "now", etc. are evaluated on the server using the server\'s ' + @@ -857,6 +857,24 @@ export const controls = { }), }, + time_range_fixed: { + type: 'CheckboxControl', + label: t('Fix to selected Time Range'), + description: t( + 'Fix the trend line to the full time range specified in case filtered results do not include the start or end dates', + ), + renderTrigger: true, + visibility(props) { + const { + time_range: timeRange, + viz_type: vizType, + show_trend_line: showTrendLine, + } = props.form_data; + // only display this option when a time range is selected + return timeRange && timeRange !== 'No filter'; + }, + }, + max_bubble_size: { type: 'SelectControl', freeForm: true, @@ -1197,28 +1215,28 @@ export const controls = { label: t('Header Font Size'), renderTrigger: true, clearable: false, - default: 0.3, + default: 0.4, // Values represent the percentage of space a header should take options: [ { label: t('Tiny'), - value: 0.125, + value: 0.2, }, { label: t('Small'), - value: 0.2, + value: 0.3, }, { label: t('Normal'), - value: 0.3, + value: 0.4, }, { label: t('Large'), - value: 0.4, + value: 0.5, }, { label: t('Huge'), - value: 0.5, + value: 0.6, }, ], }, @@ -1228,7 +1246,7 @@ export const controls = { label: t('Subheader Font Size'), renderTrigger: true, clearable: false, - default: 0.125, + default: 0.15, // Values represent the percentage of space a subheader should take options: [ { @@ -1237,19 +1255,19 @@ export const controls = { }, { label: t('Small'), - value: 0.2, + value: 0.15, }, { label: t('Normal'), - value: 0.3, + value: 0.2, }, { label: t('Large'), - value: 0.4, + value: 0.3, }, { label: t('Huge'), - value: 0.5, + value: 0.4, }, ], }, diff --git a/superset/viz.py b/superset/viz.py index 7df94c577862d..f4890ec69b043 100644 --- a/superset/viz.py +++ b/superset/viz.py @@ -484,6 +484,8 @@ def get_df_payload(self, query_obj=None, **kwargs): "form_data": self.form_data, "is_cached": self._any_cache_key is not None, "query": self.query, + "from_dttm": self.from_dttm, + "to_dttm": self.to_dttm, "status": self.status, "stacktrace": stacktrace, "rowcount": len(df.index) if df is not None else 0,