Beispiel #1
0
    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
Beispiel #2
0
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
Beispiel #3
0
    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
Beispiel #4
0
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
        })
Beispiel #5
0
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')