From cb384d051badcc9823f24a6491bcbe3cdb9dee7e Mon Sep 17 00:00:00 2001 From: George Ke Date: Wed, 1 Jun 2016 22:59:06 -0700 Subject: [PATCH] Fix for Not Grouped By on Table View (#544) * fix for default metric in table visualization * better location for form override; covers all parameters * remove dead code, use items instead of iteritems for python 3 --- caravel/forms.py | 799 ++++++++++++++----------- caravel/templates/caravel/explore.html | 4 +- caravel/viz.py | 15 +- 3 files changed, 466 insertions(+), 352 deletions(-) diff --git a/caravel/forms.py b/caravel/forms.py index 4c1b71875..fa9227d43 100644 --- a/caravel/forms.py +++ b/caravel/forms.py @@ -129,122 +129,151 @@ class FormFactory(object): default_groupby = gb_cols[0] if gb_cols else None group_by_choices = self.choicify(gb_cols) # Pool of all the fields that can be used in Caravel - self.field_dict = { - 'viz_type': SelectField( - 'Viz', - default='table', - choices=[(k, v.verbose_name) for k, v in viz_types.items()], - description="The type of visualization to display"), - 'metrics': SelectMultipleSortableField( - 'Metrics', choices=datasource.metrics_combo, - default=[default_metric], - description="One or many metrics to display"), - 'metric': SelectField( - 'Metric', choices=datasource.metrics_combo, - default=default_metric, - description="Chose the metric"), - 'stacked_style': SelectField( - 'Chart Style', choices=self.choicify( - ['stack', 'stream', 'expand']), - default='stack', - description=""), - 'linear_color_scheme': SelectField( - 'Color Scheme', choices=self.choicify([ + field_data = { + 'viz_type': (SelectField, { + "label": "Viz", + "default": 'table', + "choices": [(k, v.verbose_name) for k, v in viz_types.items()], + "description": "The type of visualization to display" + }), + 'metrics': (SelectMultipleSortableField, { + "label": "Metrics", + "choices": datasource.metrics_combo, + "default": [default_metric], + "description": "One or many metrics to display" + }), + 'metric': (SelectField, { + "label": "Metric", + "choices": datasource.metrics_combo, + "default": default_metric, + "description": "Choose the metric" + }), + 'stacked_style': (SelectField, { + "label": "Chart Style", + "choices": self.choicify(['stack', 'stream', 'expand']), + "default": 'stack', + "description": "" + }), + 'linear_color_scheme': (SelectField, { + "label": "Color Scheme", + "choices": self.choicify([ 'fire', 'blue_white_yellow', 'white_black', 'black_white']), - default='blue_white_yellow', - description=""), - 'normalize_across': SelectField( - 'Normalize Across', choices=self.choicify([ + "default": 'blue_white_yellow', + "description": "" + }), + 'normalize_across': (SelectField, { + "label": "Normalize Across", + "choices": self.choicify([ 'heatmap', 'x', 'y']), - default='heatmap', - description=( + "default": 'heatmap', + "description": ( "Color will be rendered based on a ratio " "of the cell against the sum of across this " - "criteria")), - 'horizon_color_scale': SelectField( - 'Color Scale', choices=self.choicify([ - 'series', 'overall', 'change']), - default='series', - description="Defines how the color are attributed."), - 'canvas_image_rendering': SelectField( - 'Rendering', choices=( + "criteria") + }), + 'horizon_color_scale': (SelectField, { + "label": "Color Scale", + "choices": self.choicify(['series', 'overall', 'change']), + "default": 'series', + "description": "Defines how the color are attributed." + }), + 'canvas_image_rendering': (SelectField, { + "label": "Rendering", + "choices": ( ('pixelated', 'pixelated (Sharp)'), ('auto', 'auto (Smooth)'), ), - default='pixelated', - description=( + "default": 'pixelated', + "description": ( "image-rendering CSS attribute of the canvas object that " - "defines how the browser scales up the image")), - 'xscale_interval': SelectField( - 'XScale Interval', choices=self.choicify(range(1, 50)), - default='1', - description=( + "defines how the browser scales up the image") + }), + 'xscale_interval': (SelectField, { + "label": "XScale Interval", + "choices": self.choicify(range(1, 50)), + "default": '1', + "description": ( "Number of step to take between ticks when " - "printing the x scale")), - 'yscale_interval': SelectField( - 'YScale Interval', choices=self.choicify(range(1, 50)), - default='1', - description=( + "printing the x scale") + }), + 'yscale_interval': (SelectField, { + "label": "YScale Interval", + "choices": self.choicify(range(1, 50)), + "default": '1', + "description": ( "Number of step to take between ticks when " - "printing the y scale")), - 'bar_stacked': BetterBooleanField( - 'Stacked Bars', - default=False, - description=""), - 'include_series': BetterBooleanField( - 'Include Series', - default=False, - description="Include series name as an axis"), - 'secondary_metric': SelectField( - 'Color Metric', choices=datasource.metrics_combo, - default=default_metric, - description="A metric to use for color"), - 'country_fieldtype': SelectField( - 'Country Field Type', - default='cca2', - choices=( + "printing the y scale") + }), + 'bar_stacked': (BetterBooleanField, { + "label": "Stacked Bars", + "default": False, + "description": "" + }), + 'include_series': (BetterBooleanField, { + "label": "Include Series", + "default": False, + "description": "Include series name as an axis" + }), + 'secondary_metric': (SelectField, { + "label": "Color Metric", + "choices": datasource.metrics_combo, + "default": default_metric, + "description": "A metric to use for color" + }), + 'country_fieldtype': (SelectField, { + "label": "Country Field Type", + "default": 'cca2', + "choices": ( ('name', 'Full name'), ('cioc', 'code International Olympic Committee (cioc)'), ('cca2', 'code ISO 3166-1 alpha-2 (cca2)'), ('cca3', 'code ISO 3166-1 alpha-3 (cca3)'), ), - description=( + "description": ( "The country code standard that Caravel should expect " - "to find in the [country] column")), - 'groupby': SelectMultipleSortableField( - 'Group by', - choices=self.choicify(datasource.groupby_column_names), - description="One or many fields to group by"), - 'columns': SelectMultipleSortableField( - 'Columns', - choices=self.choicify(datasource.groupby_column_names), - description="One or many fields to pivot as columns"), - 'all_columns': SelectMultipleSortableField( - 'Columns', - choices=self.choicify(datasource.column_names), - description="Columns to display"), - 'all_columns_x': SelectField( - 'X', - choices=self.choicify(datasource.column_names), - description="Columns to display"), - 'all_columns_y': SelectField( - 'Y', - choices=self.choicify(datasource.column_names), - description="Columns to display"), - 'druid_time_origin': FreeFormSelectField( - 'Origin', - choices=( + "to find in the [country] column") + }), + 'groupby': (SelectMultipleSortableField, { + "label": "Group by", + "choices": self.choicify(datasource.groupby_column_names), + "description": "One or many fields to group by" + }), + 'columns': (SelectMultipleSortableField, { + "label": "Columns", + "choices": self.choicify(datasource.groupby_column_names), + "description": "One or many fields to pivot as columns" + }), + 'all_columns': (SelectMultipleSortableField, { + "label": "Columns", + "choices": self.choicify(datasource.column_names), + "description": "Columns to display" + }), + 'all_columns_x': (SelectField, { + "label": "X", + "choices": self.choicify(datasource.column_names), + "description": "Columns to display" + }), + 'all_columns_y': (SelectField, { + "label": "Y", + "choices": self.choicify(datasource.column_names), + "description": "Columns to display" + }), + 'druid_time_origin': (FreeFormSelectField, { + "label": "Origin", + "choices": ( ('', 'default'), ('now', 'now'), ), - default='', - description=( + "default": '', + "description": ( "Defines the origin where time buckets start, " - "accepts natural dates as in 'now', 'sunday' or '1970-01-01'")), - 'granularity': FreeFormSelectField( - 'Time Granularity', default="one day", - choices=self.choicify([ + "accepts natural dates as in 'now', 'sunday' or '1970-01-01'") + }), + 'granularity': (FreeFormSelectField, { + "label": "Time Granularity", + "default": "one day", + "choices": self.choicify([ 'all', '5 seconds', '30 seconds', @@ -255,36 +284,42 @@ class FormFactory(object): '1 day', '7 days', ]), - description=( + "description": ( "The time granularity for the visualization. Note that you " "can type and use simple natural language as in '10 seconds', " - "'1 day' or '56 weeks'")), - 'domain_granularity': SelectField( - 'Domain', default="month", - choices=self.choicify([ + "'1 day' or '56 weeks'") + }), + 'domain_granularity': (SelectField, { + "label": "Domain", + "default": "month", + "choices": self.choicify([ 'hour', 'day', 'week', 'month', 'year', ]), - description=( - "The time unit used for the grouping of blocks")), - 'subdomain_granularity': SelectField( - 'Subdomain', default="day", - choices=self.choicify([ + "description": ( + "The time unit used for the grouping of blocks") + }), + 'subdomain_granularity': (SelectField, { + "label": "Subdomain", + "default": "day", + "choices": self.choicify([ 'min', 'hour', 'day', 'week', 'month', ]), - description=( + "description": ( "The time unit for each block. Should be a smaller unit than " - "domain_granularity. Should be larger or equal to Time Grain")), - 'link_length': FreeFormSelectField( - 'Link Length', default="200", - choices=self.choicify([ + "domain_granularity. Should be larger or equal to Time Grain") + }), + 'link_length': (FreeFormSelectField, { + "label": "Link Length", + "default": "200", + "choices": self.choicify([ '10', '25', '50', @@ -294,10 +329,12 @@ class FormFactory(object): '200', '250', ]), - description="Link length in the force layout"), - 'charge': FreeFormSelectField( - 'Charge', default="-500", - choices=self.choicify([ + "description": "Link length in the force layout" + }), + 'charge': (FreeFormSelectField, { + "label": "Charge", + "default": "-500", + "choices": self.choicify([ '-50', '-75', '-100', @@ -309,32 +346,41 @@ class FormFactory(object): '-2500', '-5000', ]), - description="Charge in the force layout"), - 'granularity_sqla': SelectField( - 'Time Column', - default=datasource.main_dttm_col or datasource.any_dttm_col, - choices=self.choicify(datasource.dttm_cols), - description=( + "description": "Charge in the force layout" + }), + 'granularity_sqla': (SelectField, { + "label": "Time Column", + "default": datasource.main_dttm_col or datasource.any_dttm_col, + "choices": self.choicify(datasource.dttm_cols), + "description": ( "The time column for the visualization. Note that you " "can define arbitrary expression that return a DATETIME " "column in the table editor. Also note that the " "filter bellow is applied against this column or " - "expression")), - 'resample_rule': FreeFormSelectField( - 'Resample Rule', default='', - choices=self.choicify(('1T', '1H', '1D', '7D', '1M', '1AS')), - description=("Pandas resample rule")), - 'resample_how': FreeFormSelectField( - 'Resample How', default='', - choices=self.choicify(('', 'mean', 'sum', 'median')), - description=("Pandas resample how")), - 'resample_fillmethod': FreeFormSelectField( - 'Resample Fill Method', default='', - choices=self.choicify(('', 'ffill', 'bfill')), - description=("Pandas resample fill method")), - 'since': FreeFormSelectField( - 'Since', default="7 days ago", - choices=self.choicify([ + "expression") + }), + 'resample_rule': (FreeFormSelectField, { + "label": "Resample Rule", + "default": '', + "choices": self.choicify(('1T', '1H', '1D', '7D', '1M', '1AS')), + "description": ("Pandas resample rule") + }), + 'resample_how': (FreeFormSelectField, { + "label": "Resample How", + "default": '', + "choices": self.choicify(('', 'mean', 'sum', 'median')), + "description": ("Pandas resample how") + }), + 'resample_fillmethod': (FreeFormSelectField, { + "label": "Resample Fill Method", + "default": '', + "choices": self.choicify(('', 'ffill', 'bfill')), + "description": ("Pandas resample fill method") + }), + 'since': (FreeFormSelectField, { + "label": "Since", + "default": "7 days ago", + "choices": self.choicify([ '1 hour ago', '12 hours ago', '1 day ago', @@ -343,22 +389,25 @@ class FormFactory(object): '90 days ago', '1 year ago' ]), - description=( + "description": ( "Timestamp from filter. This supports free form typing and " - "natural language as in '1 day ago', '28 days' or '3 years'")), - 'until': FreeFormSelectField( - 'Until', default="now", - choices=self.choicify([ + "natural language as in '1 day ago', '28 days' or '3 years'") + }), + 'until': (FreeFormSelectField, { + "label": "Until", + "default": "now", + "choices": self.choicify([ 'now', '1 day ago', '7 days ago', '28 days ago', '90 days ago', '1 year ago']) - ), - 'max_bubble_size': FreeFormSelectField( - 'Max Bubble Size', default="25", - choices=self.choicify([ + }), + 'max_bubble_size': (FreeFormSelectField, { + "label": "Max Bubble Size", + "default": "25", + "choices": self.choicify([ '5', '10', '15', @@ -367,27 +416,28 @@ class FormFactory(object): '75', '100', ]) - ), - 'whisker_options': FreeFormSelectField( - 'Whisker/outlier options', default="Tukey", - description=( + }), + 'whisker_options': (FreeFormSelectField, { + "label": "Whisker/outlier options", + "default": "Tukey", + "description": ( "Determines how whiskers and outliers are calculated."), - choices=self.choicify([ + "choices": self.choicify([ 'Tukey', 'Min/max (no outliers)', '2/98 percentiles', '9/91 percentiles', ]) - ), - 'treemap_ratio': DecimalField( - 'Ratio', - default=0.5 * (1 + math.sqrt(5)), # d3 default, golden ratio - description='Target aspect ratio for treemap tiles.', - ), - 'number_format': FreeFormSelectField( - 'Number format', - default='.3s', - choices=[ + }), + 'treemap_ratio': (DecimalField, { + "label": "Ratio", + "default": 0.5 * (1 + math.sqrt(5)), # d3 default, golden ratio + "description": 'Target aspect ratio for treemap tiles.', + }), + 'number_format': (FreeFormSelectField, { + "label": "Number format", + "default": '.3s', + "choices": [ ('.3s', '".3s" | 12.3k'), ('.3%', '".3%" | 1234543.210%'), ('.4r', '".4r" | 12350'), @@ -395,109 +445,130 @@ class FormFactory(object): ('+,', '"+," | +12,345.4321'), ('$,.2f', '"$,.2f" | $12,345.43'), ], - description="D3 format syntax for numbers " - "https://github.com/mbostock/\n" - "d3/wiki/Formatting"), - - 'row_limit': - FreeFormSelectField( - 'Row limit', - default=config.get("ROW_LIMIT"), - choices=self.choicify( - [10, 50, 100, 250, 500, 1000, 5000, 10000, 50000])), - 'limit': - FreeFormSelectField( - 'Series limit', - choices=self.choicify(self.series_limits), - default=50, - description=( - "Limits the number of time series that get displayed")), - 'rolling_type': SelectField( - 'Rolling', - default='None', - choices=[(s, s) for s in ['None', 'mean', 'sum', 'std', 'cumsum']], - description=( + "description": "D3 format syntax for numbers " + "https: //github.com/mbostock/\n" + "d3/wiki/Formatting" + }), + 'row_limit': (FreeFormSelectField, { + "label": 'Row limit', + "default": config.get("ROW_LIMIT"), + "choices": self.choicify( + [10, 50, 100, 250, 500, 1000, 5000, 10000, 50000]) + }), + 'limit': (FreeFormSelectField, { + "label": 'Series limit', + "choices": self.choicify(self.series_limits), + "default": 50, + "description": ( + "Limits the number of time series that get displayed") + }), + 'rolling_type': (SelectField, { + "label": "Rolling", + "default": 'None', + "choices": [(s, s) for s in ['None', 'mean', 'sum', 'std', 'cumsum']], + "description": ( "Defines a rolling window function to apply, works along " - "with the [Periods] text box")), - 'rolling_periods': IntegerField( - 'Periods', - validators=[validators.optional()], - description=( + "with the [Periods] text box") + }), + 'rolling_periods': (IntegerField, { + "label": "Periods", + "validators": [validators.optional()], + "description": ( "Defines the size of the rolling window function, " - "relative to the time granularity selected")), - 'series': SelectField( - 'Series', choices=group_by_choices, - default=default_groupby, - description=( + "relative to the time granularity selected") + }), + 'series': (SelectField, { + "label": "Series", + "choices": group_by_choices, + "default": default_groupby, + "description": ( "Defines the grouping of entities. " "Each serie is shown as a specific color on the chart and " - "has a legend toggle")), - 'entity': SelectField( - 'Entity', choices=group_by_choices, - default=default_groupby, - description="This define the element to be plotted on the chart"), - 'x': SelectField( - 'X Axis', choices=datasource.metrics_combo, - default=default_metric, - description="Metric assigned to the [X] axis"), - 'y': SelectField( - 'Y Axis', choices=datasource.metrics_combo, - default=default_metric, - description="Metric assigned to the [Y] axis"), - 'size': SelectField( - 'Bubble Size', - default=default_metric, - choices=datasource.metrics_combo), - 'url': TextField( - 'URL', - description=( + "has a legend toggle") + }), + 'entity': (SelectField, { + "label": "Entity", + "choices": group_by_choices, + "default": default_groupby, + "description": "This define the element to be plotted on the chart" + }), + 'x': (SelectField, { + "label": "X Axis", + "choices": datasource.metrics_combo, + "default": default_metric, + "description": "Metric assigned to the [X] axis" + }), + 'y': (SelectField, { + "label": "Y Axis", + "choices": datasource.metrics_combo, + "default": default_metric, + "description": "Metric assigned to the [Y] axis" + }), + 'size': (SelectField, { + "label": 'Bubble Size', + "default": default_metric, + "choices": datasource.metrics_combo + }), + 'url': (TextField, { + "label": "URL", + "description": ( "The URL, this field is templated, so you can integrate " "{{ width }} and/or {{ height }} in your URL string." ), - default='https://www.youtube.com/embed/JkI5rg_VcQ4',), - 'where': TextField( - 'Custom WHERE clause', default='', - description=( + "default": 'https: //www.youtube.com/embed/JkI5rg_VcQ4', + }), + 'where': (TextField, { + "label": "Custom WHERE clause", + "default": '', + "description": ( "The text in this box gets included in your query's WHERE " "clause, as an AND to other criteria. You can include " "complex expression, parenthesis and anything else " - "supported by the backend it is directed towards.")), - 'having': TextField( - 'Custom HAVING clause', default='', - description=( + "supported by the backend it is directed towards.") + }), + 'having': (TextField, { + "label": "Custom HAVING clause", + "default": '', + "description": ( "The text in this box gets included in your query's HAVING" " clause, as an AND to other criteria. You can include " "complex expression, parenthesis and anything else " - "supported by the backend it is directed towards.")), - 'compare_lag': TextField( - 'Comparison Period Lag', - description=( + "supported by the backend it is directed towards.") + }), + 'compare_lag': (TextField, { + "label": "Comparison Period Lag", + "description": ( "Based on granularity, number of time periods to " - "compare against")), - 'compare_suffix': TextField( - 'Comparison suffix', - description="Suffix to apply after the percentage display"), - 'table_timestamp_format': FreeFormSelectField( - 'Table Timestamp Format', - default='smart_date', - choices=TIMESTAMP_CHOICES, - description="Timestamp Format"), - 'series_height': FreeFormSelectField( - 'Series Height', - default=25, - choices=self.choicify([10, 25, 40, 50, 75, 100, 150, 200]), - description="Pixel height of each series"), - 'x_axis_format': FreeFormSelectField( - 'X axis format', - default='smart_date', - choices=TIMESTAMP_CHOICES, - description="D3 format syntax for y axis " - "https://github.com/mbostock/\n" - "d3/wiki/Formatting"), - 'y_axis_format': FreeFormSelectField( - 'Y axis format', - default='.3s', - choices=[ + "compare against") + }), + 'compare_suffix': (TextField, { + "label": "Comparison suffix", + "description": "Suffix to apply after the percentage display" + }), + 'table_timestamp_format': (FreeFormSelectField, { + "label": "Table Timestamp Format", + "default": 'smart_date', + "choices": TIMESTAMP_CHOICES, + "description": "Timestamp Format" + }), + 'series_height': (FreeFormSelectField, { + "label": "Series Height", + "default": 25, + "choices": self.choicify([10, 25, 40, 50, 75, 100, 150, 200]), + "description": "Pixel height of each series" + }), + 'x_axis_format': (FreeFormSelectField, { + "label": "X axis format", + "default": 'smart_date', + "choices": TIMESTAMP_CHOICES, + "description": "D3 format syntax for y axis " + "https: //github.com/mbostock/\n" + "d3/wiki/Formatting" + }), + 'y_axis_format': (FreeFormSelectField, { + "label": "Y axis format", + "default": '.3s', + "choices": [ ('.3s', '".3s" | 12.3k'), ('.3%', '".3%" | 1234543.210%'), ('.4r', '".4r" | 12350'), @@ -505,107 +576,155 @@ class FormFactory(object): ('+,', '"+," | +12,345.4321'), ('$,.2f', '"$,.2f" | $12,345.43'), ], - description="D3 format syntax for y axis " - "https://github.com/mbostock/\n" - "d3/wiki/Formatting"), - 'markup_type': SelectField( - "Markup Type", - choices=self.choicify(['markdown', 'html']), - default="markdown", - description="Pick your favorite markup language"), - 'rotation': SelectField( - "Rotation", - choices=[(s, s) for s in ['random', 'flat', 'square']], - default="random", - description="Rotation to apply to words in the cloud"), - 'line_interpolation': SelectField( - "Line Style", - choices=self.choicify([ + "description": "D3 format syntax for y axis " + "https: //github.com/mbostock/\n" + "d3/wiki/Formatting" + }), + 'markup_type': (SelectField, { + "label": "Markup Type", + "choices": self.choicify(['markdown', 'html']), + "default": "markdown", + "description": "Pick your favorite markup language" + }), + 'rotation': (SelectField, { + "label": "Rotation", + "choices": [(s, s) for s in ['random', 'flat', 'square']], + "default": "random", + "description": "Rotation to apply to words in the cloud" + }), + 'line_interpolation': (SelectField, { + "label": "Line Style", + "choices": self.choicify([ 'linear', 'basis', 'cardinal', 'monotone', 'step-before', 'step-after']), - default='linear', - description="Line interpolation as defined by d3.js"), - 'code': TextAreaField( - "Code", description="Put your code here", default=''), - 'pandas_aggfunc': SelectField( - "Aggregation function", - choices=self.choicify([ + "default": 'linear', + "description": "Line interpolation as defined by d3.js" + }), + 'code': (TextAreaField, { + "label": "Code", + "description": "Put your code here", + "default": '' + }), + 'pandas_aggfunc': (SelectField, { + "label": "Aggregation function", + "choices": self.choicify([ 'sum', 'mean', 'min', 'max', 'median', 'stdev', 'var']), - default='sum', - description=( + "default": 'sum', + "description": ( "Aggregate function to apply when pivoting and " - "computing the total rows and columns")), - 'size_from': TextField( - "Font Size From", - default="20", - description="Font size for the smallest value in the list"), - 'size_to': TextField( - "Font Size To", - default="150", - description="Font size for the biggest value in the list"), - 'show_brush': BetterBooleanField( - "Range Filter", default=False, - description=( - "Whether to display the time range interactive selector")), - 'show_datatable': BetterBooleanField( - "Data Table", default=False, - description="Whether to display the interactive data table"), - 'include_search': BetterBooleanField( - "Search Box", default=False, - description=( - "Whether to include a client side search box")), - 'show_bubbles': BetterBooleanField( - "Show Bubbles", default=False, - description=( - "Whether to display bubbles on top of countries")), - 'show_legend': BetterBooleanField( - "Legend", default=True, - description="Whether to display the legend (toggles)"), - 'x_axis_showminmax': BetterBooleanField( - "X bounds", default=True, - description=( - "Whether to display the min and max values of the X axis")), - 'rich_tooltip': BetterBooleanField( - "Rich Tooltip", default=True, - description=( + "computing the total rows and columns") + }), + 'size_from': (TextField, { + "label": "Font Size From", + "default": "20", + "description": "Font size for the smallest value in the list" + }), + 'size_to': (TextField, { + "label": "Font Size To", + "default": "150", + "description": "Font size for the biggest value in the list" + }), + 'show_brush': (BetterBooleanField, { + "label": "Range Filter", + "default": False, + "description": ( + "Whether to display the time range interactive selector") + }), + 'show_datatable': (BetterBooleanField, { + "label": "Data Table", + "default": False, + "description": "Whether to display the interactive data table" + }), + 'include_search': (BetterBooleanField, { + "label": "Search Box", + "default": False, + "description": ( + "Whether to include a client side search box") + }), + 'show_bubbles': (BetterBooleanField, { + "label": "Show Bubbles", + "default": False, + "description": ( + "Whether to display bubbles on top of countries") + }), + 'show_legend': (BetterBooleanField, { + "label": "Legend", + "default": True, + "description": "Whether to display the legend (toggles)" + }), + 'x_axis_showminmax': (BetterBooleanField, { + "label": "X bounds", + "default": True, + "description": ( + "Whether to display the min and max values of the X axis") + }), + 'rich_tooltip': (BetterBooleanField, { + "label": "Rich Tooltip", + "default": True, + "description": ( "The rich tooltip shows a list of all series for that" - " point in time")), - 'y_axis_zero': BetterBooleanField( - "Y Axis Zero", default=False, - description=( + " point in time") + }), + 'y_axis_zero': (BetterBooleanField, { + "label": "Y Axis Zero", + "default": False, + "description": ( "Force the Y axis to start at 0 instead of the minimum " - "value")), - 'y_log_scale': BetterBooleanField( - "Y Log", default=False, - description="Use a log scale for the Y axis"), - 'x_log_scale': BetterBooleanField( - "X Log", default=False, - description="Use a log scale for the X axis"), - 'donut': BetterBooleanField( - "Donut", default=False, - description="Do you want a donut or a pie?"), - 'contribution': BetterBooleanField( - "Contribution", default=False, - description="Compute the contribution to the total"), - 'num_period_compare': IntegerField( - "Period Ratio", default=None, - validators=[validators.optional()], - description=( + "value") + }), + 'y_log_scale': (BetterBooleanField, { + "label": "Y Log", + "default": False, + "description": "Use a log scale for the Y axis" + }), + 'x_log_scale': (BetterBooleanField, { + "label": "X Log", + "default": False, + "description": "Use a log scale for the X axis" + }), + 'donut': (BetterBooleanField, { + "label": "Donut", + "default": False, + "description": "Do you want a donut or a pie?" + }), + 'contribution': (BetterBooleanField, { + "label": "Contribution", + "default": False, + "description": "Compute the contribution to the total" + }), + 'num_period_compare': (IntegerField, { + "label": "Period Ratio", + "default": None, + "validators": [validators.optional()], + "description": ( "[integer] Number of period to compare against, " - "this is relative to the granularity selected")), - 'time_compare': TextField( - "Time Shift", - default="", - description=( + "this is relative to the granularity selected") + }), + 'time_compare': (TextField, { + "label": "Time Shift", + "default": "", + "description": ( "Overlay a timeseries from a " "relative time period. Expects relative time delta " - "in natural language (example: 24 hours, 7 days, " - "56 weeks, 365 days")), - 'subheader': TextField( - 'Subheader', - description=( + "in natural language (example: 24 hours, 7 days, " + "56 weeks, 365 days") + }), + 'subheader': (TextField, { + "label": "Subheader", + "description": ( "Description text that shows up below your Big " - "Number")), + "Number") + }), + } + + # Override default arguments with form overrides + for field_name, override_map in viz.form_overrides.items(): + if field_name in field_data: + field_data[field_name][1].update(override_map) + + self.field_dict = { + field_name: v[0](**v[1]) + for field_name, v in field_data.items() } @staticmethod diff --git a/caravel/templates/caravel/explore.html b/caravel/templates/caravel/explore.html index 64b27e87a..5e12efeba 100644 --- a/caravel/templates/caravel/explore.html +++ b/caravel/templates/caravel/explore.html @@ -16,10 +16,10 @@
{% set field = form.get_field(fieldname)%}
- {{ viz.get_form_override(fieldname, 'label') or field.label }} + {{ field.label }} {% if field.description %} + title="{{ field.description }}"> {% endif %} {{ field(class_=form.field_css_classes(field.name)) }}
diff --git a/caravel/viz.py b/caravel/viz.py index c5f4a2fc4..4fd12fe73 100644 --- a/caravel/viz.py +++ b/caravel/viz.py @@ -90,16 +90,6 @@ class BaseViz(object): self.groupby = self.form_data.get('groupby') or [] self.reassignments() - def get_form_override(self, fieldname, attr): - if ( - fieldname in self.form_overrides and - attr in self.form_overrides[fieldname]): - s = self.form_overrides[fieldname][attr] - if attr == 'label': - s = ''.format(**locals()) - s = Markup(s) - return s - @classmethod def flat_form_fields(cls): l = set() @@ -344,6 +334,11 @@ class TableViz(BaseViz): ('include_search', None), ) }) + form_overrides = ({ + 'metrics': { + 'default': [], + }, + }) is_timeseries = False def query_obj(self):