""" Analytics app forms for CRUD operations. """ from django import forms from django.core.exceptions import ValidationError from django.utils import timezone from datetime import datetime, date from .models import ( Dashboard, DashboardWidget, DataSource, Report, MetricDefinition ) class DashboardForm(forms.ModelForm): """ Form for creating and updating dashboards. """ class Meta: model = Dashboard fields = [ 'name', 'description', 'dashboard_type', 'is_public', 'layout_config', 'refresh_interval', 'is_active' ] widgets = { 'name': forms.TextInput(attrs={ 'class': 'form-control', 'placeholder': 'Enter dashboard name' }), 'description': forms.Textarea(attrs={ 'class': 'form-control', 'rows': 3, 'placeholder': 'Enter dashboard description' }), 'dashboard_type': forms.Select(attrs={'class': 'form-control'}), 'is_public': forms.CheckboxInput(attrs={'class': 'form-check-input'}), 'layout_config': forms.Textarea(attrs={ 'class': 'form-control', 'rows': 5, 'placeholder': 'Enter JSON layout configuration' }), 'refresh_interval': forms.NumberInput(attrs={ 'class': 'form-control', 'min': 30, 'max': 3600, 'step': 30 }), 'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}) } help_texts = { 'name': 'Unique name for this dashboard', 'dashboard_type': 'Dashboard type for organization', 'is_public': 'Whether this dashboard is publicly accessible', 'layout_config': 'JSON configuration for dashboard layout', 'refresh_interval': 'Auto-refresh interval in seconds (30-3600)', } def clean_name(self): name = self.cleaned_data['name'] if len(name) < 3: raise ValidationError('Dashboard name must be at least 3 characters long.') return name def clean_refresh_interval(self): interval = self.cleaned_data['refresh_interval'] if interval and (interval < 30 or interval > 3600): raise ValidationError('Refresh interval must be between 30 and 3600 seconds.') return interval class DashboardWidgetForm(forms.ModelForm): """ Form for creating and updating dashboard widgets. """ class Meta: model = DashboardWidget fields = [ 'dashboard', 'name', 'widget_type', 'position_x', 'position_y', 'width', 'height', 'display_config', 'query_config', 'is_active' ] widgets = { 'dashboard': forms.Select(attrs={'class': 'form-control'}), 'name': forms.TextInput(attrs={ 'class': 'form-control', 'placeholder': 'Enter widget name' }), 'widget_type': forms.Select(attrs={'class': 'form-control'}), 'position_x': forms.NumberInput(attrs={ 'class': 'form-control', 'min': 0, 'max': 12 }), 'position_y': forms.NumberInput(attrs={ 'class': 'form-control', 'min': 0 }), 'width': forms.NumberInput(attrs={ 'class': 'form-control', 'min': 1, 'max': 12 }), 'height': forms.NumberInput(attrs={ 'class': 'form-control', 'min': 1, 'max': 20 }), 'display_config': forms.Textarea(attrs={ 'class': 'form-control', 'rows': 4, 'placeholder': 'Enter JSON display configuration' }), 'query_config': forms.Textarea(attrs={ 'class': 'form-control', 'rows': 3, 'placeholder': 'Enter query configuration' }), 'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}) } help_texts = { 'widget_type': 'Type of widget (chart, table, KPI, etc.)', 'position_x': 'Horizontal position (0-12 grid system)', 'position_y': 'Vertical position', 'width': 'Widget width (1-12 grid columns)', 'height': 'Widget height in grid rows', 'display_config': 'JSON configuration for widget display', 'query_config': 'Query configuration for widget content', } def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) super().__init__(*args, **kwargs) if user: self.fields['dashboard'].queryset = Dashboard.objects.filter( tenant=user.tenant ).order_by('name') def clean_position_x(self): x = self.cleaned_data['position_x'] if x < 0 or x > 12: raise ValidationError('Position X must be between 0 and 12.') return x def clean_width(self): width = self.cleaned_data['width'] if width < 1 or width > 12: raise ValidationError('Width must be between 1 and 12.') return width class DataSourceForm(forms.ModelForm): """ Form for creating and updating data sources. """ class Meta: model = DataSource fields = [ 'name', 'description', 'source_type', 'connection_config', 'authentication_config', 'query_template', 'cache_duration', 'is_active' ] widgets = { 'name': forms.TextInput(attrs={ 'class': 'form-control', 'placeholder': 'Enter data source name' }), 'description': forms.Textarea(attrs={ 'class': 'form-control', 'rows': 3, 'placeholder': 'Enter data source description' }), 'source_type': forms.Select(attrs={'class': 'form-control'}), 'connection_config': forms.Textarea(attrs={ 'class': 'form-control', 'rows': 4, 'placeholder': 'Enter JSON connection configuration' }), 'authentication_config': forms.Textarea(attrs={ 'class': 'form-control', 'rows': 3, 'placeholder': 'Enter JSON authentication configuration' }), 'query_template': forms.Textarea(attrs={ 'class': 'form-control', 'rows': 4, 'placeholder': 'Enter query template' }), 'cache_duration': forms.NumberInput(attrs={ 'class': 'form-control', 'min': 0, 'max': 86400, 'value': 300 }), 'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}) } help_texts = { 'name': 'Unique name for this data source', 'source_type': 'Type of data source (database, API, file, etc.)', 'connection_config': 'JSON configuration for connection settings', 'authentication_config': 'JSON configuration for authentication', 'cache_duration': 'Cache duration in seconds (0-86400)', } def clean_name(self): name = self.cleaned_data['name'] if len(name) < 3: raise ValidationError('Data source name must be at least 3 characters long.') return name def clean_cache_duration(self): cache_duration = self.cleaned_data['cache_duration'] if cache_duration < 0 or cache_duration > 86400: raise ValidationError('Cache duration must be between 0 and 86400 seconds.') return cache_duration class ReportForm(forms.ModelForm): """ Form for creating and updating reports. """ class Meta: model = Report fields = [ 'name', 'description', 'report_type', 'data_source', 'query_config', 'output_format', 'template_config', 'schedule_config', 'is_active' ] widgets = { 'name': forms.TextInput(attrs={ 'class': 'form-control', 'placeholder': 'Enter report name' }), 'description': forms.Textarea(attrs={ 'class': 'form-control', 'rows': 3, 'placeholder': 'Enter report description' }), 'report_type': forms.Select(attrs={'class': 'form-control'}), 'data_source': forms.Select(attrs={'class': 'form-control'}), 'query_config': forms.Textarea(attrs={ 'class': 'form-control', 'rows': 8, 'placeholder': 'Enter query configuration' }), 'template_config': forms.Textarea(attrs={ 'class': 'form-control', 'rows': 4, 'placeholder': 'Enter JSON template configuration' }), 'output_format': forms.Select(attrs={'class': 'form-control'}), 'schedule_config': forms.Textarea(attrs={ 'class': 'form-control', 'rows': 3, 'placeholder': 'Enter JSON schedule configuration' }), 'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}) } help_texts = { 'name': 'Unique name for this report', 'report_type': 'Report type for organization', 'query_config': 'Query configuration for report data', 'template_config': 'Template configuration for report formatting', 'output_format': 'Default output format for report', 'schedule_config': 'JSON configuration for automated scheduling', } def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) super().__init__(*args, **kwargs) if user: self.fields['data_source'].queryset = DataSource.objects.filter( tenant=user.tenant, is_active=True ).order_by('name') def clean_report_name(self): name = self.cleaned_data['report_name'] if len(name) < 3: raise ValidationError('Report name must be at least 3 characters long.') return name def clean_query_definition(self): query = self.cleaned_data['query_definition'] if len(query.strip()) < 10: raise ValidationError('Query definition must be at least 10 characters long.') return query class MetricDefinitionForm(forms.ModelForm): """ Form for creating and updating metric definitions. """ class Meta: model = MetricDefinition fields = [ 'name', 'description', 'metric_type', 'data_source', 'calculation_config', 'aggregation_period', 'unit_of_measure', 'target_value', 'warning_threshold', 'critical_threshold', 'aggregation_config', 'is_active' ] widgets = { 'name': forms.TextInput(attrs={ 'class': 'form-control', 'placeholder': 'Enter metric name' }), 'description': forms.Textarea(attrs={ 'class': 'form-control', 'rows': 3, 'placeholder': 'Enter metric description' }), 'metric_type': forms.Select(attrs={'class': 'form-control'}), 'data_source': forms.Select(attrs={'class': 'form-control'}), 'calculation_config': forms.Textarea(attrs={ 'class': 'form-control', 'rows': 6, 'placeholder': 'Enter calculation configuration' }), 'aggregation_period': forms.Select(attrs={'class': 'form-control'}), 'unit_of_measure': forms.TextInput(attrs={ 'class': 'form-control', 'placeholder': 'e.g., %, count, minutes, dollars' }), 'target_value': forms.NumberInput(attrs={ 'class': 'form-control', 'step': 'any', 'placeholder': 'Target value for this metric' }), 'warning_threshold': forms.NumberInput(attrs={ 'class': 'form-control', 'step': 'any', 'placeholder': 'Warning threshold value' }), 'critical_threshold': forms.NumberInput(attrs={ 'class': 'form-control', 'step': 'any', 'placeholder': 'Critical threshold value' }), 'aggregation_config': forms.Textarea(attrs={ 'class': 'form-control', 'rows': 3, 'placeholder': 'Enter aggregation configuration' }), 'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}) } help_texts = { 'name': 'Unique name for this metric', 'metric_type': 'Metric type for organization', 'calculation_config': 'Configuration for metric calculation', 'aggregation_period': 'Period for metric aggregation', 'unit_of_measure': 'Unit of measurement for metric values', 'target_value': 'Target or goal value for this metric', 'warning_threshold': 'Value that triggers warning alerts', 'critical_threshold': 'Value that triggers critical alerts', 'aggregation_config': 'Configuration for metric aggregation', } def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) super().__init__(*args, **kwargs) if user: self.fields['data_source'].queryset = DataSource.objects.filter( tenant=user.tenant, is_active=True ).order_by('source_name') def clean_metric_name(self): name = self.cleaned_data['metric_name'] if len(name) < 3: raise ValidationError('Metric name must be at least 3 characters long.') return name def clean_query_definition(self): query = self.cleaned_data['query_definition'] if len(query.strip()) < 5: raise ValidationError('Query definition must be at least 5 characters long.') return query def clean(self): cleaned_data = super().clean() target = cleaned_data.get('target_value') warning = cleaned_data.get('threshold_warning') critical = cleaned_data.get('threshold_critical') # Validate threshold relationships if target and warning and critical: if warning == critical: raise ValidationError('Warning and critical thresholds must be different.') return cleaned_data # from django import forms # from django.core.exceptions import ValidationError # from django.utils import timezone # from crispy_forms.helper import FormHelper # from crispy_forms.layout import Layout, Fieldset, Submit, Row, Column, HTML, Div # from crispy_forms.bootstrap import FormActions # import json # # from .models import Dashboard, DashboardWidget, DataSource, Report, MetricDefinition # from core.models import Tenant # # # class ReportGenerationForm(forms.ModelForm): # """ # Form for report generation configuration # """ # parameters = forms.CharField( # required=False, # widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 4}) # ) # output_format = forms.ChoiceField( # choices=[ # ('pdf', 'PDF'), # ('excel', 'Excel'), # ('csv', 'CSV'), # ('json', 'JSON') # ], # required=True, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # schedule_execution = forms.BooleanField( # required=False, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # execution_time = forms.DateTimeField( # required=False, # widget=forms.DateTimeInput(attrs={'class': 'form-control', 'type': 'datetime-local'}) # ) # email_recipients = forms.CharField( # required=False, # widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 3}) # ) # # class Meta: # model = Report # fields = [ # 'name', 'description', 'report_type', 'data_sources', # 'parameters', 'output_format', 'schedule_execution', # 'execution_time', 'email_recipients' # ] # widgets = { # 'name': forms.TextInput(attrs={'class': 'form-control'}), # 'description': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), # 'report_type': forms.Select(attrs={'class': 'form-control'}), # 'data_sources': forms.CheckboxSelectMultiple(attrs={'class': 'form-check-input'}) # } # # def __init__(self, *args, **kwargs): # tenant = kwargs.pop('tenant', None) # super().__init__(*args, **kwargs) # # if tenant: # self.fields['data_sources'].queryset = DataSource.objects.filter(tenant=tenant) # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Report Configuration', # Row( # Column('name', css_class='form-group col-md-6 mb-0'), # Column('report_type', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # 'description', # 'data_sources', # 'parameters' # ), # Fieldset( # 'Output Settings', # Row( # Column('output_format', css_class='form-group col-md-6 mb-0'), # Column('email_recipients', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ) # ), # Fieldset( # 'Scheduling', # HTML('
'), # 'schedule_execution', # HTML( # ''), # HTML('
'), # 'execution_time' # ), # FormActions( # Submit('submit', 'Generate Report', css_class='btn btn-primary'), # HTML('Cancel') # ) # ) # # def clean_parameters(self): # parameters = self.cleaned_data.get('parameters') # if parameters: # try: # json.loads(parameters) # except json.JSONDecodeError: # raise ValidationError('Parameters must be valid JSON.') # return parameters # # def clean(self): # cleaned_data = super().clean() # schedule_execution = cleaned_data.get('schedule_execution') # execution_time = cleaned_data.get('execution_time') # # if schedule_execution and not execution_time: # raise ValidationError('Execution time is required when scheduling execution.') # # return cleaned_data # # # class DashboardCreationForm(forms.ModelForm): # """ # Form for dashboard creation # """ # layout_template = forms.ChoiceField( # choices=[ # ('grid_2x2', '2x2 Grid'), # ('grid_3x3', '3x3 Grid'), # ('sidebar_main', 'Sidebar + Main'), # ('top_bottom', 'Top + Bottom'), # ('custom', 'Custom Layout') # ], # required=True, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # copy_from_dashboard = forms.ModelChoiceField( # queryset=None, # required=False, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # # class Meta: # model = Dashboard # fields = [ # 'name', 'description', 'dashboard_type', 'layout_template', # 'refresh_interval', 'is_public', 'allowed_roles', # 'copy_from_dashboard' # ] # widgets = { # 'name': forms.TextInput(attrs={'class': 'form-control'}), # 'description': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), # 'dashboard_type': forms.Select(attrs={'class': 'form-control'}), # 'refresh_interval': forms.NumberInput(attrs={'class': 'form-control'}), # 'is_public': forms.CheckboxInput(attrs={'class': 'form-check-input'}), # 'allowed_roles': forms.Textarea(attrs={'class': 'form-control', 'rows': 2}) # } # # def __init__(self, *args, **kwargs): # tenant = kwargs.pop('tenant', None) # super().__init__(*args, **kwargs) # # if tenant: # self.fields['copy_from_dashboard'].queryset = Dashboard.objects.filter( # tenant=tenant, # is_active=True # ) # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Dashboard Information', # Row( # Column('name', css_class='form-group col-md-6 mb-0'), # Column('dashboard_type', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # 'description' # ), # Fieldset( # 'Layout Configuration', # Row( # Column('layout_template', css_class='form-group col-md-6 mb-0'), # Column('refresh_interval', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # 'copy_from_dashboard' # ), # Fieldset( # 'Access Control', # HTML('
'), # 'is_public', # HTML(''), # HTML('
'), # 'allowed_roles' # ), # FormActions( # Submit('submit', 'Create Dashboard', css_class='btn btn-primary'), # HTML('Cancel') # ) # ) # # # class DataSourceConfigurationForm(forms.ModelForm): # """ # Form for data source configuration # """ # test_connection = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # # class Meta: # model = DataSource # fields = [ # 'name', 'description', 'source_type', 'connection_config', # 'query_config', 'refresh_interval', 'is_active', # 'test_connection' # ] # widgets = { # 'name': forms.TextInput(attrs={'class': 'form-control'}), # 'description': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), # 'source_type': forms.Select(attrs={'class': 'form-control'}), # 'connection_config': forms.Textarea(attrs={'class': 'form-control', 'rows': 5}), # 'query_config': forms.Textarea(attrs={'class': 'form-control', 'rows': 5}), # 'refresh_interval': forms.NumberInput(attrs={'class': 'form-control'}), # 'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}) # } # # def __init__(self, *args, **kwargs): # super().__init__(*args, **kwargs) # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Data Source Information', # Row( # Column('name', css_class='form-group col-md-6 mb-0'), # Column('source_type', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # 'description' # ), # Fieldset( # 'Connection Configuration', # 'connection_config', # HTML('Enter connection details in JSON format') # ), # Fieldset( # 'Query Configuration', # 'query_config', # HTML('Enter query configuration in JSON format') # ), # Fieldset( # 'Settings', # Row( # Column('refresh_interval', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # HTML('
'), # 'is_active', # HTML(''), # HTML('
'), # HTML('
'), # 'test_connection', # HTML(''), # HTML('
') # ), # FormActions( # Submit('submit', 'Save Data Source', css_class='btn btn-primary'), # HTML('Cancel') # ) # ) # # def clean_connection_config(self): # config = self.cleaned_data.get('connection_config') # if config: # try: # json.loads(config) # except json.JSONDecodeError: # raise ValidationError('Connection configuration must be valid JSON.') # return config # # def clean_query_config(self): # config = self.cleaned_data.get('query_config') # if config: # try: # json.loads(config) # except json.JSONDecodeError: # raise ValidationError('Query configuration must be valid JSON.') # return config # # # class MetricCalculationForm(forms.ModelForm): # """ # Form for metric calculation configuration # """ # calculate_now = forms.BooleanField( # required=False, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # date_range_start = forms.DateField( # required=False, # widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) # ) # date_range_end = forms.DateField( # required=False, # widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) # ) # # class Meta: # model = MetricDefinition # fields = [ # 'name', 'description', 'metric_type', 'data_source', # 'calculation_config', 'aggregation_period', 'target_value', # 'warning_threshold', 'critical_threshold', 'unit_of_measure', # 'calculate_now', 'date_range_start', 'date_range_end' # ] # widgets = { # 'name': forms.TextInput(attrs={'class': 'form-control'}), # 'description': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), # 'metric_type': forms.Select(attrs={'class': 'form-control'}), # 'data_source': forms.Select(attrs={'class': 'form-control'}), # 'calculation_config': forms.Textarea(attrs={'class': 'form-control', 'rows': 4}), # 'aggregation_period': forms.Select(attrs={'class': 'form-control'}), # 'target_value': forms.NumberInput(attrs={'class': 'form-control'}), # 'warning_threshold': forms.NumberInput(attrs={'class': 'form-control'}), # 'critical_threshold': forms.NumberInput(attrs={'class': 'form-control'}), # 'unit_of_measure': forms.TextInput(attrs={'class': 'form-control'}) # } # # def __init__(self, *args, **kwargs): # tenant = kwargs.pop('tenant', None) # super().__init__(*args, **kwargs) # # if tenant: # self.fields['data_source'].queryset = DataSource.objects.filter(tenant=tenant) # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Metric Definition', # Row( # Column('name', css_class='form-group col-md-6 mb-0'), # Column('metric_type', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # 'description', # Row( # Column('data_source', css_class='form-group col-md-6 mb-0'), # Column('aggregation_period', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # 'calculation_config' # ), # Fieldset( # 'Thresholds and Targets', # Row( # Column('target_value', css_class='form-group col-md-4 mb-0'), # Column('warning_threshold', css_class='form-group col-md-4 mb-0'), # Column('critical_threshold', css_class='form-group col-md-4 mb-0'), # css_class='form-row' # ), # 'unit_of_measure' # ), # Fieldset( # 'Calculation Options', # HTML('
'), # 'calculate_now', # HTML(''), # HTML('
'), # Row( # Column('date_range_start', css_class='form-group col-md-6 mb-0'), # Column('date_range_end', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ) # ), # FormActions( # Submit('submit', 'Save Metric', css_class='btn btn-primary'), # HTML('Cancel') # ) # ) # # def clean_calculation_config(self): # config = self.cleaned_data.get('calculation_config') # if config: # try: # json.loads(config) # except json.JSONDecodeError: # raise ValidationError('Calculation configuration must be valid JSON.') # return config # # # class QualityAssuranceForm(forms.Form): # """ # Form for quality assurance configuration # """ # check_data_accuracy = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # validate_calculations = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # verify_data_sources = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # check_performance = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # generate_qa_report = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # qa_threshold = forms.DecimalField( # max_digits=5, # decimal_places=2, # initial=95.0, # widget=forms.NumberInput(attrs={'class': 'form-control'}) # ) # # def __init__(self, *args, **kwargs): # super().__init__(*args, **kwargs) # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Quality Assurance Checks', # HTML('
'), # 'check_data_accuracy', # HTML(''), # HTML('
'), # HTML('
'), # 'validate_calculations', # HTML(''), # HTML('
'), # HTML('
'), # 'verify_data_sources', # HTML(''), # HTML('
'), # HTML('
'), # 'check_performance', # HTML(''), # HTML('
'), # HTML('
'), # 'generate_qa_report', # HTML(''), # HTML('
') # ), # Fieldset( # 'Quality Threshold', # 'qa_threshold', # HTML('Minimum quality score percentage (0-100)') # ), # FormActions( # Submit('submit', 'Start Quality Check', css_class='btn btn-primary'), # HTML('Cancel') # ) # ) # # # class DistributionForm(forms.Form): # """ # Form for report distribution configuration # """ # distribution_method = forms.ChoiceField( # choices=[ # ('email', 'Email'), # ('download', 'Download Link'), # ('ftp', 'FTP Upload'), # ('api', 'API Endpoint'), # ('dashboard', 'Dashboard Publication') # ], # required=True, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # recipients = forms.CharField( # required=False, # widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 4}) # ) # subject = forms.CharField( # required=False, # widget=forms.TextInput(attrs={'class': 'form-control'}) # ) # message = forms.CharField( # required=False, # widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 4}) # ) # schedule_distribution = forms.BooleanField( # required=False, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # distribution_time = forms.DateTimeField( # required=False, # widget=forms.DateTimeInput(attrs={'class': 'form-control', 'type': 'datetime-local'}) # ) # # def __init__(self, *args, **kwargs): # super().__init__(*args, **kwargs) # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Distribution Method', # 'distribution_method', # 'recipients', # HTML('Enter email addresses separated by commas') # ), # Fieldset( # 'Message Content', # 'subject', # 'message' # ), # Fieldset( # 'Scheduling', # HTML('
'), # 'schedule_distribution', # HTML(''), # HTML('
'), # 'distribution_time' # ), # FormActions( # Submit('submit', 'Distribute Report', css_class='btn btn-primary'), # HTML('Cancel') # ) # ) # # def clean(self): # cleaned_data = super().clean() # distribution_method = cleaned_data.get('distribution_method') # recipients = cleaned_data.get('recipients') # schedule_distribution = cleaned_data.get('schedule_distribution') # distribution_time = cleaned_data.get('distribution_time') # # if distribution_method == 'email' and not recipients: # raise ValidationError('Recipients are required for email distribution.') # # if schedule_distribution and not distribution_time: # raise ValidationError('Distribution time is required when scheduling distribution.') # # return cleaned_data # # # class VisualizationForm(forms.Form): # """ # Form for visualization configuration # """ # chart_type = forms.ChoiceField( # choices=[ # ('line', 'Line Chart'), # ('bar', 'Bar Chart'), # ('pie', 'Pie Chart'), # ('scatter', 'Scatter Plot'), # ('heatmap', 'Heat Map'), # ('gauge', 'Gauge'), # ('table', 'Data Table') # ], # required=True, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # title = forms.CharField( # required=True, # widget=forms.TextInput(attrs={'class': 'form-control'}) # ) # x_axis_label = forms.CharField( # required=False, # widget=forms.TextInput(attrs={'class': 'form-control'}) # ) # y_axis_label = forms.CharField( # required=False, # widget=forms.TextInput(attrs={'class': 'form-control'}) # ) # color_scheme = forms.ChoiceField( # choices=[ # ('default', 'Default'), # ('blue', 'Blue Theme'), # ('green', 'Green Theme'), # ('red', 'Red Theme'), # ('purple', 'Purple Theme'), # ('custom', 'Custom Colors') # ], # required=True, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # show_legend = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # show_grid = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # # def __init__(self, *args, **kwargs): # super().__init__(*args, **kwargs) # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Chart Configuration', # Row( # Column('chart_type', css_class='form-group col-md-6 mb-0'), # Column('color_scheme', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # 'title' # ), # Fieldset( # 'Axis Labels', # Row( # Column('x_axis_label', css_class='form-group col-md-6 mb-0'), # Column('y_axis_label', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ) # ), # Fieldset( # 'Display Options', # HTML('
'), # 'show_legend', # HTML(''), # HTML('
'), # HTML('
'), # 'show_grid', # HTML(''), # HTML('
') # ), # FormActions( # Submit('submit', 'Create Visualization', css_class='btn btn-primary'), # HTML('Cancel') # ) # ) # # # class AnalysisForm(forms.Form): # """ # Form for data analysis configuration # """ # analysis_type = forms.ChoiceField( # choices=[ # ('descriptive', 'Descriptive Analysis'), # ('trend', 'Trend Analysis'), # ('correlation', 'Correlation Analysis'), # ('regression', 'Regression Analysis'), # ('forecasting', 'Forecasting'), # ('anomaly', 'Anomaly Detection') # ], # required=True, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # data_source = forms.ModelChoiceField( # queryset=None, # required=True, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # date_range_start = forms.DateField( # required=True, # widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) # ) # date_range_end = forms.DateField( # required=True, # widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) # ) # confidence_level = forms.DecimalField( # max_digits=5, # decimal_places=2, # initial=95.0, # widget=forms.NumberInput(attrs={'class': 'form-control'}) # ) # generate_insights = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # # def __init__(self, *args, **kwargs): # tenant = kwargs.pop('tenant', None) # super().__init__(*args, **kwargs) # # if tenant: # self.fields['data_source'].queryset = DataSource.objects.filter(tenant=tenant) # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Analysis Configuration', # Row( # Column('analysis_type', css_class='form-group col-md-6 mb-0'), # Column('data_source', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # Row( # Column('date_range_start', css_class='form-group col-md-6 mb-0'), # Column('date_range_end', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # 'confidence_level' # ), # Fieldset( # 'Options', # HTML('
'), # 'generate_insights', # HTML(''), # HTML('
') # ), # FormActions( # Submit('submit', 'Start Analysis', css_class='btn btn-primary'), # HTML('Cancel') # ) # ) #