Esempio n. 1
0
def vis_html_content(context, column_name):
    # Get the action
    action = context.get(action_context_var, None)
    if not action:
        raise Exception(_('Action object not found when processing tag'))
    workflow = action.workflow

    # Check if the column is correct
    if not Column.objects.filter(workflow=workflow, name=column_name).exists():
        raise Exception(_('Column {0} does not exist').format(column_name))

    # Get the visualization number to generate unique IDs
    viz_number = context[viz_number_context_var]

    # Create the context for the visualization
    viz_ctx = {
        'style': 'width:400px; height:225px;',
        'id': 'viz_tag_{0}'.format(viz_number)
    }

    # If there is a column name in the context, insert it as individual value
    # If the template is simply being saved and rendered to detect syntax
    # errors, we may not have the data of an individual, so we have to relax
    # this restriction.
    ivalue = context.get(tr_item(column_name), None)
    if ivalue is not None:
        viz_ctx['individual_value'] = ivalue

    # Get the condition filter
    try:
        cond_filter = Condition.objects.get(action__id=action.id,
                                            is_filter=True)
    except ObjectDoesNotExist:
        cond_filter = None

    # Get the data from the data frame
    df = pandas_db.get_subframe(workflow.id, cond_filter, [column_name])
    # Get the visualisation
    viz = PlotlyColumnHistogram(data=df, context=viz_ctx)

    prefix = ''
    if viz_number == 0:
        prefix = ''.join([
            '<script src="{0}"></script>'.format(x)
            for x in PlotlyColumnHistogram.get_engine_scripts()
        ])

    # Update viz number
    context[viz_number_context_var] = viz_number + 1

    # Return the rendering of the viz marked as safe
    return mark_safe(prefix + viz.render())
Esempio n. 2
0
def csvdownload(request, pk=None):
    """

    :param request: HTML request
    :param pk: If given, the PK of the view to subset the table
    :return: Return a CSV download of the data in the table
    """

    # Get the appropriate workflow object
    workflow = get_workflow(request)
    if not workflow:
        return redirect('workflow:index')

    # Check if dataframe is present
    if not ops.workflow_id_has_table(workflow.id):
        # Go back to show the workflow detail
        return redirect(reverse('workflow:detail',
                                kwargs={'pk': workflow.id}))

    # Get the columns from the view (if given)
    view = None
    if pk:
        try:
            view = View.objects.filter(
                Q(workflow__user=request.user) |
                Q(workflow__shared=request.user)
            ).distinct().prefetch_related('columns').get(pk=pk)
        except ObjectDoesNotExist:
            # Go back to show the workflow detail
            return redirect(reverse('workflow:detail',
                                    kwargs={'pk': workflow.id}))

    # Fetch the data frame
    if view:
        col_names = [x.name for x in view.columns.all()]
    else:
        col_names = workflow.get_column_names()
    data_frame = pandas_db.get_subframe(workflow.id, view, col_names)

    # Create the response object
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = \
        'attachment; filename="ontask_table.csv"'

    # Dump the data frame as the content of the response object
    data_frame.to_csv(path_or_buf=response,
                      sep=str(','),
                      index=False,
                      encoding='utf-8')

    return response
Esempio n. 3
0
def evaluate_action(action, extra_string, column_name):
    """
    Given an action object and an optional string:
    1) Access the attached workflow
    2) Obtain the data from the appropriate data frame
    3) Loop over each data row and
      3.1) Evaluate the conditions with respect to the values in the row
      3.2) Create a context with the result of evaluating the conditions,
           attributes and column names to values
      3.3) Run the template with the context
      3.4) Run the optional string argument with the template and the context
      3.5) Select the optional column_name
    6) Return the resulting objects:
       List of (HTMLs body, extra string, column name value)
        or an error message

    :param action: Action object with pointers to conditions, filter,
                   workflow, etc.
    :param extra_string: An extra string to process (something like the email
           subject line) with the same dictionary as the text in the action.
    :param column_name: Column from where to extract the special value (
           typically the email address) and include it in the result.
    :return: list of lists resulting from the evaluation of the action
    """

    # Step 1: Get the workflow to access the data and prepare data
    workflow = Workflow.objects.get(pk=action.workflow.id)
    col_names = workflow.get_column_names()
    col_idx = -1
    if column_name and column_name in col_names:
        col_idx = col_names.index(column_name)

    # Step 2: Get the row of data from the DB
    try:
        cond_filter = Condition.objects.get(action__id=action.id,
                                            is_filter=True)
    except ObjectDoesNotExist:
        cond_filter = None

    # Step 3: Get the table data
    result = []
    data_frame = pandas_db.get_subframe(workflow.id, cond_filter)

    # Check if the values in the email column are correct emails
    try:
        correct_emails = all(
            [validate_email(x) for x in data_frame[column_name]])
        if not correct_emails:
            # column has incorrect email addresses
            return 'The column with email addresses has incorrect values.'
    except TypeError:
        return 'The column with email addresses has incorrect values'

    for _, row in data_frame.iterrows():

        # Get the dict(col_name, value)
        row_values = dict(zip(col_names, row))

        # Step 3: Evaluate all the conditions
        condition_eval = {}
        for condition in Condition.objects.filter(action__id=action.id).values(
                'is_filter', 'formula', 'name'):
            if condition['is_filter']:
                # Filter can be skipped in this stage
                continue

            # Evaluate the condition
            condition_eval[condition['name']] = \
                dataops.formula_evaluation.evaluate_top_node(
                    condition['formula'],
                    row_values
                )

        # Step 4: Create the context with the attributes, the evaluation of the
        # conditions and the values of the columns.
        attributes = workflow.attributes
        context = dict(dict(row_values, **condition_eval), **attributes)

        # Step 5: run the template with the given context
        # Render the text and append to result
        try:
            partial_result = [render_template(action.content, context, action)]
        except Exception as e:
            return 'Syntax error detected in the action text. ' + e.message

        # If there is extra message, render with context and create tuple
        if extra_string:
            try:
                partial_result.append(render_template(extra_string, context))
            except Exception as e:
                return 'Syntax error detected in the subject. ' + e.message

        # If column_name was given (and it exists), create a tuple with that
        # element as the third component
        if col_idx != -1:
            partial_result.append(row_values[col_names[col_idx]])

        # Append result
        result.append(partial_result)

    return result
def evaluate_action_canvas(action, extra_string, column_name):
    
    # Step 1: Get the workflow to access the data and prepare data
    workflow = Workflow.objects.get(pk=action.workflow.id)
    col_names = workflow.get_column_names()
    col_idx = -1
    if column_name and column_name in col_names:
        col_idx = col_names.index(column_name)

    # Step 2: Get the row of data from the DB
    try:
        cond_filter = Condition.objects.get(action__id=action.id,
                                            is_filter=True)
    except ObjectDoesNotExist:
        cond_filter = None

    # Step 3: Get the table data
    result = []
    data_frame = pandas_db.get_subframe(workflow.id, cond_filter)


    for _, row in data_frame.iterrows():

        # Get the dict(col_name, value)
        row_values = dict(zip(col_names, row))

        # Step 3: Evaluate all the conditions
        condition_eval = {}
        for condition in Condition.objects.filter(
                action__id=action.id
        ).values('is_filter', 'formula', 'name'):
            if condition['is_filter']:
                # Filter can be skipped in this stage
                continue

            # Evaluate the condition
            condition_eval[condition['name']] = \
                dataops.formula_evaluation.evaluate_top_node(
                    condition['formula'],
                    row_values
                )

        # Step 4: Create the context with the attributes, the evaluation of the
        # conditions and the values of the columns.
        attributes = workflow.attributes
        context = dict(dict(row_values, **condition_eval), **attributes)
        #print(list[context[col_names[col_idx]]])
        # Step 5: run the template with the given context
        # Render the text and append to result
        try:
            partial_result = [render_template(action.content,
                                              context,
                                              action)]
           
        except Exception as e:
            return 'Syntax error detected in the action text. ' + e.message

        # If there is extra message, render with context and create tuple
        if extra_string:
            try:
                partial_result.append(render_template(extra_string, context))
            except Exception as e:
                return 'Syntax error detected in the subject. ' + e.message

        # If column_name was given (and it exists), create a tuple with that
        # element as the third component
        if col_idx != -1:
            partial_result.append(row_values[col_names[col_idx]])
        
        # Append result
        result.append(partial_result)
        
    return result