Beispiel #1
0
def serve_action_out(
    user,
    action: Action,
    user_attribute_name: str,
):
    """Serve request for an action out.

    Function that given a user and an Action Out
    searches for the appropriate data in the table with the given
    attribute name equal to the user email and returns the HTTP response.
    :param user: User object making the request
    :param action: Action to execute (action out)
    :param user_attribute_name: Column to check for email
    :return:
    """
    # For the response
    payload = {'action': action.name, 'action_id': action.id}

    # User_instance has the record used for verification
    row_values = get_row_values(action, (user_attribute_name, user.email))

    # Get the dictionary containing column names, attributes and condition
    # valuations:
    context = get_action_evaluation_context(action, row_values)
    if context is None:
        payload['error'] = (
            _('Error when evaluating conditions for user {0}').format(
                user.email, ))
        # Log the event
        Log.objects.register(user,
                             Log.ACTION_SERVED_EXECUTE,
                             workflow=action.workflow,
                             payload=payload)
        return HttpResponse(
            render_to_string('action/action_unavailable.html', {}))

    # Evaluate the action content.
    action_content = evaluate_row_action_out(action, context)

    # If the action content is empty, forget about it
    response = action_content
    if action_content is None:
        response = render_to_string('action/action_unavailable.html', {})
        payload['error'] = _('Action not enabled for user {0}').format(
            user.email, )

    # Log the event
    Log.objects.register(user,
                         Log.ACTION_SERVED_EXECUTE,
                         workflow=action.workflow,
                         payload=payload)

    # Respond the whole thing
    return HttpResponse(response)
Beispiel #2
0
def get_survey_context(
    request: http.HttpRequest,
    is_manager: bool,
    action: models.Action,
    user_attribute_name: str,
) -> Dict:
    """Get the context to render a survey page.

    :param request: Request received
    :param is_manager: User is manager
    :param action: Action object being executed
    :param user_attribute_name: Name of the column to use for username
    :return: Dictionary with the context
    """
    # Get the attribute value depending if the user is managing the workflow
    # User is instructor, and either owns the workflow or is allowed to access
    # it as shared
    user_attribute_value = None
    if is_manager:
        user_attribute_value = request.GET.get('uatv')
    if not user_attribute_value:
        user_attribute_value = request.user.email

    # Get the dictionary containing column names, attributes and condition
    # valuations:
    context = get_action_evaluation_context(
        action,
        get_row_values(
            action,
            (user_attribute_name, user_attribute_value),
        ),
    )

    if not context:
        # If the data has not been found, flag
        if not is_manager:
            raise OnTaskActionSurveyDataNotFound()

        raise OnTaskActionSurveyNoTableData(
            message=_('Data not found in the table'))

    return context
def _create_row_preview_response(
    action: Action,
    idx: int,
    page_context: Dict,
    prelude: str = None,
):
    """Create the elements to render a sigle row preview.

    :param action: Action being previewed.
    :param idx:
    :param page_context:
    :return: page_context is modified to include the appropriate items
    """

    # Get the total number of items
    filter_obj = action.get_filter()
    if filter_obj:
        n_items = filter_obj.n_rows_selected
    else:
        n_items = action.workflow.nrows

    # Set the correct values to the indeces
    prv, idx, nxt = _get_navigation_index(idx, n_items)

    row_values = get_row_values(action, idx)

    # Obtain the dictionary with the condition evaluation
    condition_evaluation = action_condition_evaluation(action, row_values)
    # Get the dictionary containing column names, attributes and condition
    # valuations:
    eval_context = get_action_evaluation_context(action, row_values,
                                                 condition_evaluation)

    all_false = False
    if action.conditions.filter(is_filter=False).count():
        # If there are conditions, check if they are all false
        all_false = all(not bool_val
                        for __, bool_val in condition_evaluation.items())

    # Evaluate the action content.
    show_values = ''
    incorrect_json = False
    if action.is_out:
        action_content = evaluate_row_action_out(action, eval_context)
        if action.action_type == Action.personalized_json:
            incorrect_json = not _check_json_is_correct(action_content)
    else:
        action_content = evaluate_row_action_in(action, eval_context)
    if action_content is None:
        action_content = _(
            'Error while retrieving content for student {0}', ).format(idx)
    else:
        # Get the conditions used in the action content
        act_cond = action.get_used_conditions()
        # Get the variables/columns from the conditions
        act_vars = set().union(
            *[
                cond.columns.all()
                for cond in action.conditions.filter(name__in=act_cond)
            ], )
        # Sort the variables/columns  by position and get the name
        show_values = ', '.join([
            '{0} = {1}'.format(col.name, row_values[col.name])
            for col in act_vars
        ], )

    uses_plain_text = (action.action_type == Action.personalized_canvas_email
                       or action.action_type == Action.personalized_json)
    if uses_plain_text:
        action_content = escape(action_content)

    if prelude:
        prelude = evaluate_row_action_out(action, eval_context, prelude)

    # Update the context
    page_context.update({
        'n_items': n_items,
        'nxt': nxt,
        'prv': prv,
        'incorrect_json': incorrect_json,
        'show_values': show_values,
        'all_false': all_false,
        'prelude': prelude,
        'action_content': action_content,
        'show_navigation': True
    })

    return
Beispiel #4
0
def serve_survey_row(
    request: HttpRequest,
    action: Action,
    user_attribute_name: str,
) -> HttpResponse:
    """Serve a request for action in.

    Function that given a request, and an action IN, it performs the lookup
     and data input of values.

    :param request: HTTP request

    :param action:  Action In

    :param user_attribute_name: The column name used to check for email

    :return:
    """
    # Get the attribute value depending if the user is managing the workflow
    # User is instructor, and either owns the workflow or is allowed to access
    # it as shared
    manager = has_access(request.user, action.workflow)
    user_attribute_value = None
    if manager:
        user_attribute_value = request.GET.get('uatv')
    if not user_attribute_value:
        user_attribute_value = request.user.email

    # Get the dictionary containing column names, attributes and condition
    # valuations:
    context = get_action_evaluation_context(
        action,
        get_row_values(
            action,
            (user_attribute_name, user_attribute_value),
        ),
    )

    if not context:
        # If the data has not been found, flag
        if not manager:
            return ontask_handler404(request, None)

        messages.error(request, _('Data not found in the table'))
        return redirect(reverse('action:run', kwargs={'pk': action.id}))

    # Get the active columns attached to the action
    colcon_items = extract_survey_questions(action, request.user)

    # Bind the form with the existing data
    form = EnterActionIn(
        request.POST or None,
        tuples=colcon_items,
        context=context,
        values=[context[colcon.column.name] for colcon in colcon_items],
        show_key=manager)

    keep_processing = (request.method == 'POST' and form.is_valid()
                       and not request.POST.get('lti_version'))
    if keep_processing:
        # Update the content in the DB
        row_keys, row_values = survey_update_row_values(
            action, colcon_items, manager, form.cleaned_data, 'email',
            request.user.email, context)

        # Log the event and update its content in the action
        log_item = action.log(request.user,
                              Log.ACTION_SURVEY_INPUT,
                              new_values=json.dumps(
                                  dict(zip(row_keys, row_values))))

        # Modify the time of execution for the action
        action.last_executed_log = log_item
        action.save()

        # If not instructor, just thank the user!
        if not manager:
            return render(request, 'thanks.html', {})

        # Back to running the action
        return redirect(reverse('action:run', kwargs={'pk': action.id}))

    return render(
        request,
        'action/run_survey_row.html',
        {
            'form':
            form,
            'action':
            action,
            'cancel_url':
            reverse(
                'action:run',
                kwargs={'pk': action.id},
            ) if manager else None,
        },
    )
Beispiel #5
0
def create_row_preview_context(
    action: models.Action,
    idx: int,
    context: Dict,
    prelude: Optional[str] = None,
):
    """Create the elements to render a single row preview.

    :param action: Action being previewed.
    :param idx:
    :param context:
    :param prelude: Optional additional text to include in the preview.
    :return: context is modified to include the appropriate items
    """
    # Get the total number of items
    filter_obj = action.get_filter()
    if filter_obj:
        n_items = filter_obj.n_rows_selected
    else:
        n_items = action.workflow.nrows

    # Set the correct values to the indeces
    prv, idx, nxt = _get_navigation_index(idx, n_items)

    row_values = get_row_values(action, idx)

    # Obtain the dictionary with the condition evaluation
    condition_evaluation = action_condition_evaluation(action, row_values)
    # Get the dictionary containing column names, attributes and condition
    # valuations:
    eval_context = get_action_evaluation_context(action, row_values,
                                                 condition_evaluation)

    all_false = False
    if action.conditions.filter(is_filter=False).count():
        # If there are conditions, check if they are all false
        all_false = all(not bool_val
                        for __, bool_val in condition_evaluation.items())

    # Evaluate the action content.
    show_values = ''
    incorrect_json = False
    if action.is_out:
        action_content = evaluate_row_action_out(action, eval_context)
        if action.action_type == models.Action.PERSONALIZED_JSON:
            incorrect_json = not _check_json_is_correct(action_content)
    else:
        action_content = _evaluate_row_action_in(action, eval_context)
    if action_content is None:
        action_content = _(
            'Error while retrieving content (index: {0})', ).format(idx)
    else:
        # Get the conditions used in the action content
        act_cond = action.get_used_conditions()
        # Get the variables/columns from the conditions
        act_vars = set().union(*[
            cond.columns.all()
            for cond in action.conditions.filter(name__in=act_cond)
        ])

        act_vars = act_vars.union(
            {triplet.column
             for triplet in action.column_condition_pair.all()})

        # Sort the variables/columns  by position and get the name
        show_values = ', '.join([
            '"{0}" = {1}'.format(col.name, row_values[col.name])
            for col in act_vars
        ])

    uses_plain_text = (
        action.action_type == models.Action.PERSONALIZED_CANVAS_EMAIL
        or action.action_type == models.Action.PERSONALIZED_JSON)
    if uses_plain_text:
        action_content = escape(action_content)

    if prelude:
        prelude = evaluate_row_action_out(action, eval_context, prelude)

    # Update the context
    context.update({
        'n_items':
        n_items,
        'nxt':
        nxt,
        'prv':
        prv,
        'incorrect_json':
        incorrect_json,
        'show_values':
        show_values,
        'show_conditions':
        ', '.join([
            '"{0}" = {1}'.format(cond_name, str(cond_value))
            for cond_name, cond_value in condition_evaluation.items()
        ]),
        'all_false':
        all_false,
        'prelude':
        prelude,
        'action_content':
        action_content,
        'show_navigation':
        True
    })