class ConfigurableDataSourceFromAppForm(forms.Form): def __init__(self, domain, *args, **kwargs): super(ConfigurableDataSourceFromAppForm, self).__init__(*args, **kwargs) self.app_source_helper = ApplicationDataSourceUIHelper() self.app_source_helper.bootstrap(domain) report_source_fields = self.app_source_helper.get_fields() self.fields.update(report_source_fields) self.helper = FormHelper() self.helper.form_id = "data-source-config" self.helper.form_method = 'POST' self.helper.form_class = 'form-horizontal' self.helper.form_action = '#' self.helper.label_class = 'col-sm-3 col-md-2' self.helper.field_class = 'col-sm-9 col-md-9' self.helper.layout = crispy.Layout( crispy.Fieldset( _("Create Data Source from Application"), *report_source_fields.keys() ), hqcrispy.FormActions( twbscrispy.StrictButton( _("Create Data Source"), type="submit", css_class="btn btn-primary", ), ), )
class ConfigurableDataSourceFromAppForm(forms.Form): def __init__(self, domain, *args, **kwargs): super(ConfigurableDataSourceFromAppForm, self).__init__(*args, **kwargs) self.app_source_helper = ApplicationDataSourceUIHelper() self.app_source_helper.bootstrap(domain) report_source_fields = self.app_source_helper.get_fields() self.fields.update(report_source_fields) self.helper = FormHelper() self.helper.form_id = "data-source-config" self.helper.form_method = 'POST' self.helper.form_class = 'form-horizontal' self.helper.form_action = '#' self.helper.label_class = 'col-sm-3 col-md-2' self.helper.field_class = 'col-sm-9 col-md-9' self.helper.layout = crispy.Layout( crispy.Fieldset(_("Create Data Source from Application"), *list(report_source_fields)), hqcrispy.FormActions( twbscrispy.StrictButton( _("Create Data Source"), type="submit", css_class="btn btn-primary", ), ), )
class ConfigurableDataSourceFromAppForm(forms.Form): def __init__(self, domain, *args, **kwargs): super(ConfigurableDataSourceFromAppForm, self).__init__(*args, **kwargs) self.app_source_helper = ApplicationDataSourceUIHelper() self.app_source_helper.bootstrap(domain) report_source_fields = self.app_source_helper.get_fields() self.fields.update(report_source_fields) self.helper = FormHelper() self.helper.form_id = "data-source-config" self.helper.layout = crispy.Layout( crispy.Div(*report_source_fields.keys() + [Submit("submit", _("Save Changes"))]) )
class ConfigurableDataSourceFromAppForm(forms.Form): def __init__(self, domain, *args, **kwargs): super(ConfigurableDataSourceFromAppForm, self).__init__(*args, **kwargs) self.app_source_helper = ApplicationDataSourceUIHelper() self.app_source_helper.bootstrap(domain) report_source_fields = self.app_source_helper.get_fields() self.fields.update(report_source_fields) self.helper = FormHelper() self.helper.form_id = "data-source-config" self.helper.layout = crispy.Layout( crispy.Div(*report_source_fields.keys() + [Submit('submit', _('Save Changes'))]))
class PerformanceMessageEditForm(forms.Form): recipient_id = forms.CharField() schedule = forms.ChoiceField(choices=[(choice, ugettext_lazy(choice)) for choice in SCHEDULE_CHOICES]) template = forms.CharField(widget=forms.Textarea) time_range = forms.ChoiceField( choices=[(choice.slug, choice.description) for choice in get_simple_dateranges()] ) def __init__(self, domain, config, *args, **kwargs): self.domain = domain self.config = config def _to_initial(config): initial = copy.copy(config._doc) initial['schedule'] = config.schedule.interval if config.template_variables: initial['application'] = config.template_variables[0].app_id initial['source'] = config.template_variables[0].source_id initial['time_range'] = config.template_variables[0].time_range return initial super(PerformanceMessageEditForm, self).__init__(initial=_to_initial(config), *args, **kwargs) self.fields['recipient_id'] = GroupField(domain=domain, label=_('Recipient Group')) self.app_source_helper = ApplicationDataSourceUIHelper(enable_cases=False) self.app_source_helper.bootstrap(self.domain) data_source_fields = self.app_source_helper.get_fields() self.fields.update(data_source_fields) self.helper = _get_default_form_helper() form_layout = self.fields.keys() form_layout.append( hqcrispy.FormActions( StrictButton( _("Save Changes"), type="submit", css_class="btn btn-primary", ), ) ) self.helper.layout = Layout( *form_layout ) def clean_template(self): return _clean_template(self.cleaned_data['template']) def clean_schedule(self): # todo: support other scheduling options return ScheduleConfiguration(interval=self.cleaned_data['schedule']) def save(self, commit=True): self.config.recipient_id = self.cleaned_data['recipient_id'] self.config.schedule = self.cleaned_data['schedule'] self.config.template = self.cleaned_data['template'] template_variable = TemplateVariable( type=self.cleaned_data['source_type'], time_range=self.cleaned_data['time_range'], source_id=self.cleaned_data['source'], app_id=self.cleaned_data['application'], ) self.config.template_variables = [template_variable] if commit: self.config.save() return self.config @property def app_id(self): if self.config.template_variables: return self.config.template_variables[0].app_id return '' @property def source_id(self): if self.config.template_variables: return self.config.template_variables[0].source_id return ''
class DataSourceForm(forms.Form): report_name = forms.CharField() chart_type = forms.ChoiceField( choices=[ ('bar', _('Bar')), ('pie', _("Pie")), ], ) def __init__(self, domain, report_type, *args, **kwargs): super(DataSourceForm, self).__init__(*args, **kwargs) self.domain = domain self.report_type = report_type self.app_source_helper = ApplicationDataSourceUIHelper() self.app_source_helper.bootstrap(self.domain) report_source_fields = self.app_source_helper.get_fields() report_source_help_texts = { "source_type": _("<strong>Form</strong>: display data from form submissions.<br/><strong>Case</strong>: display data from your cases. You must be using case management for this option."), "application": _("Which application should the data come from?"), "source": _("Choose the case type or form from which to retrieve data for this report."), } self.fields.update(report_source_fields) self.fields['chart_type'].required = self.report_type == "chart" self.helper = FormHelper() self.helper.form_class = "form-horizontal" self.helper.form_id = "report-builder-form" chart_type_crispy_field = None if self.report_type == 'chart': chart_type_crispy_field = FieldWithHelpBubble('chart_type', help_bubble_text=_("<strong>Bar</strong> shows one vertical bar for each value in your case or form. <strong>Pie</strong> shows what percentage of the total each value is.")) report_source_crispy_fields = [] for k in report_source_fields.keys(): if k in report_source_help_texts: report_source_crispy_fields.append(FieldWithHelpBubble( k, help_bubble_text=report_source_help_texts[k] )) else: report_source_crispy_fields.append(k) self.helper.layout = crispy.Layout( crispy.Fieldset( _('{} Report'.format(self.report_type.capitalize())), FieldWithHelpBubble('report_name', help_bubble_text=_('Web users will see this name in the "Reports" section of CommCareHQ and can click to view the report')), chart_type_crispy_field ), crispy.Fieldset( _('Data'), *report_source_crispy_fields ), FormActions( crispy.ButtonHolder( crispy.Submit( 'create_new_report_builder_btn', _('Next'), ) ), ), ) @property def sources_map(self): return self.app_source_helper.all_sources def get_selected_source(self): return self.app_source_helper.get_app_source(self.cleaned_data) def clean(self): """ Raise a validation error if there are already 5 data sources and this report won't be able to use one of the existing ones. """ cleaned_data = super(DataSourceForm, self).clean() source_type = cleaned_data.get('source_type') report_source = cleaned_data.get('report_source') app_id = cleaned_data.get('application') if report_source and source_type and app_id: app = Application.get(app_id) ds_builder = DataSourceBuilder(self.domain, app, source_type, report_source) existing_sources = DataSourceConfiguration.by_domain(self.domain) if len(existing_sources) >= 5: if not ds_builder.get_existing_match(): raise forms.ValidationError(_( "Too many data sources!\n" "Creating this report would cause you to go over the maximum " "number of data sources allowed in this domain. The current " "limit is 5. " "To continue, delete all of the reports using a particular " "data source (or the data source itself) and try again. " )) return cleaned_data
class CreateNewReportForm(forms.Form): """ A form for the first page of the report builder. Allows user to specify report type, application, and source. """ report_type = forms.ChoiceField( choices=[ ('bar_chart', _("Bar Chart")), ('pie_chart', _("Pie Chart")), ('table', _("Table")), ], ) def __init__(self, domain, *args, **kwargs): super(CreateNewReportForm, self).__init__(*args, **kwargs) self.domain = domain self.app_source_helper = ApplicationDataSourceUIHelper() self.app_source_helper.bootstrap(self.domain) report_source_fields = self.app_source_helper.get_fields() self.fields.update(report_source_fields) self.helper = FormHelper() self.helper.form_class = "form-horizontal" self.helper.form_id = "report-builder-form" self.helper.layout = crispy.Layout( crispy.Fieldset( _('Create New Report'), 'report_type', *report_source_fields.keys() ), FormActions( crispy.ButtonHolder( crispy.Submit( 'create_new_report_builder_btn', _('Next'), ) ), ), ) @property def sources_map(self): return self.app_source_helper.all_sources def get_selected_source(self): return self.app_source_helper.get_app_source(self.cleaned_data) def clean(self): """ Raise a validation error if there are already 5 data sources and this report won't be able to use one of the existing ones. """ cleaned_data = super(CreateNewReportForm, self).clean() source_type = cleaned_data.get('source_type') report_source = cleaned_data.get('report_source') app_id = cleaned_data.get('application') if report_source and source_type and app_id: app = Application.get(app_id) ds_builder = DataSourceBuilder(self.domain, app, source_type, report_source) existing_sources = DataSourceConfiguration.by_domain(self.domain) if len(existing_sources) >= 5: if not ds_builder.get_existing_match(): raise forms.ValidationError(_( "Too many data sources!\n" "Creating this report would cause you to go over the maximum " "number of data sources allowed in this domain. The current " "limit is 5. " "To continue, delete all of the reports using a particular " "data source (or the data source itself) and try again. " )) return cleaned_data
class PerformanceMessageEditForm(forms.Form): recipient_id = forms.CharField() schedule = forms.ChoiceField(choices=[(choice, ugettext_lazy(choice)) for choice in SCHEDULE_CHOICES]) template = forms.CharField(widget=forms.Textarea) time_range = forms.ChoiceField( choices=[(choice.slug, choice.description) for choice in get_simple_dateranges()] ) def __init__(self, domain, config, *args, **kwargs): self.domain = domain self.config = config def _to_initial(config): initial = copy.copy(config._doc) initial['schedule'] = config.schedule.interval if config.template_variables: # todo: needs to support multiple sources initial['application'] = config.template_variables[0].app_id initial['source'] = config.template_variables[0].source_id initial['time_range'] = config.template_variables[0].time_range return initial super(PerformanceMessageEditForm, self).__init__(initial=_to_initial(config), *args, **kwargs) self.fields['recipient_id'] = GroupField(domain=domain, label=_('Recipient Group')) self.app_source_helper = ApplicationDataSourceUIHelper(enable_cases=False) self.app_source_helper.bootstrap(self.domain) data_source_fields = self.app_source_helper.get_fields() self.fields.update(data_source_fields) self.helper = FormHelper() self.helper.label_class = 'col-sm-3 col-md-2' self.helper.field_class = 'col-sm-9 col-md-8 col-lg-6' self.helper.form_class = "form-horizontal" self.helper.form_id = "performance-form" self.helper.form_method = 'post' form_layout = self.fields.keys() form_layout.append( hqcrispy.FormActions( StrictButton( _("Save Changes"), type="submit", css_class="btn btn-primary", ), ) ) self.helper.layout = Layout( *form_layout ) def clean_template(self): template = self.cleaned_data['template'] try: parser.validate(template) except InvalidParameterException as e: raise forms.ValidationError(unicode(e)) return template def clean_schedule(self): # todo: support other scheduling options return ScheduleConfiguration(interval=self.cleaned_data['schedule']) def save(self, commit=True): self.config.recipient_id = self.cleaned_data['recipient_id'] self.config.schedule = self.cleaned_data['schedule'] self.config.template = self.cleaned_data['template'] # todo: support more than one data source template_variable = TemplateVariable( type=self.cleaned_data['source_type'], time_range=self.cleaned_data['time_range'], source_id=self.cleaned_data['source'], app_id=self.cleaned_data['application'], ) self.config.template_variables = [template_variable] if commit: self.config.save() return self.config @property def app_id(self): # todo: need to support multiple sources if self.config.template_variables: return self.config.template_variables[0].app_id return '' @property def source_id(self): if self.config.template_variables: return self.config.template_variables[0].source_id return ''
class DataSourceForm(forms.Form): report_name = forms.CharField() chart_type = forms.ChoiceField( choices=[ ('bar', _('Bar')), ('pie', _("Pie")), ], ) def __init__(self, domain, report_type, max_allowed_reports, *args, **kwargs): super(DataSourceForm, self).__init__(*args, **kwargs) self.domain = domain self.report_type = report_type self.max_allowed_reports = max_allowed_reports self.app_source_helper = ApplicationDataSourceUIHelper() self.app_source_helper.source_type_field.label = _('Forms or Cases') self.app_source_helper.source_type_field.choices = [("case", _("Cases")), ("form", _("Forms"))] self.app_source_helper.source_field.label = '<span data-bind="text: labelMap[sourceType()]"></span>' self.app_source_helper.bootstrap(self.domain) report_source_fields = self.app_source_helper.get_fields() report_source_help_texts = { "source_type": _("<strong>Form</strong>: display data from form submissions.<br/><strong>Case</strong>: display data from your cases. You must be using case management for this option."), "application": _("Which application should the data come from?"), "source": _("Choose the case type or form from which to retrieve data for this report."), } self.fields.update(report_source_fields) self.fields['chart_type'].required = self.report_type == "chart" self.helper = FormHelper() self.helper.form_class = "form form-horizontal" self.helper.form_id = "report-builder-form" self.helper.label_class = 'col-sm-3 col-md-2 col-lg-2' self.helper.field_class = 'col-sm-9 col-md-8 col-lg-6' chart_type_crispy_field = None if self.report_type == 'chart': chart_type_crispy_field = FieldWithHelpBubble('chart_type', help_bubble_text=_("<strong>Bar</strong> shows one vertical bar for each value in your case or form. <strong>Pie</strong> shows what percentage of the total each value is.")) report_source_crispy_fields = [] for k in report_source_fields.keys(): if k in report_source_help_texts: report_source_crispy_fields.append(FieldWithHelpBubble( k, help_bubble_text=report_source_help_texts[k] )) else: report_source_crispy_fields.append(k) top_fields = [ FieldWithHelpBubble( 'report_name', help_bubble_text=_('Web users will see this name in the "Reports" section of CommCareHQ and can click to view the report')) ] if chart_type_crispy_field: top_fields.append(chart_type_crispy_field) self.helper.layout = crispy.Layout( crispy.Fieldset( _('{} Report'.format(self.report_type.capitalize())), *top_fields ), crispy.Fieldset( _('Data'), *report_source_crispy_fields ), hqcrispy.FormActions( StrictButton( _('Next'), type="submit", css_class="btn-primary", ) ), ) @property def sources_map(self): return self.app_source_helper.all_sources def get_selected_source(self): return self.app_source_helper.get_app_source(self.cleaned_data) def clean(self): """ Raise a validation error if there are already 5 data sources and this report won't be able to use one of the existing ones. """ cleaned_data = super(DataSourceForm, self).clean() existing_reports = ReportConfiguration.by_domain(self.domain) builder_reports = filter(lambda report: report.report_meta.created_by_builder, existing_reports) if len(builder_reports) >= self.max_allowed_reports: raise forms.ValidationError(_( "Too many reports!\n" "Creating this report would cause you to go over the maximum " "number of report builder reports allowed in this domain. Your" "limit is {number}. " "To continue, delete another report and try again. " ).format(number=self.max_allowed_reports)) return cleaned_data
class DataSourceForm(forms.Form): report_name = forms.CharField() chart_type = forms.ChoiceField(choices=[ ('bar', _('Bar')), ('pie', _("Pie")), ], ) def __init__(self, domain, report_type, *args, **kwargs): super(DataSourceForm, self).__init__(*args, **kwargs) self.domain = domain self.report_type = report_type self.app_source_helper = ApplicationDataSourceUIHelper() self.app_source_helper.bootstrap(self.domain) report_source_fields = self.app_source_helper.get_fields() report_source_help_texts = { "source_type": _("<strong>Form</strong>: display data from form submissions.<br/><strong>Case</strong>: display data from your cases. You must be using case management for this option." ), "application": _("Which application should the data come from?"), "source": _("Choose the case type or form from which to retrieve data for this report." ), } self.fields.update(report_source_fields) self.fields['chart_type'].required = self.report_type == "chart" self.helper = FormHelper() self.helper.form_class = "form-horizontal" self.helper.form_id = "report-builder-form" chart_type_crispy_field = None if self.report_type == 'chart': chart_type_crispy_field = FieldWithHelpBubble( 'chart_type', help_bubble_text= _("<strong>Bar</strong> shows one vertical bar for each value in your case or form. <strong>Pie</strong> shows what percentage of the total each value is." )) report_source_crispy_fields = [] for k in report_source_fields.keys(): if k in report_source_help_texts: report_source_crispy_fields.append( FieldWithHelpBubble( k, help_bubble_text=report_source_help_texts[k])) else: report_source_crispy_fields.append(k) self.helper.layout = crispy.Layout( crispy.Fieldset( _('{} Report'.format(self.report_type.capitalize())), FieldWithHelpBubble( 'report_name', help_bubble_text= _('Web users will see this name in the "Reports" section of CommCareHQ and can click to view the report' )), chart_type_crispy_field), crispy.Fieldset(_('Data'), *report_source_crispy_fields), FormActions( crispy.ButtonHolder( crispy.Submit( 'create_new_report_builder_btn', _('Next'), )), ), ) @property def sources_map(self): return self.app_source_helper.all_sources def get_selected_source(self): return self.app_source_helper.get_app_source(self.cleaned_data) def clean(self): """ Raise a validation error if there are already 5 data sources and this report won't be able to use one of the existing ones. """ cleaned_data = super(DataSourceForm, self).clean() source_type = cleaned_data.get('source_type') report_source = cleaned_data.get('report_source') app_id = cleaned_data.get('application') if report_source and source_type and app_id: app = Application.get(app_id) ds_builder = DataSourceBuilder(self.domain, app, source_type, report_source) existing_sources = DataSourceConfiguration.by_domain(self.domain) if len(existing_sources) >= 5: if not ds_builder.get_existing_match(): raise forms.ValidationError( _("Too many data sources!\n" "Creating this report would cause you to go over the maximum " "number of data sources allowed in this domain. The current " "limit is 5. " "To continue, delete all of the reports using a particular " "data source (or the data source itself) and try again. " )) return cleaned_data
class PerformanceMessageEditForm(forms.Form): recipient_id = forms.CharField() schedule = forms.ChoiceField(choices=[(choice, ugettext_lazy(choice)) for choice in SCHEDULE_CHOICES]) template = forms.CharField(widget=forms.Textarea) time_range = forms.ChoiceField( choices=[(choice.slug, choice.description) for choice in get_simple_dateranges()]) def __init__(self, domain, config, *args, **kwargs): self.domain = domain self.config = config def _to_initial(config): initial = copy.copy(config._doc) initial['schedule'] = config.schedule.interval if config.template_variables: initial['application'] = config.template_variables[0].app_id initial['source'] = config.template_variables[0].source_id initial['time_range'] = config.template_variables[0].time_range return initial super(PerformanceMessageEditForm, self).__init__(initial=_to_initial(config), *args, **kwargs) self.fields['recipient_id'] = GroupField(domain=domain, label=_('Recipient Group')) self.app_source_helper = ApplicationDataSourceUIHelper( enable_cases=False) self.app_source_helper.bootstrap(self.domain) data_source_fields = self.app_source_helper.get_fields() self.fields.update(data_source_fields) self.helper = _get_default_form_helper() form_layout = self.fields.keys() form_layout.append( hqcrispy.FormActions( StrictButton( _("Save Changes"), type="submit", css_class="btn btn-primary", ), )) self.helper.layout = Layout(*form_layout) def clean_template(self): return _clean_template(self.cleaned_data['template']) def clean_schedule(self): # todo: support other scheduling options return ScheduleConfiguration(interval=self.cleaned_data['schedule']) def save(self, commit=True): self.config.recipient_id = self.cleaned_data['recipient_id'] self.config.schedule = self.cleaned_data['schedule'] self.config.template = self.cleaned_data['template'] template_variable = TemplateVariable( type=self.cleaned_data['source_type'], time_range=self.cleaned_data['time_range'], source_id=self.cleaned_data['source'], app_id=self.cleaned_data['application'], ) self.config.template_variables = [template_variable] if commit: self.config.save() return self.config @property def app_id(self): if self.config.template_variables: return self.config.template_variables[0].app_id return '' @property def source_id(self): if self.config.template_variables: return self.config.template_variables[0].source_id return ''