Example #1
0
def log_table_server_side(
    request: http.HttpRequest,
    workflow: models.Workflow
) -> Dict:
    """Create the server side response for the table of logs.

    :param request: Http Request
    :param workflow: Workflow being considered.
    :return:
    """
    dt_page = DataTablesServerSidePaging(request)
    if not dt_page.is_valid:
        return {'error': _('Incorrect request. Unable to process')}

    # Get the logs
    qs = workflow.logs
    records_total = qs.count()

    if dt_page.search_value:
        # Refine the log
        qs = qs.filter(
            Q(id__icontains=dt_page.search_value)
            | Q(user__email__icontains=dt_page.search_value)
            | Q(name__icontains=dt_page.search_value)
            | Q(payload__icontains=dt_page.search_value),
            workflow__id=workflow.id,
        ).distinct()

    # Order and select values
    qs = qs.order_by(F('created').desc()).values_list(
        'id',
        'name',
        'created',
        'user__email')
    records_filtered = qs.count()

    final_qs = []
    for log_item in qs[dt_page.start:dt_page.start + dt_page.length]:
        row = [
            '<button type="button" data-url="{0}"'.format(
                reverse('logs:modal_view', kwargs={'pk': log_item[0]}),
            )
            + ' class="btn btn-sm btn-light js-log-view"'
            + ' data-toggle="tooltip" title="{0}">{1}</button>'.format(
                ugettext('View log content'),
                log_item[0],
            ),
            models.Log.LOG_TYPES[log_item[1]],
            simplify_datetime_str(log_item[2]),
            log_item[3],
        ]

        # Add the row to the final query_set
        final_qs.append(row)

    return {
        'draw': dt_page.draw,
        'recordsTotal': records_total,
        'recordsFiltered': records_filtered,
        'data': final_qs}
Example #2
0
def display_ss(
    request: HttpRequest,
    workflow: Optional[Workflow] = None,
) -> JsonResponse:
    """Return the subset of logs to include in a table page."""
    # Try to get workflow and if not present, go to home page
    # Check that the GET parameter are correctly given
    dt_page = DataTablesServerSidePaging(request)
    if not dt_page.is_valid:
        return JsonResponse(
            {'error': _('Incorrect request. Unable to process')}, )

    # Get the logs
    qs = workflow.logs
    records_total = qs.count()

    if dt_page.search_value:
        # Refine the log
        qs = qs.filter(
            Q(id__icontains=dt_page.search_value)
            | Q(user__email__icontains=dt_page.search_value)
            | Q(name__icontains=dt_page.search_value)
            | Q(payload__icontains=dt_page.search_value),
            workflow__id=workflow.id,
        ).distinct()

    # Order and select values
    qs = qs.order_by(F('created').desc()).values_list(
        'id',
        'created',
        'user__email',
        'name',
    )
    records_filtered = qs.count()

    final_qs = []
    for log_item in qs[dt_page.start:dt_page.start + dt_page.length]:
        row = [
            '<a href="{0}" class="spin"'.format(
                reverse('logs:view', kwargs={'pk': log_item[0]}), ) +
            ' data-toggle="tooltip" title="{0}">{1}</a>'.format(
                ugettext('View log content'),
                log_item[0],
            ),
            simplify_datetime_str(log_item[1]),
            log_item[2],
            log_item[3],
        ]

        # Add the row to the final query_set
        final_qs.append(row)

    # Render the page with the table
    return JsonResponse({
        'draw': dt_page.draw,
        'recordsTotal': records_total,
        'recordsFiltered': records_filtered,
        'data': final_qs,
    })
Example #3
0
    def render_last_executed_log(self, record):
        log_item = record.last_executed_log
        if not log_item:
            return "---"

        return format_html("""<a class="spin" href="{0}">{1}</a>""",
                           reverse('logs:view', kwargs={'pk': log_item.id}),
                           simplify_datetime_str(log_item.modified))
Example #4
0
    def log(self, operation_type: str, **kwargs):
        """Log the operation with the object."""
        payload = {
            'id': self.id,
            'name': self.name,
            'execute': simplify_datetime_str(self.execute),
            'frequency': self.frequency,
            'execute_until': simplify_datetime_str(self.execute_until),
            'status': self.status,
            'payload': json.dumps(self.payload)
        }

        if self.action:
            payload['action'] = self.action.name
            payload['action_id'] = self.action.id

        payload.update(kwargs)
        return Log.objects.register(self.user, operation_type, self.workflow,
                                    payload)
Example #5
0
    def log(self, operation_type: str, **kwargs):
        """Log the operation with the object."""
        payload = {
            'id': self.id,
            'name': self.name,
            'action': self.action.name,
            'action_id': self.action.id,
            'execute': simplify_datetime_str(self.execute),
            'execute_until': simplify_datetime_str(self.execute_until),
            'item_column': self.item_column.name,
            'status': self.status,
            'exclude_values': self.exclude_values,
            'payload': json.dumps(self.payload)}

        payload.update(kwargs)
        return Log.objects.register(
            self.user,
            operation_type,
            self.action.workflow,
            payload)
Example #6
0
def create_track_column(action: Action) -> str:
    """Create an additional column for email tracking.

    :param action: Action to consider
    :return: column name
    """
    # Make sure the column name does not collide with an existing one
    idx = 0  # Suffix to rename
    cnames = [col.name for col in action.workflow.columns.all()]
    while True:
        idx += 1
        track_col_name = 'EmailRead_{0}'.format(idx)
        if track_col_name not in cnames:
            break

    # Add the column if needed (before the mass email to avoid overload
    # Create the new column and store
    column = Column(
        name=track_col_name,
        description_text='Emails sent with action {0} on {1}'.format(
            action.name,
            simplify_datetime_str(
                datetime.datetime.now(pytz.timezone(
                    ontask_settings.TIME_ZONE))),
        ),
        workflow=action.workflow,
        data_type='integer',
        is_key=False,
        position=action.workflow.ncols + 1,
    )
    column.save()

    # Increase the number of columns in the workflow
    action.workflow.ncols += 1
    action.workflow.save()

    # Add the column to the DB table
    add_column_to_db(action.workflow.get_data_frame_table_name(),
                     track_col_name, 'integer', 0)

    return track_col_name
Example #7
0
class ActionTable(tables.Table):
    """Class to render the list of actions per workflow.

    The Operations column is taken from another class to centralise the
    customisation.
    """

    name = tables.Column(verbose_name=_('Name'))

    description_text = tables.Column(verbose_name=_('Description'))

    action_type = tables.TemplateColumn(
        template_name='action/includes/partial_action_type.html',
        verbose_name=_('Type'))

    last_executed_log = tables.LinkColumn(
        verbose_name=_('Last executed'),
        empty_values=['', None],
        viewname='logs:view',
        text=lambda record: simplify_datetime_str(record.last_executed_log.
                                                  modified),
        kwargs={'pk': tables.A('last_executed_log.id')},
        attrs={'a': {
            'class': 'spin'
        }},
    )

    #
    # Operatiosn available per action type (see partial_action_operations.html)
    #
    #  Action type               |  Email  |  ZIP |  URL  |  RUN  |
    #  ------------------------------------------------------------
    #  Personalized text         |    X    |   X  |   X   |   X   |
    #  Personalized canvas email |    X    |      |       |   X   |
    #  Personalized JSON         |         |      |   ?   |   X   |
    #  Survey                    |         |      |   X   |   X   |
    #  Todo List                 |         |      |   X   |   X   |
    #
    operations = OperationsColumn(
        verbose_name='',
        template_file='action/includes/partial_action_operations.html',
        template_context=lambda record: {
            'id': record.id,
            'action_tval': record.action_type,
            'is_out': int(record.is_out),
            'is_executable': record.is_executable,
            'serve_enabled': record.serve_enabled
        },
    )

    def render_name(self, record):
        """Render name as a link with a potential flag."""
        return render_to_string(
            'action/includes/partial_action_name.html',
            context={
                'action_id':
                record.id,
                'danger_msg': (record.get_row_all_false_count
                               or not record.is_executable),
                'action_name':
                record.name,
            },
        )

    class Meta:
        """Define model, fields and ordering."""

        model = Action
        fields = (
            'name',
            'description_text',
            'action_type',
            'last_executed_log',
        )
        sequence = (
            'action_type',
            'name',
            'description_text',
            'last_executed_log',
        )
        exclude = ('content', 'serve_enabled', 'filter')
        attrs = {
            'class': 'table table-hover table-bordered shadow',
            'style': 'width: 100%;',
            'id': 'action-table',
        }
Example #8
0
def display_ss(request):
    # Try to get workflow and if not present, go to home page
    workflow = get_workflow(request)
    if not workflow:
        return JsonResponse(
            {'error': _('Incorrect request. Unable to process')})

    # Check that the GET parameter are correctly given
    try:
        draw = int(request.POST.get('draw', None))
        start = int(request.POST.get('start', None))
        length = int(request.POST.get('length', None))
    except ValueError:
        return JsonResponse(
            {'error': _('Incorrect request. Unable to process')})

    # Get the column information from the request and the rest of values.
    search_value = request.POST.get('search[value]', None)

    # Get the logs
    qs = workflow.logs
    recordsTotal = qs.count()

    if search_value:
        # Refine the log
        qs = qs.filter(
            Q(id__icontains=search_value)
            | Q(user__email__icontains=search_value)
            | Q(name__icontains=search_value)
            | Q(payload__icontains=search_value),
            workflow__id=workflow.id,
        ).distinct()

    # Order and select values
    qs = qs.order_by(F('created').desc()).values_list('id', 'created',
                                                      'user__email', 'name')
    recordsFiltered = qs.count()

    final_qs = []
    for item in qs[start:start + length]:
        row = [
            """<a href="{0}" class="btn btn-outline-dark spin"
                  data-toggle="tooltip" title="{1}">
                  <span class="fa fa-eye"></span> {2}
                </a>""".format(reverse('logs:view', kwargs={'pk': item[0]}),
                               ugettext('View log content'), item[0]),
            simplify_datetime_str(item[1]),
            item[2],
            item[3],
        ]

        # Add the row to the final query_set
        final_qs.append(row)

    # Result to return as AJAX response
    data = {
        'draw': draw,
        'recordsTotal': recordsTotal,
        'recordsFiltered': recordsFiltered,
        'data': final_qs
    }
    # Render the page with the table
    return JsonResponse(data)