def clean(self): data = super(EmailActionForm, self).clean() email_column = self.cleaned_data['email_column'] # Check if the values in the email column are correct emails try: column_data = execute_select_on_table(self.action.workflow.id, [], [], column_names=[email_column]) if not all([validate_email(x[0]) for x in column_data]): # column has incorrect email addresses self.add_error( 'email_column', _('The column with email addresses has incorrect values.')) except TypeError: self.add_error( 'email_column', _('The column with email addresses has incorrect values.')) if not all([ validate_email(x) for x in self.cleaned_data['cc_email'].split(',') if x ]): self.add_error('cc_email', _('Field needs a comma-separated list of emails.')) if not all([ validate_email(x) for x in self.cleaned_data['bcc_email'].split(',') if x ]): self.add_error('bcc_email', _('Field needs a comma-separated list of emails.')) return data
def scheduled_email_action_data_is_correct(action, cleaned_data): """ Verify the integrity of a ScheduledAction object with a Personalised_text type. The function returns a list of pairs (field name, message) with the errors, or [] if no error has been found. :param cleaned_data: :return: List of pairs (field name, error) or [] if correct """ result = [] item_column = cleaned_data['item_column'] # Verify the correct time result.extend(scheduled_action_data_is_correct(cleaned_data)) # Check if the values in the email column are correct emails try: column_data = execute_select_on_table( action.workflow.id, [], [], column_names=[item_column.name]) if not all([validate_email(x[0]) for x in column_data]): # column has incorrect email addresses result.append( ('item_column', _('The column with email addresses has incorrect values.')) ) except TypeError: result.append( ('item_column', _('The column with email addresses has incorrect values.')) ) if not all([validate_email(x) for x in cleaned_data['cc_email'].split(',') if x]): result.append( ('cc_email', _('This field must be a comma-separated list of emails.')) ) if not all([validate_email(x) for x in cleaned_data['bcc_email'].split(',') if x]): result.append( ('bcc_email', _('This field must be a comma-separated list of emails.')) ) return result
def extra_validation(self, validated_data): action, execute, item_column, exclude_values, payload = \ super(ScheduledEmailSerializer, self).extra_validation( validated_data ) if action.action_type != Action.PERSONALIZED_TEXT: raise APIException(_('Incorrect type of action to schedule.')) subject = payload.get('subject') if not subject: raise APIException(_('Personalized text needs a subject.')) if not item_column: raise APIException(_('Personalized text needs a item_column')) # Check if the values in the email column are correct emails try: column_data = execute_select_on_table( action.workflow.id, [], [], column_names=[item_column.name]) if not all([validate_email(x[0]) for x in column_data]): # column has incorrect email addresses raise APIException( _('The column with email addresses has incorrect values.')) except TypeError: raise APIException( _('The column with email addresses has incorrect values.')) if not all( [validate_email(x) for x in payload.get('cc_email', []) if x]): raise APIException( _('cc_email must be a comma-separated list of emails.')) if not all( [validate_email(x) for x in payload.get('bcc_email', []) if x]): raise APIException( _('bcc_email must be a comma-separated list of emails.')) return action, execute, item_column, exclude_values, payload
def get_row_visualisations(request, view_id=None): # If there is no workflow object, go back to the index workflow = get_workflow(request) if not workflow: return redirect('workflow:index') # If the workflow has no data, something went wrong, go back to the # workflow details page if workflow.nrows == 0: return redirect('worflow:detail', workflow.id) # Get the pair key,value to fetch the row from the table update_key = request.GET.get('key', None) update_val = request.GET.get('val', None) if not update_key or not update_val: # Malformed request return render(request, 'error.html', {'message': _('Unable to visualize table row')}) # If a view is given, filter the columns columns_to_view = workflow.columns.all() column_names = None if view_id: try: view = View.objects.get(pk=view_id) except ObjectDoesNotExist: # View not found. Redirect to workflow detail return redirect('workflow:detail', workflow.id) columns_to_view = view.columns.all() column_names = [c.name for c in columns_to_view] df = pandas_db.load_from_db(workflow.id, column_names, view.formula) else: # No view given, fetch the entire data frame df = pandas_db.load_from_db(workflow.id) # Get the rows from the table row = pandas_db.execute_select_on_table(workflow.id, [update_key], [update_val], column_names)[0] vis_scripts = [] visualizations = [] idx = -1 context = {'style': 'width:400px; height:225px;'} for column in columns_to_view: idx += 1 # Skip primary keys (no point to represent any of them) if column.is_key: continue # Add the title and surrounding container visualizations.append('<h4>' + column.name + '</h4>') # If all values are empty, no need to proceed if all([not x for x in df[column.name]]): visualizations.append("<p>" + _('No values in this column') + "</p><hr/>") continue if row[idx] is None or row[idx] == '': visualizations.append( '<p class="alert-warning">' + \ _('No value for this student in this column</p>') ) visualizations.append('<div style="display: inline-flex;">') v = get_column_visualisations(column, df[[column.name]], vis_scripts=vis_scripts, id='column_{0}'.format(idx), single_val=row[idx], context=context) visualizations.extend([x.html_content for x in v]) visualizations.append('</div><hr/>') return render( request, 'table/stat_row.html', { 'value': update_val, 'vis_scripts': vis_scripts, 'visualizations': visualizations })
def row_update(request): """ Receives a POST request to update a row in the data table :param request: Request object with all the data. :return: """ # If there is no workflow object, go back to the index workflow = get_workflow(request) if not workflow: return redirect('workflow:index') # If the workflow has no data, something went wrong, go back to the # dataops home if workflow.nrows == 0: return redirect('dataops:list') # Get the pair key,value to fetch the row from the table update_key = request.GET.get('update_key', None) update_val = request.GET.get('update_val', None) if not update_key or not update_val: # Malformed request return render(request, 'error.html', {'message': 'Unable to update table row'}) # Get the rows from the table rows = pandas_db.execute_select_on_table(workflow.id, [update_key], [update_val]) row_form = RowForm(request.POST or None, workflow=workflow, initial_values=list(rows[0])) if request.method == 'GET' or not row_form.is_valid(): return render( request, 'dataops/row_filter.html', { 'workflow': workflow, 'row_form': row_form, 'cancel_url': reverse('table:display') }) # This is a valid POST request # Create the query to update the row set_fields = [] set_values = [] columns = workflow.get_columns() unique_names = [c.name for c in columns if c.is_key] unique_field = None unique_value = None log_payload = [] for idx, col in enumerate(columns): value = row_form.cleaned_data[field_prefix + '%s' % idx] set_fields.append(col.name) set_values.append(value) log_payload.append((col.name, str(value))) if not unique_field and col.name in unique_names: unique_field = col.name unique_value = value # If there is no unique key, something went wrong. if not unique_field: raise Exception('Key value not found when updating row') pandas_db.update_row(workflow.id, set_fields, set_values, [unique_field], [unique_value]) # Log the event logs.ops.put(request.user, 'tablerow_update', workflow, { 'id': workflow.id, 'name': workflow.name, 'new_values': log_payload }) return redirect('table:display')