Exemple #1
0
    def __init__(self, viz):
        self.viz = viz
        from caravel.viz import viz_types
        viz = self.viz
        datasource = viz.datasource
        default_metric = datasource.metrics_combo[0][0]

        gb_cols = datasource.groupby_column_names
        default_groupby = gb_cols[0] if gb_cols else None
        group_by_choices = [(s, s) for s in datasource.groupby_column_names]
        # 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([
                            'fire', 'blue_white_yellow', 'white_black',
                            'black_white'
                        ]),
                        default='blue_white_yellow',
                        description=""),
            'normalize_across':
            SelectField(
                'Normalize Across',
                choices=self.choicify(['heatmap', 'x', 'y']),
                default='heatmap',
                description=("Color will be rendered based on a ratio "
                             "of the cell against the sum of across this "
                             "criteria")),
            'canvas_image_rendering':
            SelectField(
                'Rendering',
                choices=(
                    ('pixelated', 'pixelated (Sharp)'),
                    ('auto', 'auto (Smooth)'),
                ),
                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=("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=("Number of step to take between ticks when "
                             "printing the y scale")),
            'bar_stacked':
            BetterBooleanField('Stacked Bars', default=False, description=""),
            '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=(
                    ('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=(
                    "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"),
            'granularity':
            FreeFormSelectField(
                'Time Granularity',
                default="one day",
                choices=self.choicify([
                    'all',
                    '5 seconds',
                    '30 seconds',
                    '1 minute',
                    '5 minutes',
                    '1 hour',
                    '6 hour',
                    '1 day',
                    '7 days',
                ]),
                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'")),
            'link_length':
            FreeFormSelectField('Link Length',
                                default="200",
                                choices=self.choicify([
                                    '10',
                                    '25',
                                    '50',
                                    '75',
                                    '100',
                                    '150',
                                    '200',
                                    '250',
                                ]),
                                description="Link length in the force layout"),
            'charge':
            FreeFormSelectField('Charge',
                                default="-500",
                                choices=self.choicify([
                                    '-50',
                                    '-75',
                                    '-100',
                                    '-150',
                                    '-200',
                                    '-250',
                                    '-500',
                                    '-1000',
                                    '-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=(
                    "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([
                    '1 hour ago', '12 hours ago', '1 day ago', '7 days ago',
                    '28 days ago', '90 days ago', '1 year ago'
                ]),
                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([
                                    '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([
                                    '5',
                                    '10',
                                    '15',
                                    '25',
                                    '50',
                                    '75',
                                    '100',
                                ])),
            'whisker_options':
            FreeFormSelectField(
                'Whisker/outlier options',
                default="Tukey",
                description=(
                    "Determines how whiskers and outliers are calculated."),
                choices=self.choicify([
                    'Tukey',
                    'Min/max (no outliers)',
                    '2/98 percentiles',
                    '9/91 percentiles',
                ])),
            '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=(
                    "Defines a rolling window function to apply, works along "
                    "with the [Periods] text box")),
            'rolling_periods':
            IntegerField(
                '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=(
                    "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',
                default='www.airbnb.com',
            ),
            'where':
            TextField(
                '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=(
                    "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=("Based on granularity, number of time periods to "
                             "compare against")),
            'compare_suffix':
            TextField(
                'Comparison suffix',
                description="Suffix to apply after the percentage display"),
            'x_axis_format':
            FreeFormSelectField(
                'X axis format',
                default='smart_date',
                choices=[
                    ('smart_date', 'Adaptative formating'),
                    ("%m/%d/%Y", '"%m/%d/%Y" | 01/14/2019'),
                    ("%Y-%m-%d", '"%Y-%m-%d" | 2019-01-14'),
                    ("%Y-%m-%d %H:%M:%S",
                     '"%Y-%m-%d %H:%M:%S" | 2019-01-14 01:32:10'),
                    ("%H:%M:%S", '"%H:%M:%S" | 01:32:10'),
                ],
                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=[
                                    ('.3s', '".3s" | 12.3k'),
                                    ('.3%', '".3%" | 1234543.210%'),
                                    ('.4r', '".4r" | 12350'),
                                    ('.3f', '".3f" | 12345.432'),
                                    ('+,', '"+," | +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([
                            '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(
                    ['sum', 'mean', 'min', 'max', 'median', 'stdev', 'var']),
                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=(
                    "The rich tooltip shows a list of all series for that"
                    " point in time")),
            'y_axis_zero':
            BetterBooleanField(
                "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=("[integer] Number of period to compare against, "
                             "this is relative to the granularity selected")),
            'time_compare':
            TextField("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=("Description text that shows up below your Big "
                             "Number")),
        }
Exemple #2
0
    def __init__(self, viz):
        self.viz = viz
        from caravel.viz import viz_types
        viz = self.viz
        datasource = viz.datasource
        if not datasource.metrics_combo:
            raise Exception("Please define at least one metric for your table")
        default_metric = datasource.metrics_combo[0][0]

        gb_cols = datasource.groupby_column_names
        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
        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, {
                "label": "Normalize Across",
                "choices": self.choicify([
                    'heatmap', 'x', 'y']),
                "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, {
                "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": (
                    "image-rendering CSS attribute of the canvas object that "
                    "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, {
                "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, {
                "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": (
                    "The country code standard that Caravel should expect "
                    "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": (
                    "Defines the origin where time buckets start, "
                    "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',
                    '1 minute',
                    '5 minutes',
                    '1 hour',
                    '6 hour',
                    '1 day',
                    '7 days',
                ]),
                "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, {
                "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, {
                "label": "Subdomain",
                "default": "day",
                "choices": self.choicify([
                    'min',
                    'hour',
                    'day',
                    'week',
                    'month',
                ]),
                "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, {
                "label": "Link Length",
                "default": "200",
                "choices": self.choicify([
                    '10',
                    '25',
                    '50',
                    '75',
                    '100',
                    '150',
                    '200',
                    '250',
                ]),
                "description": "Link length in the force layout"
            }),
            'charge': (FreeFormSelectField, {
                "label": "Charge",
                "default": "-500",
                "choices": self.choicify([
                    '-50',
                    '-75',
                    '-100',
                    '-150',
                    '-200',
                    '-250',
                    '-500',
                    '-1000',
                    '-2500',
                    '-5000',
                ]),
                "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, {
                "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',
                    '7 days ago',
                    '28 days ago',
                    '90 days ago',
                    '1 year ago'
                ]),
                "description": (
                    "Timestamp from filter. This supports free form typing and "
                    "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, {
                "label": "Max Bubble Size",
                "default": "25",
                "choices": self.choicify([
                    '5',
                    '10',
                    '15',
                    '25',
                    '50',
                    '75',
                    '100',
                ])
            }),
            'whisker_options': (FreeFormSelectField, {
                "label": "Whisker/outlier options",
                "default": "Tukey",
                "description": (
                    "Determines how whiskers and outliers are calculated."),
                "choices": self.choicify([
                    'Tukey',
                    'Min/max (no outliers)',
                    '2/98 percentiles',
                    '9/91 percentiles',
                ])
            }),
            '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'),
                    ('.3f', '".3f" | 12345.432'),
                    ('+,', '"+," | +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, {
                "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, {
                "label": "Periods",
                "validators": [validators.optional()],
                "description": (
                    "Defines the size of the rolling window function, "
                    "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, {
                "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, {
                "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, {
                "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, {
                "label": "Comparison Period Lag",
                "description": (
                    "Based on granularity, number of time periods to "
                    "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'),
                    ('.3f', '".3f" | 12345.432'),
                    ('+,', '"+," | +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, {
                "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, {
                "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": (
                    "Aggregate function to apply when pivoting and "
                    "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, {
                "label": "Y Axis Zero",
                "default": False,
                "description": (
                    "Force the Y axis to start at 0 instead of the minimum "
                    "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, {
                "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, {
                "label": "Subheader",
                "description": (
                    "Description text that shows up below your Big "
                    "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()
        }
Exemple #3
0
    def __init__(self, viz):
        self.viz = viz
        from caravel.viz import viz_types
        viz = self.viz
        datasource = viz.datasource
        if not datasource.metrics_combo:
            raise Exception("Please define at least one metric for your table")
        default_metric = datasource.metrics_combo[0][0]

        gb_cols = datasource.groupby_column_names
        default_groupby = gb_cols[0] if gb_cols else None
        group_by_choices = self.choicify(gb_cols)
        order_by_choices = []
        for s in sorted(datasource.num_cols):
            order_by_choices.append((json.dumps([s, True]), s + ' [asc]'))
            order_by_choices.append((json.dumps([s, False]), s + ' [desc]'))
        # Pool of all the fields that can be used in Caravel
        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")
            }),
            'order_by_cols': (SelectMultipleSortableField, {
                "label": _("Ordering"),
                "choices": order_by_choices,
                "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": (
                    ('stack', _('stack')),
                    ('stream', _('stream')),
                    ('expand', _('expand')),
                ),
                "default": 'stack',
                "description": ""
            }),
            'linear_color_scheme': (SelectField, {
                "label": _("Color Scheme"),
                "choices": (
                    ('fire', _('fire')),
                    ('blue_white_yellow', _('blue_white_yellow')),
                    ('white_black', _('white_black')),
                    ('black_white', _('black_white')),
                ),
                "default": 'blue_white_yellow',
                "description": ""
            }),
            'normalize_across': (SelectField, {
                "label": _("Normalize Across"),
                "choices": (
                    ('heatmap', _('heatmap')),
                    ('x', _('x')),
                    ('y', _('y')),
                ),
                "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, {
                "label": _("Color Scale"),
                "choices": (
                    ('series', _('series')),
                    ('overall', _('overall')),
                    ('change', _('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": _(
                    "image-rendering CSS attribute of the canvas object that "
                    "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, {
                "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, {
                "label": _("Stacked Bars"),
                "default": False,
                "description": ""
            }),
            'show_markers': (BetterBooleanField, {
                "label": _("Show Markers"),
                "default": False,
                "description": (
                    "Show data points as circle markers on top of the lines "
                    "in the chart")
            }),
            'show_bar_value': (BetterBooleanField, {
                "label": _("Bar Values"),
                "default": False,
                "description": "Show the value on top of the bars or not"
            }),
            'show_controls': (BetterBooleanField, {
                "label": _("Extra Controls"),
                "default": False,
                "description": _(
                    "Whether to show extra controls or not. Extra controls "
                    "include things like making mulitBar charts stacked "
                    "or side by side.")
            }),
            'reduce_x_ticks': (BetterBooleanField, {
                "label": _("Reduce X ticks"),
                "default": False,
                "description": _(
                    "Reduces the number of X axis ticks to be rendered. "
                    "If true, the x axis wont overflow and labels may be "
                    "missing. If false, a minimum width will be applied "
                    "to columns and the width may overflow into an "
                    "horizontal scroll."),
            }),
            '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": _(
                    "The country code standard that Caravel should expect "
                    "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),
                "default": datasource.column_names[0],
                "description": _("Columns to display")
            }),
            'all_columns_y': (SelectField, {
                "label": _("Y"),
                "choices": self.choicify(datasource.column_names),
                "default": datasource.column_names[0],
                "description": _("Columns to display")
            }),
            'druid_time_origin': (FreeFormSelectField, {
                "label": _("Origin"),
                "choices": (
                    ('', _('default')),
                    ('now', _('now')),
                ),
                "default": '',
                "description": _(
                    "Defines the origin where time buckets start, "
                    "accepts natural dates as in 'now', 'sunday' or '1970-01-01'")
            }),
            'bottom_margin': (FreeFormSelectField, {
                "label": _("Bottom Margin"),
                "choices": self.choicify(['auto', 50, 75, 100, 125, 150, 200]),
                "default": 'auto',
                "description": _(
                    "Bottom marging, in pixels, allowing for more room for "
                    "axis labels"),
            }),
            'granularity': (FreeFormSelectField, {
                "label": _("Time Granularity"),
                "default": "one day",
                "choices": (
                    ('all', _('all')),
                    ('5 seconds', _('5 seconds')),
                    ('30 seconds', _('30 seconds')),
                    ('1 minute', _('1 minute')),
                    ('5 minutes', _('5 minutes')),
                    ('1 hour', _('1 hour')),
                    ('6 hour', _('6 hour')),
                    ('1 day', _('1 day')),
                    ('7 days', _('7 days')),
                ),
                "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, {
                "label": _("Domain"),
                "default": "month",
                "choices": (
                    ('hour', _('hour')),
                    ('day', _('day')),
                    ('week', _('week')),
                    ('month', _('month')),
                    ('year', _('year')),
                ),
                "description": _(
                    "The time unit used for the grouping of blocks")
            }),
            'subdomain_granularity': (SelectField, {
                "label": _("Subdomain"),
                "default": "day",
                "choices": (
                    ('min', _('min')),
                    ('hour', _('hour')),
                    ('day', _('day')),
                    ('week', _('week')),
                    ('month', _('month')),
                ),
                "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, {
                "label": _("Link Length"),
                "default": "200",
                "choices": self.choicify([
                    '10',
                    '25',
                    '50',
                    '75',
                    '100',
                    '150',
                    '200',
                    '250',
                ]),
                "description": _("Link length in the force layout")
            }),
            'charge': (FreeFormSelectField, {
                "label": _("Charge"),
                "default": "-500",
                "choices": self.choicify([
                    '-50',
                    '-75',
                    '-100',
                    '-150',
                    '-200',
                    '-250',
                    '-500',
                    '-1000',
                    '-2500',
                    '-5000',
                ]),
                "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 below is applied against this column or "
                    "expression")
            }),
            'resample_rule': (FreeFormSelectField, {
                "label": _("Resample Rule"),
                "default": '',
                "choices": (
                    ('1T', _('1T')),
                    ('1H', _('1H')),
                    ('1D', _('1D')),
                    ('7D', _('7D')),
                    ('1M', _('1M')),
                    ('1AS', _('1AS')),
                ),
                "description": _("Pandas resample rule")
            }),
            'resample_how': (FreeFormSelectField, {
                "label": _("Resample How"),
                "default": '',
                "choices": (
                     ('', ''),
                     ('mean', _('mean')),
                     ('sum', _('sum')),
                     ('median', _('median')),
                 ),
                "description": _("Pandas resample how")
            }),
            'resample_fillmethod': (FreeFormSelectField, {
                "label": _("Resample Fill Method"),
                "default": '',
                "choices": (
                    ('', ''),
                    ('ffill', _('ffill')),
                    ('bfill', _('bfill')),
                ),
                "description": _("Pandas resample fill method")
            }),
            'since': (FreeFormSelectField, {
                "label": _("Since"),
                "default": "7 days ago",
                "choices": (
                    ('1 hour ago', _('1 hour ago')),
                    ('12 hours ago', _('12 hours ago')),
                    ('1 day ago', _('1 day ago')),
                    ('7 days ago', _('7 days ago')),
                    ('28 days ago', _('28 days ago')),
                    ('90 days ago', _('90 days ago')),
                    ('1 year ago', _('1 year ago')),
                ),
                "description": _(
                    "Timestamp from filter. This supports free form typing and "
                    "natural language as in '1 day ago', '28 days' or '3 years'")
            }),
            'until': (FreeFormSelectField, {
                "label": _("Until"),
                "default": "now",
                "choices": (
                    ('now', _('now')),
                    ('1 day ago', _('1 day ago')),
                    ('7 days ago', _('7 days ago')),
                    ('28 days ago', _('28 days ago')),
                    ('90 days ago', _('90 days ago')),
                    ('1 year ago', _('1 year ago')),
                )
            }),
            'max_bubble_size': (FreeFormSelectField, {
                "label": _("Max Bubble Size"),
                "default": "25",
                "choices": self.choicify([
                    '5',
                    '10',
                    '15',
                    '25',
                    '50',
                    '75',
                    '100',
                ])
            }),
            'whisker_options': (FreeFormSelectField, {
                "label": _("Whisker/outlier options"),
                "default": "Tukey",
                "description": _(
                    "Determines how whiskers and outliers are calculated."),
                "choices": (
                    ('Tukey', _('Tukey')),
                    ('Min/max (no outliers)', _('Min/max (no outliers)')),
                    ('2/98 percentiles', _('2/98 percentiles')),
                    ('9/91 percentiles', _('9/91 percentiles')),
                )
            }),
            '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'),
                    ('.3f', '".3f" | 12345.432'),
                    ('+,', '"+," | +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, {
                "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, {
                "label": _("Periods"),
                "validators": [validators.optional()],
                "description": _(
                    "Defines the size of the rolling window function, "
                    "relative to the time granularity selected")
            }),
            'series': (SelectField, {
                "label": _("Series"),
                "choices": group_by_choices,
                "default": default_groupby,
                "description": _(
                    "Defines the grouping of entities. "
                    "Each series is shown as a specific color on the chart and "
                    "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',
            }),
            'x_axis_label': (TextField, {
                "label": _("X Axis Label"),
                "default": '',
            }),
            'y_axis_label': (TextField, {
                "label": _("Y Axis Label"),
                "default": '',
            }),
            '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, {
                "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, {
                "label": _("Comparison Period Lag"),
                "description": _(
                    "Based on granularity, number of time periods to "
                    "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'),
                    ('.3f', '".3f" | 12345.432'),
                    ('+,', '"+," | +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, {
                "label": _("Markup Type"),
                "choices": (
                    ('markdown', _('markdown')),
                    ('html', _('html'))
                ),
                "default": "markdown",
                "description": _("Pick your favorite markup language")
            }),
            'rotation': (SelectField, {
                "label": _("Rotation"),
                "choices": (
                    ('random', _('random')),
                    ('flat', _('flat')),
                    ('square', _('square')),
                ),
                "default": "random",
                "description": _("Rotation to apply to words in the cloud")
            }),
            'line_interpolation': (SelectField, {
                "label": _("Line Style"),
                "choices": (
                    ('linear', _('linear')),
                    ('basis', _('basis')),
                    ('cardinal', _('cardinal')),
                    ('monotone', _('monotone')),
                    ('step-before', _('step-before')),
                    ('step-after', _('step-after')),
                ),
                "default": 'linear',
                "description": _("Line interpolation as defined by d3.js")
            }),
            'pie_label_type': (SelectField, {
                "label": _("Label Type"),
                "default": 'key',
                "choices": (
                    ('key', _("Category Name")),
                    ('value', _("Value")),
                    ('percent', _("Percentage")),
                ),
                "description": _("What should be shown on the label?")
            }),
            'code': (TextAreaField, {
                "label": _("Code"),
                "description": _("Put your code here"),
                "default": ''
            }),
            'pandas_aggfunc': (SelectField, {
                "label": _("Aggregation function"),
                "choices": (
                    ('sum', _('sum')),
                    ('mean', _('mean')),
                    ('min', _('min')),
                    ('max', _('max')),
                    ('median', _('median')),
                    ('stdev', _('stdev')),
                    ('var', _('var')),
                ),
                "default": 'sum',
                "description": _(
                    "Aggregate function to apply when pivoting and "
                    "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")
            }),
            'date_filter': (BetterBooleanField, {
                "label": _("Date Filter"),
                "default": False,
                "description": _("Whether to include a time filter")
            }),
            '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, {
                "label": _("Y Axis Zero"),
                "default": False,
                "description": _(
                    "Force the Y axis to start at 0 instead of the minimum "
                    "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?")
            }),
            'labels_outside': (BetterBooleanField, {
                "label": _("Put labels outside"),
                "default": True,
                "description": _("Put the labels outside the 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")
            }),
            'period_ratio_type': (SelectField, {
                "label": _("Period Ratio Type"),
                "default": 'growth',
                "choices": (
                    ('factor', _('factor')),
                    ('growth', _('growth')),
                    ('value', _('value')),
                ),
                "description": _(
                    "`factor` means (new/previous), `growth` is "
                    "((new/previous) - 1), `value` is (new-previous)")
            }),
            '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, {
                "label": _("Subheader"),
                "description": _(
                    "Description text that shows up below your Big "
                    "Number")
            }),
            'mapbox_label': (SelectMultipleSortableField, {
                "label": "Label",
                "choices": self.choicify(["count"] + datasource.column_names),
                "description": _(
                    "'count' is COUNT(*) if a group by is used. "
                    "Numerical columns will be aggregated with the aggregator. "
                    "Non-numerical columns will be used to label points. "
                    "Leave empty to get a count of points in each cluster."),
            }),
            'mapbox_style': (SelectField, {
                "label": "Map Style",
                "choices": [
                    ("mapbox://styles/mapbox/streets-v9", "Streets"),
                    ("mapbox://styles/mapbox/dark-v9", "Dark"),
                    ("mapbox://styles/mapbox/light-v9", "Light"),
                    ("mapbox://styles/mapbox/satellite-streets-v9", "Satellite Streets"),
                    ("mapbox://styles/mapbox/satellite-v9", "Satellite"),
                    ("mapbox://styles/mapbox/outdoors-v9", "Outdoors"),
                ],
                "default": "mapbox://styles/mapbox/streets-v9",
                "description": _("Base layer map style")
            }),
            'clustering_radius': (FreeFormSelectField, {
                "label": _("Clustering Radius"),
                "default": "60",
                "choices": self.choicify([
                    '0',
                    '20',
                    '40',
                    '60',
                    '80',
                    '100',
                    '200',
                    '500',
                    '1000',
                ]),
                "description": _(
                    "The radius (in pixels) the algorithm uses to define a cluster. "
                    "Choose 0 to turn off clustering, but beware that a large "
                    "number of points (>1000) will cause lag.")
            }),
            'point_radius': (SelectField, {
                "label": _("Point Radius"),
                "default": "Auto",
                "choices": self.choicify(["Auto"] + datasource.column_names),
                "description": _(
                    "The radius of individual points (ones that are not in a cluster). "
                    "Either a numerical column or 'Auto', which scales the point based "
                    "on the largest cluster")
            }),
            'point_radius_unit': (SelectField, {
                "label": _("Point Radius Unit"),
                "default": "Pixels",
                "choices": self.choicify([
                    "Pixels",
                    "Miles",
                    "Kilometers",
                ]),
                "description": _("The unit of measure for the specified point radius")
            }),
            'global_opacity': (DecimalField, {
                "label": _("Opacity"),
                "default": 1,
                "description": _(
                    "Opacity of all clusters, points, and labels. "
                    "Between 0 and 1."),
            }),
            'viewport_zoom': (DecimalField, {
                "label": _("Zoom"),
                "default": 11,
                "validators": [validators.optional()],
                "description": _("Zoom level of the map"),
                "places": 8,
            }),
            'viewport_latitude': (DecimalField, {
                "label": _("Default latitude"),
                "default": 37.772123,
                "description": _("Latitude of default viewport"),
                "places": 8,
            }),
            'viewport_longitude': (DecimalField, {
                "label": _("Default longitude"),
                "default": -122.405293,
                "description": _("Longitude of default viewport"),
                "places": 8,
            }),
            'render_while_dragging': (BetterBooleanField, {
                "label": _("Live render"),
                "default": True,
                "description": _("Points and clusters will update as viewport "
                    "is being changed")
            }),
            'mapbox_color': (FreeFormSelectField, {
                "label": _("RGB Color"),
                "default": "rgb(0, 122, 135)",
                "choices": [
                    ("rgb(0, 139, 139)", "Dark Cyan"),
                    ("rgb(128, 0, 128)", "Purple"),
                    ("rgb(255, 215, 0)", "Gold"),
                    ("rgb(69, 69, 69)", "Dim Gray"),
                    ("rgb(220, 20, 60)", "Crimson"),
                    ("rgb(34, 139, 34)", "Forest Green"),
                ],
                "description": _("The color for points and clusters in RGB")
            }),
        }

        # 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()
        }
Exemple #4
0
    def __init__(self, viz):
        self.viz = viz
        from caravel.viz import viz_types
        viz = self.viz
        datasource = viz.datasource
        if not datasource.metrics_combo:
            raise Exception("Please define at least one metric for your table")
        default_metric = datasource.metrics_combo[0][0]

        gb_cols = datasource.groupby_column_names
        default_groupby = gb_cols[0] if gb_cols else None
        group_by_choices = self.choicify(gb_cols)
        order_by_choices = []
        for s in sorted(datasource.num_cols):
            order_by_choices.append((json.dumps([s, True]), s + ' [asc]'))
            order_by_choices.append((json.dumps([s, False]), s + ' [desc]'))
        # Pool of all the fields that can be used in Caravel
        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")
            }),
            'order_by_cols': (SelectMultipleSortableField, {
                "label": _("Ordering"),
                "choices": order_by_choices,
                "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": (
                    ('stack', _('stack')),
                    ('stream', _('stream')),
                    ('expand', _('expand')),
                ),
                "default": 'stack',
                "description": ""
            }),
            'linear_color_scheme': (SelectField, {
                "label": _("Color Scheme"),
                "choices": (
                    ('fire', _('fire')),
                    ('blue_white_yellow', _('blue_white_yellow')),
                    ('white_black', _('white_black')),
                    ('black_white', _('black_white')),
                ),
                "default": 'blue_white_yellow',
                "description": ""
            }),
            'normalize_across': (SelectField, {
                "label": _("Normalize Across"),
                "choices": (
                    ('heatmap', _('heatmap')),
                    ('x', _('x')),
                    ('y', _('y')),
                ),
                "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, {
                "label": _("Color Scale"),
                "choices": (
                    ('series', _('series')),
                    ('overall', _('overall')),
                    ('change', _('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": _(
                    "image-rendering CSS attribute of the canvas object that "
                    "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, {
                "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, {
                "label": _("Stacked Bars"),
                "default": False,
                "description": ""
            }),
            'show_controls': (BetterBooleanField, {
                "label": _("Extra Controls"),
                "default": False,
                "description": (
                    "Whether to show extra controls or not. Extra controls "
                    "include things like making mulitBar charts stacked "
                    "or side by side.")
            }),
            'reduce_x_ticks': (BetterBooleanField, {
                "label": _("Reduce X ticks"),
                "default": False,
                "description": _(
                    "Reduces the number of X axis ticks to be rendered. "
                    "If true, the x axis wont overflow and labels may be "
                    "missing. If false, a minimum width will be applied "
                    "to columns and the width may overflow into an "
                    "horizontal scroll."),
            }),
            '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": _(
                    "The country code standard that Caravel should expect "
                    "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": _(
                    "Defines the origin where time buckets start, "
                    "accepts natural dates as in 'now', 'sunday' or '1970-01-01'")
            }),
            'bottom_margin': (FreeFormSelectField, {
                "label": _("Bottom Margin"),
                "choices": self.choicify([50, 75, 100, 125, 150, 200]),
                "default": 50,
                "description": _(
                    "Bottom marging, in pixels, allowing for more room for "
                    "axis labels"),
            }),
            'granularity': (FreeFormSelectField, {
                "label": _("Time Granularity"),
                "default": "one day",
                "choices": (
                    ('all', _('all')),
                    ('5 seconds', _('5 seconds')),
                    ('30 seconds', _('30 seconds')),
                    ('1 minute', _('1 minute')),
                    ('5 minutes', _('5 minutes')),
                    ('1 hour', _('1 hour')),
                    ('6 hour', _('6 hour')),
                    ('1 day', _('1 day')),
                    ('7 days', _('7 days')),
                ),
                "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, {
                "label": _("Domain"),
                "default": "month",
                "choices": (
                    ('hour', _('hour')),
                    ('day', _('day')),
                    ('week', _('week')),
                    ('month', _('month')),
                    ('year', _('year')),
                ),
                "description": _(
                    "The time unit used for the grouping of blocks")
            }),
            'subdomain_granularity': (SelectField, {
                "label": _("Subdomain"),
                "default": "day",
                "choices": (
                    ('min', _('min')),
                    ('hour', _('hour')),
                    ('day', _('day')),
                    ('week', _('week')),
                    ('month', _('month')),
                ),
                "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, {
                "label": _("Link Length"),
                "default": "200",
                "choices": self.choicify([
                    '10',
                    '25',
                    '50',
                    '75',
                    '100',
                    '150',
                    '200',
                    '250',
                ]),
                "description": _("Link length in the force layout")
            }),
            'charge': (FreeFormSelectField, {
                "label": _("Charge"),
                "default": "-500",
                "choices": self.choicify([
                    '-50',
                    '-75',
                    '-100',
                    '-150',
                    '-200',
                    '-250',
                    '-500',
                    '-1000',
                    '-2500',
                    '-5000',
                ]),
                "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, {
                "label": _("Resample Rule"),
                "default": '',
                "choices": (
                    ('1T', _('1T')),
                    ('1H', _('1H')),
                    ('1D', _('1D')),
                    ('7D', _('7D')),
                    ('1M', _('1M')),
                    ('1AS', _('1AS')),
                ),
                "description": _("Pandas resample rule")
            }),
            'resample_how': (FreeFormSelectField, {
                "label": _("Resample How"),
                "default": '',
                "choices": (
                     ('', ''),
                     ('mean', _('mean')),
                     ('sum', _('sum')),
                     ('median', _('median')),
                 ),
                "description": _("Pandas resample how")
            }),
            'resample_fillmethod': (FreeFormSelectField, {
                "label": _("Resample Fill Method"),
                "default": '',
                "choices": (
                    ('', ''),
                    ('ffill', _('ffill')),
                    ('bfill', _('bfill')),
                ),
                "description": _("Pandas resample fill method")
            }),
            'since': (FreeFormSelectField, {
                "label": _("Since"),
                "default": "7 days ago",
                "choices": (
                    ('1 hour ago', _('1 hour ago')),
                    ('12 hours ago', _('12 hours ago')),
                    ('1 day ago', _('1 day ago')),
                    ('7 days ago', _('7 days ago')),
                    ('28 days ago', _('28 days ago')),
                    ('90 days ago', _('90 days ago')),
                    ('1 year ago', _('1 year ago')),
                ),
                "description": _(
                    "Timestamp from filter. This supports free form typing and "
                    "natural language as in '1 day ago', '28 days' or '3 years'")
            }),
            'until': (FreeFormSelectField, {
                "label": _("Until"),
                "default": "now",
                "choices": (
                    ('now', _('now')),
                    ('1 day ago', _('1 day ago')),
                    ('7 days ago', _('7 days ago')),
                    ('28 days ago', _('28 days ago')),
                    ('90 days ago', _('90 days ago')),
                    ('1 year ago', _('1 year ago')),
                )
            }),
            'max_bubble_size': (FreeFormSelectField, {
                "label": _("Max Bubble Size"),
                "default": "25",
                "choices": self.choicify([
                    '5',
                    '10',
                    '15',
                    '25',
                    '50',
                    '75',
                    '100',
                ])
            }),
            'whisker_options': (FreeFormSelectField, {
                "label": _("Whisker/outlier options"),
                "default": "Tukey",
                "description": _(
                    "Determines how whiskers and outliers are calculated."),
                "choices": (
                    ('Tukey', _('Tukey')),
                    ('Min/max (no outliers)', _('Min/max (no outliers)')),
                    ('2/98 percentiles', _('2/98 percentiles')),
                    ('9/91 percentiles', _('9/91 percentiles')),
                )
            }),
            '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'),
                    ('.3f', '".3f" | 12345.432'),
                    ('+,', '"+," | +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, {
                "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, {
                "label": _("Periods"),
                "validators": [validators.optional()],
                "description": _(
                    "Defines the size of the rolling window function, "
                    "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, {
                "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',
            }),
            'x_axis_label': (TextField, {
                "label": _("X Axis Label"),
                "default": '',
            }),
            'y_axis_label': (TextField, {
                "label": _("Y Axis Label"),
                "default": '',
            }),
            '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, {
                "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, {
                "label": _("Comparison Period Lag"),
                "description": _(
                    "Based on granularity, number of time periods to "
                    "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'),
                    ('.3f', '".3f" | 12345.432'),
                    ('+,', '"+," | +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, {
                "label": _("Markup Type"),
                "choices": (
                    ('markdown', _('markdown')),
                    ('html', _('html'))
                ),
                "default": "markdown",
                "description": _("Pick your favorite markup language")
            }),
            'rotation': (SelectField, {
                "label": _("Rotation"),
                "choices": (
                    ('random', _('random')),
                    ('flat', _('flat')),
                    ('square', _('square')),
                ),
                "default": "random",
                "description": _("Rotation to apply to words in the cloud")
            }),
            'line_interpolation': (SelectField, {
                "label": _("Line Style"),
                "choices": (
                    ('linear', _('linear')),
                    ('basis', _('basis')),
                    ('cardinal', _('cardinal')),
                    ('monotone', _('monotone')),
                    ('step-before', _('step-before')),
                    ('step-after', _('step-after')),
                ),
                "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": (
                    ('sum', _('sum')),
                    ('mean', _('mean')),
                    ('min', _('min')),
                    ('max', _('max')),
                    ('median', _('median')),
                    ('stdev', _('stdev')),
                    ('var', _('var')),
                ),
                "default": 'sum',
                "description": _(
                    "Aggregate function to apply when pivoting and "
                    "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, {
                "label": _("Y Axis Zero"),
                "default": False,
                "description": _(
                    "Force the Y axis to start at 0 instead of the minimum "
                    "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, {
                "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, {
                "label": _("Subheader"),
                "description": _(
                    "Description text that shows up below your Big "
                    "Number")
            }),
            'mapbox_label': (SelectMultipleSortableField, {
                "label": "Label",
                "choices": self.choicify(["count"] + datasource.column_names),
                "description": _(
                    "'count' is COUNT(*) if a group by is used. "
                    "Numerical columns will be aggregated with the aggregator. "
                    "Non-numerical columns will be used to label points. "
                    "Leave empty to get a count of points in each cluster."),
            }),
            'mapbox_style': (SelectField, {
                "label": "Map Style",
                "choices": [
                    ("mapbox://styles/mapbox/streets-v9", "Streets"),
                    ("mapbox://styles/mapbox/dark-v9", "Dark"),
                    ("mapbox://styles/mapbox/light-v9", "Light"),
                    ("mapbox://styles/mapbox/satellite-streets-v9", "Satellite Streets"),
                    ("mapbox://styles/mapbox/satellite-v9", "Satellite"),
                    ("mapbox://styles/mapbox/outdoors-v9", "Outdoors"),
                ],
                "description": _("Base layer map style")
            }),
            'clustering_radius': (FreeFormSelectField, {
                "label": _("Clustering Radius"),
                "default": "60",
                "choices": self.choicify([
                    '0',
                    '20',
                    '40',
                    '60',
                    '80',
                    '100',
                    '200',
                    '500',
                    '1000',
                ]),
                "description": _(
                    "The radius (in pixels) the algorithm uses to define a cluster. "
                    "Choose 0 to turn off clustering, but beware that a large "
                    "number of points (>1000) will cause lag.")
            }),
            'point_radius': (SelectField, {
                "label": _("Point Radius"),
                "default": "Auto",
                "choices": self.choicify(["Auto"] + datasource.column_names),
                "description": _(
                    "The radius of individual points (ones that are not in a cluster). "
                    "Either a numerical column or 'Auto', which scales the point based "
                    "on the largest cluster")
            }),
            'point_radius_unit': (SelectField, {
                "label": _("Point Radius Unit"),
                "default": "Pixels",
                "choices": self.choicify([
                    "Pixels",
                    "Miles",
                    "Kilometers",
                ]),
                "description": _("The unit of measure for the specified point radius")
            }),
            'global_opacity': (DecimalField, {
                "label": _("Opacity"),
                "default": 1,
                "description": _(
                    "Opacity of all clusters, points, and labels. "
                    "Between 0 and 1."),
            }),
            'viewport_zoom': (DecimalField, {
                "label": _("Zoom"),
                "default": 11,
                "validators": [validators.optional()],
                "description": _("Zoom level of the map"),
                "places": 8,
            }),
            'viewport_latitude': (DecimalField, {
                "label": _("Default latitude"),
                "default": 37.772123,
                "description": _("Latitude of default viewport"),
                "places": 8,
            }),
            'viewport_longitude': (DecimalField, {
                "label": _("Default longitude"),
                "default": -122.405293,
                "description": _("Longitude of default viewport"),
                "places": 8,
            }),
            'render_while_dragging': (BetterBooleanField, {
                "label": _("Live render"),
                "default": True,
                "description": _("Points and clusters will update as viewport "
                    "is being changed")
            }),
            'mapbox_color': (FreeFormSelectField, {
                "label": _("RGB Color"),
                "default": "rgb(0, 122, 135)",
                "choices": [
                    ("rgb(0, 139, 139)", "Dark Cyan"),
                    ("rgb(128, 0, 128)", "Purple"),
                    ("rgb(255, 215, 0)", "Gold"),
                    ("rgb(69, 69, 69)", "Dim Gray"),
                    ("rgb(220, 20, 60)", "Crimson"),
                    ("rgb(34, 139, 34)", "Forest Green"),
                ],
                "description": _("The color for points and clusters in RGB")
            }),
        }

        # 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()
        }
Exemple #5
0
 def __init__(self, viz):
     self.viz = viz
     from caravel.viz import viz_types
     viz = self.viz
     datasource = viz.datasource
     default_metric = datasource.metrics_combo[0][0]
     default_groupby = datasource.groupby_column_names[0]
     group_by_choices = [(s, s) for s in datasource.groupby_column_names]
     # 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([
                 'fire', 'blue_white_yellow', 'white_black',
                 'black_white']),
             default='blue_white_yellow',
             description=""),
         'normalize_across': SelectField(
             'Normalize Across', choices=self.choicify([
                 'heatmap', 'x', 'y']),
             default='heatmap',
             description=(
                 "Color will be rendered based on a ratio "
                 "of the cell against the sum of across this "
                 "criteria")),
         'canvas_image_rendering': SelectField(
             'Rendering', choices=(
                 ('pixelated', 'pixelated (Sharp)'),
                 ('auto', 'auto (Smooth)'),
             ),
             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=(
                 "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=(
                 "Number of step to take between ticks when "
                 "printing the y scale")),
         'bar_stacked': BetterBooleanField(
             'Stacked Bars',
             default=False,
             description=""),
         '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=(
                 ('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=(
                 "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"),
         'granularity': FreeFormSelectField(
             'Time Granularity', default="one day",
             choices=self.choicify([
                 'all',
                 '5 seconds',
                 '30 seconds',
                 '1 minute',
                 '5 minutes',
                 '1 hour',
                 '6 hour',
                 '1 day',
                 '7 days',
             ]),
             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'")),
         'link_length': FreeFormSelectField(
             'Link Length', default="200",
             choices=self.choicify([
                 '10',
                 '25',
                 '50',
                 '75',
                 '100',
                 '150',
                 '200',
                 '250',
             ]),
             description="Link length in the force layout"),
         'charge': FreeFormSelectField(
             'Charge', default="-500",
             choices=self.choicify([
                 '-50',
                 '-75',
                 '-100',
                 '-150',
                 '-200',
                 '-250',
                 '-500',
                 '-1000',
                 '-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=(
                 "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([
                 '1 hour ago',
                 '12 hours ago',
                 '1 day ago',
                 '7 days ago',
                 '28 days ago',
                 '90 days ago',
                 '1 year ago'
             ]),
             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([
                 '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([
                 '5',
                 '10',
                 '15',
                 '25',
                 '50',
                 '75',
                 '100',
             ])
         ),
         '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=(
                 "Defines a rolling window function to apply, works along "
                 "with the [Periods] text box")),
         'rolling_periods': IntegerField(
             '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=(
                 "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', default='www.airbnb.com',),
         'where': TextField(
             '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=(
                 "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=(
                 "Based on granularity, number of time periods to "
                 "compare against")),
         'compare_suffix': TextField(
             'Comparison suffix',
             description="Suffix to apply after the percentage display"),
         'x_axis_format': FreeFormSelectField(
             'X axis format',
             default='smart_date',
             choices=[
                 ('smart_date', 'Adaptative formating'),
                 ("%m/%d/%Y", '"%m/%d/%Y" | 01/14/2019'),
                 ("%Y-%m-%d", '"%Y-%m-%d" | 2019-01-14'),
                 ("%Y-%m-%d %H:%M:%S",
                     '"%Y-%m-%d %H:%M:%S" | 2019-01-14 01:32:10'),
                 ("%H:%M:%S", '"%H:%M:%S" | 01:32:10'),
             ],
             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=[
                 ('.3s', '".3s" | 12.3k'),
                 ('.3%', '".3%" | 1234543.210%'),
                 ('.4r', '".4r" | 12350'),
                 ('.3f', '".3f" | 12345.432'),
                 ('+,', '"+," | +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([
                 '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([
                 'sum', 'mean', 'min', 'max', 'median', 'stdev', 'var']),
             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=(
                 "The rich tooltip shows a list of all series for that"
                 " point in time")),
         'y_axis_zero': BetterBooleanField(
             "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=(
                 "[integer] Number of period to compare against, "
                 "this is relative to the granularity selected")),
         'time_compare': TextField(
             "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=(
                 "Description text that shows up below your Big "
                 "Number")),
     }