Example #1
0
class AttributeTable(tables.Table):
    """
    Table to render the list of attributes attached to a workflow
    """
    name = tables.Column(verbose_name=_('Name'))
    value = tables.Column(verbose_name=_('Value'))
    operations = OperationsColumn(
        verbose_name='',
        template_file='workflow/includes/partial_attribute_operations.html',
        template_context=lambda record: {
            'id': record['id'],
        })

    def render_name(self, record):
        return format_html(
            """<a href="#" data-toggle="tooltip" 
                  class="js-attribute-edit" data-url="{0}"
                  title="{1}">{2}</a>""",
            reverse('workflow:attribute_edit', kwargs={'pk': record['id']}),
            _('Edit the attribute'), record['name'])

    class Meta(object):
        fields = ('name', 'value', 'operations')
        attrs = {
            'class': 'table',
            'style': 'width: 100%;',
            'id': 'attribute-table'
        }
Example #2
0
class WorkflowShareTable(tables.Table):
    email = tables.Column(attrs={'td': {
        'class': 'dt-body-center'
    }},
                          verbose_name=str('User'))

    operations = OperationsColumn(
        attrs={'td': {
            'class': 'dt-body-center'
        }},
        verbose_name='',
        orderable=False,
        template_file='workflow/includes/partial_share_operations.html',
        template_context=lambda x: {'id': x['id']})

    class Meta:
        fields = ('email', 'id')

        sequence = ('email', 'operations')

        attrs = {
            'class': 'table display',
            'id': 'share-table',
            'th': {
                'class': 'dt-body-center'
            }
        }
Example #3
0
class SQLConnectionTableRun(tables.Table):
    operations = OperationsColumn(
        verbose_name='Operations',
        template_file='dataops/includes/partial_sqlconn_runop.html',
        template_context=lambda record: {'id': record['id']})

    def __init__(self, data, *args, **kwargs):
        table_id = kwargs.pop('id')

        super(SQLConnectionTableRun, self).__init__(data, *args, **kwargs)

        # If an ID was given, pass it on to the table attrs.
        if table_id:
            self.attrs['id'] = table_id

    class Meta:
        model = SQLConnection

        fields = ('name', 'description_txt', 'conn_type', 'conn_driver',
                  'db_user', 'db_password', 'db_host', 'db_port', 'db_name',
                  'db_table')

        sequence = ('name', 'description_txt', 'conn_type', 'conn_driver',
                    'db_user', 'db_password', 'db_host', 'db_port', 'db_name',
                    'db_table', 'operations')

        attrs = {
            'class': 'table display table-bordered',
            'id': 'sqlconn-table'
        }
Example #4
0
class SQLConnectionTableRun(tables.Table):
    """Class to render the table of SQL connections."""

    operations = OperationsColumn(
        verbose_name='',
        template_file='dataops/includes/partial_sqlconn_runop.html',
        template_context=lambda record: {'id': record['id']},
    )

    def render_name(self, record):
        """Render the name as a link."""
        return format_html(
            '<a class="js-sqlconn-view" href="#" data-url="{0}">{1}</a>',
            reverse('dataops:sqlconn_view', kwargs={'pk': record['id']}),
            record['name'],
        )

    class Meta(object):
        """Define models, fields, sequence and attributes."""

        model = SQLConnection

        fields = ('name', 'description_txt')

        sequence = ('name', 'description_txt', 'operations')

        attrs = {
            'class': 'table table-hover table-bordered shadow',
            'style': 'width: 100%;',
            'id': 'sqlconn-instructor-table',
        }
Example #5
0
class ViewTable(tables.Table):
    """
    Table to display the set of views handled in a workflow
    """
    name = tables.Column(verbose_name=str('Name'))
    description_text = tables.Column(
        empty_values=[],
        verbose_name=str('Description')
    )
    modified = tables.DateTimeColumn(verbose_name='Modified')
    operations = OperationsColumn(
        verbose_name='Operations',
        template_file='table/includes/partial_view_operations.html',
        template_context=lambda record: {'id': record['id']}
    )

    class Meta:
        """
        Select the model and specify fields, sequence and attributes
        """
        model = View
        fields = ('name', 'description_text', 'modified', 'operations')
        sequence = ('name', 'description_text', 'modified', 'operations')
        attrs = {
            'class': 'table display table-bordered',
            'id': 'view-table'
        }
Example #6
0
class ActionTable(tables.Table):
    """
    Table 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.Column(verbose_name=_('Type'))

    last_executed_log = tables.Column(verbose_name=_('Last executed'))

    operations = OperationsColumn(
        verbose_name=_('Operations'),
        template_file='action/includes/partial_action_operations.html',
        template_context=lambda record: {
            'id': record['id'],
            'action_tval': record['action_tval'],
            'is_out': int(record['is_out']),
            'is_executable': record['is_executable'],
            'serve_enabled': record['serve_enabled']
        })

    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>""".format(
            reverse('logs:view', kwargs={'pk': log_item.id}),
            log_item.modified.astimezone(pytz.timezone(settings.TIME_ZONE))))

    class Meta:
        model = Action

        fields = ('name', 'description_text', 'action_type',
                  'last_executed_log')

        sequence = ('name', 'description_text', 'action_type',
                    'last_executed_log')

        exclude = ('content', 'serve_enabled', 'columns', 'filter')

        attrs = {'class': 'table display table-bordered', 'id': 'action-table'}

        row_attrs = {
            'style': 'text-align:center;',
        }
Example #7
0
class ActionTable(tables.Table):
    """
    Table 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=str('Name'))

    is_out = tables.Column(verbose_name=str('Type'))

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

    modified = tables.DateTimeColumn(verbose_name='Modified')

    operations = OperationsColumn(
        verbose_name='Operations',
        template_file='action/includes/partial_action_operations.html',
        template_context=lambda record: {
            'id': record['id'],
            'is_out': int(record['is_out']),
            'serve_enabled': record['serve_enabled']
        }
    )

    def render_is_out(self, record):
        if record['is_out']:
            return "OUT"
        else:
            return "IN"

    class Meta:
        model = Action

        fields = ('name', 'description_text', 'is_out', 'modified')

        sequence = ('name', 'description_text', 'is_out', 'modified')

        exclude = ('n_selected_rows', 'content', 'serve_enabled',
                   'columns', 'filter')

        attrs = {
            'class': 'table display table-bordered',
            'id': 'action-table'
        }

        row_attrs = {
            'style': 'text-align:center;',
            'class': lambda record: 'success' if record['is_out'] else ''
        }
Example #8
0
class WorkflowTable(tables.Table):
    name = tables.Column(verbose_name=_('Name'))

    description_text = tables.Column(empty_values=[],
                                     verbose_name=_('Description'))

    nrows_cols = tables.Column(empty_values=[],
                               verbose_name=_('Rows/Columns'),
                               default=_('No data'))

    modified = tables.DateTimeColumn(verbose_name=_('Last modified'))

    def __init__(self, data, *args, **kwargs):
        table_id = kwargs.pop('id')

        super(WorkflowTable, self).__init__(data, *args, **kwargs)
        # If an ID was given, pass it on to the table attrs.
        if table_id:
            self.attrs['id'] = table_id

    def render_nrows_cols(self, record):
        if record['nrows'] == 0 and record['ncols'] == 0:
            return "No data"

        return format_html("{0}/{1}".format(record['nrows'], record['ncols']))

    operations = OperationsColumn(
        verbose_name=_('Operations'),
        attrs={'td': {
            'class': 'dt-body-center'
        }},
        template_file='workflow/includes/workflow_basic_buttons.html',
        template_context=lambda record: {'workflow': record})

    class Meta:
        model = Workflow

        fields = ('name', 'description_text', 'nrows_cols', 'modified')

        sequence = ('name', 'description_text', 'nrows_cols', 'modified')

        exclude = ('user', 'attributes', 'nrows', 'ncols', 'column_names',
                   'column_types', 'column_unique', 'query_builder_ops',
                   'data_frame_table_name')

        attrs = {
            'class': 'table display table-bordered',
            'id': 'workflow-table'
        }
Example #9
0
class AttributeTable(tables.Table):
    """
    Table to render the list of attributes attached to a workflow
    """
    name = tables.Column(verbose_name=str('Name'))
    value = tables.Column(verbose_name=str('Value'))
    operations = OperationsColumn(
        verbose_name='Ops',
        template_file='workflow/includes/partial_attribute_operations.html',
        template_context=lambda record: {
            'id': record['id'],
        })

    class Meta:
        fields = ('name', 'value', 'operations')
        attrs = {
            'class': 'table display table-bordered',
            'id': 'attribute-table'
        }
Example #10
0
class PluginRegistryTable(tables.Table):
    """
    Table to render the list of plugins available for execution. The
    Operations column is inheriting from another class to centralise the
    customisation.
    """

    filename = tables.Column(verbose_name=str('Folder'))

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

    description_txt = tables.Column(verbose_name=str('Description'))

    modified = tables.DateTimeColumn(verbose_name='Last modified')

    executed = tables.DateTimeColumn(verbose_name='Last executed')

    operations = OperationsColumn(
        verbose_name='Operations',
        template_file='dataops/includes/partial_plugin_operations.html',
        template_context=lambda record: {
            'id': record.id,
            'is_verified': record.is_verified
        })

    class Meta:
        model = PluginRegistry

        fields = ('filename', 'name', 'description_txt', 'modified',
                  'is_verified', 'executed')

        sequence = ('filename', 'name', 'description_txt', 'modified',
                    'is_verified', 'executed')

        attrs = {
            'class': 'table display table-bordered',
            'id': 'transform-table'
        }

        row_attrs = {
            'style': 'text-align:center;',
        }
Example #11
0
class SQLConnectionTableAdmin(tables.Table):
    operations = OperationsColumn(
        verbose_name='',
        template_file='dataops/includes/partial_sqlconn_adminop.html',
        template_context=lambda record: {'id': record['id']})

    def render_name(self, record):
        return format_html(
            """<a class="js-sqlconn-edit" href="#" data-url="{0}">{1}</a>""",
            reverse('dataops:sqlconn_edit', kwargs={'pk': record['id']}),
            record['name'])

    class Meta(object):
        model = SQLConnection
        fields = ('name', 'description_txt')
        sequence = ('name', 'description_txt', 'operations')
        attrs = {
            'class': 'table table-hover table-bordered',
            'style': 'width: 100%;',
            'id': 'sqlconn-admin-table'
        }
Example #12
0
class ViewTable(tables.Table):
    """Table to display the set of views handled in a workflow."""

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

    description_text = tables.Column(empty_values=[],
                                     verbose_name=_('Description'))

    operations = OperationsColumn(
        verbose_name='',
        template_file='table/includes/partial_view_operations.html',
        template_context=lambda record: {'id': record['id']},
    )

    def render_name(self, record):
        """Render the name of the action as a link."""
        return format_html(
            """<a href="#" class="js-view-edit"
                  data-toggle="tooltip" data-url="{0}"
                  title="{1}">{2}</a>""",
            reverse('table:view_edit', kwargs={'pk': record['id']}),
            _('Change the columns present in the view'),
            record['name'],
        )

    class Meta(object):
        """Select the model and specify fields, sequence and attributes."""

        model = View

        fields = ('name', 'description_text', 'operations')

        sequence = ('name', 'description_text', 'operations')

        attrs = {
            'class': 'table table-hover table-bordered shadow',
            'style': 'width: 100%;',
            'id': 'view-table',
        }
Example #13
0
class SQLConnectionTableRun(tables.Table):
    operations = OperationsColumn(
        verbose_name='',
        template_file='dataops/includes/partial_sqlconn_runop.html',
        template_context=lambda record: {'id': record['id']})

    def render_name(self, record):
        return format_html(
            '<a class="js-sqlconn-view" href="#" data-url="{0}">{1}'
            ' <span class="fa fa-eye"></span> </a>',
            reverse('dataops:sqlconn_view', kwargs={'pk': record['id']}),
            record['name'])

    class Meta(object):
        model = SQLConnection

        fields = ('name', 'description_txt')

        sequence = ('name', 'description_txt', 'operations')
        attrs = {
            'class': 'table table-hover table-bordered',
            'style': 'width: 100%;',
            'id': 'sqlconn-instructor-table'
        }
Example #14
0
class ActionTable(tables.Table):
    """
    Table 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.Column(verbose_name=_('Type'))

    last_executed_log = tables.Column(verbose_name=_('Last executed'))

    #
    # Operatiosn available per action type (see partial_action_operations.html)
    #
    #  Action type               |  Email  |  ZIP |  URL  |  RUN  |
    #  ------------------------------------------------------------
    #  Personalized text         |    X    |   X  |   X   |       |
    #  Personalized canvas email |    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):
        return format_html(
            """<a href="{0}"
                  data-toggle="tooltip"
                  title="{1}">{2}</a>""",
            reverse('action:edit', kwargs={'pk': record.id}),
            _('Edit the text, conditions and filter'), record.name)

    def render_action_type(self, record):
        icon = 'file-text'
        title = 'Personalized text'
        if record.action_type == Action.PERSONALIZED_TEXT:
            icon = 'file-text'
            title = 'Personalized text'
        elif record.action_type == Action.PERSONALIZED_CANVAS_EMAIL:
            icon = 'envelope-square'
            title = 'Personalized Canvas Email'
        elif record.action_type == Action.PERSONALIZED_JSON:
            icon = 'code'
            title = 'Personalized JSON'
        elif record.action_type == Action.SURVEY:
            icon = 'question-circle-o'
            title = 'Survey'
        return format_html(
            """<div data-toggle="tooltip" title="{0}">
                 <span class="fa fa-{1}"></span></div>""", title, icon)

    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))

    class Meta(object):
        model = Action
        fields = ('name', 'description_text', 'action_type',
                  'last_executed_log')
        sequence = ('action_type', 'name', 'description_text',
                    'last_executed_log')
        exclude = ('content', 'serve_enabled', 'columns', 'filter')
        attrs = {
            'class': 'table table-hover table-bordered',
            'style': 'width: 100%;',
            'id': 'action-table'
        }
Example #15
0
class ScheduleActionTable(tables.Table):
    """Table to show the email actions scheduled for a workflow."""

    action = tables.LinkColumn(
        verbose_name=_('Action'),
        viewname='action:edit',
        text=lambda record: record.action.name,
        kwargs={'pk': A('action.id')},
        attrs={
            'a': {
                'class': 'spin',
                'data-toggle': 'tooltip',
                'title': _('Edit the action scheduled for execution'),
            },
            'td': {
                'data-backcolor': lambda record: record.action.action_type
            },
        },
    )

    operations = OperationsColumn(
        verbose_name='',
        orderable=False,
        template_file='scheduler/includes/partial_scheduler_operations.html',
        template_context=lambda record: {'id': record.id},
    )

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

    execute = tables.DateTimeColumn(verbose_name=_('Scheduled'))

    status = tables.Column(verbose_name=_('Status'),
                           accessor=A('get_status_display'))

    def render_name(self, record):
        """Render name as link."""
        return format_html(
            '<a href="{0}" data-toggle="tooltip" title="{1}">{2}</a>',
            reverse('scheduler:edit', kwargs={'pk': record.id}),
            _('Edit this scheduled action execution'), record.name)

    def render_status(self, record):
        """Render status as a link."""
        log_item = record.last_executed_log
        if not log_item:
            return record.get_status_display()

        # At this point, the object is not pending. Produce a link
        return format_html('<a class="spin" href="{0}">{1}</a>',
                           reverse('logs:view', kwargs={'pk': log_item.id}),
                           record.get_status_display())

    class Meta(object):
        """Choose model, fields and sequence in the table."""

        model = ScheduledAction

        fields = ('name', 'action', 'execute', 'status')

        sequence = ('name', 'action', 'execute', 'status', 'operations')

        attrs = {
            'class': 'table table-hover table-bordered shadow',
            'style': 'width: 100%;',
            'id': 'scheduler-table'
        }
Example #16
0
class ScheduleEmailActionTable(tables.Table):
    """
    Table to show the email actions scheduled for a workflow
    """

    operations = OperationsColumn(
        attrs={'td': {
            'class': 'dt-body-center'
        }},
        verbose_name=_('Operations'),
        orderable=False,
        template_file='scheduler/includes/partial_scheduler_operations.html',
        template_context=lambda record: {'id': record.id})

    action = tables.Column(attrs={'td': {
        'class': 'dt-center'
    }},
                           verbose_name=_('Action'),
                           accessor=A('action.name'))

    execute = tables.Column(attrs={'td': {
        'class': 'dt-center'
    }},
                            verbose_name=_('Scheduled'))

    status = tables.Column(attrs={'td': {
        'class': 'dt-center'
    }},
                           verbose_name=_('Status'))

    subject = tables.Column(attrs={'td': {
        'class': 'dt-center'
    }},
                            verbose_name=_('Subject'))

    email_column = tables.Column(
        attrs={'td': {
            'class': 'dt-center'
        }},
        verbose_name=_('Email column'),
    )

    cc_email = tables.Column(
        attrs={'td': {
            'class': 'dt-center'
        }},
        verbose_name=_('CC Emails'),
    )

    bcc_email = tables.Column(
        attrs={'td': {
            'class': 'dt-center'
        }},
        verbose_name=_('BCC Emails'),
    )

    send_confirmation = BooleanColumn(
        attrs={'td': {
            'class': 'dt-center'
        }},
        verbose_name=_('Send confirmation'),
        get_field=lambda x: x.send_confirmation,
    )

    track_read = BooleanColumn(
        attrs={'td': {
            'class': 'dt-center'
        }},
        verbose_name=_('Track'),
        get_field=lambda x: x.track_read,
    )

    message = tables.Column(
        attrs={'td': {
            'class': 'dt-center'
        }},
        verbose_name=_('Execution message'),
    )

    def render_action(self, record):
        return format_html('<a href="{0}">{1}</a>'.format(
            reverse('action:edit_out', kwargs={'pk': record.action.id}),
            record.action.name))

    class Meta:
        model = ScheduledEmailAction

        fields = ('action', 'created', 'execute', 'status', 'subject',
                  'email_column', 'cc_email', 'bcc_email', 'send_confirmation',
                  'track_read', 'operations', 'message')

        sequence = ('operations', 'action', 'created', 'execute', 'status',
                    'subject', 'email_column', 'cc_email', 'bcc_email',
                    'send_confirmation', 'track_read', 'message')

        attrs = {
            'class': 'table display table-bordered',
            'id': 'scheduler-table'
        }

        row_attrs = {
            'style': 'text-align:center;',
            'class': lambda record: 'success' if record.status == 0 else ''
        }
Example #17
0
def edit_action_in(request, workflow, action):
    """
    View to handle the AJAX form to edit an action in (filter + columns).
    :param request: Request object
    :param workflow: workflow
    :param action: Action
    :return: HTTP response
    """

    # Get filter or None
    filter_condition = action.get_filter()

    # Get the number of rows in DF selected by filter.
    if filter_condition:
        filter_condition.n_rows_selected = \
            pandas_db.num_rows(action.workflow.id, filter_condition.formula)
        filter_condition.save()

    # Column names suitable to insert
    columns_selected = action.columns.filter(is_key=False).order_by('position')
    columns_to_insert = [
        c for c in workflow.columns.all()
        if not c.is_key and c not in columns_selected
    ]

    # Has key column and has no-key column
    has_no_key = action.columns.filter(is_key=False).exists()
    has_empty_description = columns_selected.filter(
        description_text='').exists()

    # Create the context info.
    ctx = {
        'action':
        action,
        'filter_condition':
        filter_condition,
        'selected_rows':
        filter_condition.n_rows_selected if filter_condition else -1,
        'total_rows':
        workflow.nrows,
        'query_builder_ops':
        workflow.get_query_builder_ops_as_str(),
        'has_data':
        ops.workflow_has_table(action.workflow),
        'key_selected':
        action.columns.filter(is_key=True).first(),
        'columns_to_insert':
        columns_to_insert,
        'column_selected_table':
        ColumnSelectedTable(
            columns_selected.values('id', 'name', 'description_text'),
            orderable=False,
            extra_columns=[('operations',
                            OperationsColumn(
                                verbose_name='Ops',
                                template_file=ColumnSelectedTable.ops_template,
                                template_context=lambda record: {
                                    'id': record['id'],
                                    'aid': action.id
                                }))]),
        'has_no_key':
        has_no_key,
        'has_empty_description':
        has_empty_description
    }

    return render(request, 'action/edit_in.html', ctx)
Example #18
0
def edit_action_in(request, pk):
    """
    View to handle the AJAX form to edit an action in (filter + columns).
    :param request: Request object
    :param pk: Action PK
    :return: HTTP response
    """

    # Check if the workflow is locked
    workflow = get_workflow(request)
    if not workflow:
        return redirect('workflow:index')

    if workflow.nrows == 0:
        messages.error(request,
                       'Workflow has no data. '
                       'Go to Dataops to upload data.')
        return redirect(reverse('action:index'))

    # Get the action and the columns
    try:
        action = Action.objects.filter(
            Q(workflow__user=request.user) |
            Q(workflow__shared=request.user)
        ).distinct().prefetch_related('columns').get(pk=pk)
    except ObjectDoesNotExist:
        return redirect('action:index')

    if action.is_out:
        # Trying to edit an incorrect action. Redirect to index
        return redirect('action:index')

    # See if the action has a filter or not
    try:
        filter_condition = Condition.objects.get(
            action=action, is_filter=True
        )
    except Condition.DoesNotExist:
        filter_condition = None
    except Condition.MultipleObjectsReturned:
        return render(request, 'error.html',
                      {'message': 'Malfunction detected when retrieving filter '
                                  '(action: {0})'.format(action.id)})

    # Get the number of rows in DF selected by filter.
    if filter_condition:
        filter_condition.n_rows_selected = \
            pandas_db.num_rows(action.workflow.id, filter_condition.formula)
        filter_condition.save()

    # Column names suitable to insert
    columns_selected = action.columns.filter(is_key=False).order_by('position')
    columns_to_insert = [c for c in workflow.columns.all()
                         if not c.is_key and c not in columns_selected]

    # Has key column and has no-key column
    has_no_key = action.columns.filter(is_key=False).exists()
    has_empty_description = columns_selected.filter(
        description_text=''
    ).exists()

    # Create the context info.
    ctx = {'action': action,
           'filter_condition': filter_condition,
           'selected_rows':
               filter_condition.n_rows_selected if filter_condition else -1,
           'total_rows': workflow.nrows,
           'query_builder_ops': workflow.get_query_builder_ops_as_str(),
           'has_data': ops.workflow_has_table(action.workflow),
           'key_selected': action.columns.filter(is_key=True).first(),
           'columns_to_insert': columns_to_insert,
           'column_selected_table': ColumnSelectedTable(
               columns_selected.values('id', 'name', 'description_text'),
               orderable=False,
               extra_columns=[
                   ('operations',
                    OperationsColumn(
                        verbose_name='Ops',
                        template_file=ColumnSelectedTable.ops_template,
                        template_context=lambda record: {'id': record['id'],
                                                         'aid': action.id})
                    )]
           ),
           'has_no_key': has_no_key,
           'has_empty_description': has_empty_description}

    return render(request, 'action/edit_in.html', ctx)
Example #19
0
def edit_action_in(
    request: HttpRequest,
    workflow: Workflow,
    action: Action,
) -> HttpResponse:
    """Edit an action in.

    :param request: Request object
    :param workflow: workflow
    :param action: Action
    :return: HTTP response
    """
    # All tuples (action, column, condition) to consider
    tuples = action.column_condition_pair.all()

    # Columns
    all_columns = workflow.columns

    # Conditions
    filter_condition = action.get_filter()
    all_conditions = action.conditions.filter(is_filter=False)

    # Create the context info.
    context = {
        'action': action,
        # Workflow elements
        'total_rows': workflow.nrows,
        'query_builder_ops': workflow.get_query_builder_ops_as_str(),
        'has_data': workflow.has_table(),
        'selected_rows':
            filter_condition.n_rows_selected if filter_condition else -1,
        'all_false_conditions': any(
            cond.n_rows_selected == 0 for cond in all_conditions
        ),
        # Column elements
        'key_columns': all_columns.filter(is_key=True),
        'stat_columns': all_columns.filter(is_key=False),
        'key_selected': tuples.filter(column__is_key=True).first(),
        'has_no_key': tuples.filter(column__is_key=False).exists(),
        'any_empty_description': tuples.filter(
            column__description_text='',
            column__is_key=False,
        ).exists(),
        'columns_to_insert': all_columns.exclude(
            column_condition_pair__action=action,
        ).exclude(
            is_key=True,
        ).distinct().order_by('position'),
        'column_selected_table': ColumnSelectedTable(
            tuples.filter(column__is_key=False).values(
                'id',
                'column__id',
                'column__name',
                'column__description_text',
                'condition__name',
            ),
            orderable=False,
            extra_columns=[(
                'operations',
                OperationsColumn(
                    verbose_name='',
                    template_file=ColumnSelectedTable.ops_template,
                    template_context=lambda record: {
                        'id': record['column__id'],
                        'aid': action.id}),
            )],
            condition_list=all_conditions,
        ),
        # Conditions
        'filter_condition': filter_condition,
        'conditions': all_conditions,
        'vis_scripts': PlotlyHandler.get_engine_scripts(),
        'other_conditions': Condition.objects.filter(
            action__workflow=workflow, is_filter=False,
        ).exclude(action=action),
    }

    return render(request, 'action/edit_in.html', context)
Example #20
0
class ScheduleActionTable(tables.Table):
    """
    Table to show the email actions scheduled for a workflow
    """

    operations = OperationsColumn(
        attrs={'td': {
            'class': 'dt-body-center'
        }},
        verbose_name=_('Operations'),
        orderable=False,
        template_file='scheduler/includes/partial_scheduler_operations.html',
        template_context=lambda record: {'id': record.id})

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

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

    type = tables.Column(attrs={'td': {
        'class': 'dt-center'
    }},
                         verbose_name=_('Type'),
                         accessor=A('action.get_action_type_display'))

    action = tables.Column(attrs={'td': {
        'class': 'dt-center'
    }},
                           verbose_name=_('Action'),
                           accessor=A('action.name'))

    execute = tables.DateTimeColumn(attrs={'td': {
        'class': 'dt-center'
    }},
                                    verbose_name=_('Scheduled'))

    status = tables.Column(attrs={'td': {
        'class': 'dt-center'
    }},
                           verbose_name=_('Status'),
                           accessor=A('get_status_display'))

    item_column = tables.Column(
        attrs={'td': {
            'class': 'dt-center'
        }},
        verbose_name=_('Item column'),
    )

    exclude_values = tables.Column(
        attrs={'td': {
            'class': 'dt-center'
        }},
        verbose_name=_('Exclude'),
    )

    payload = tables.Column(
        attrs={'td': {
            'class': 'dt-center'
        }},
        verbose_name=_('Parameters'),
    )

    last_executed_log = tables.DateTimeColumn(
        attrs={'td': {
            'class': 'dt-center'
        }},
        verbose_name=_('Result'),
    )

    def render_action(self, record):
        return format_html('<a class="spin" href="{0}">{1}</a>'.format(
            reverse('action:edit', kwargs={'pk': record.action.id}),
            record.action.name))

    def render_exclude_values(self, record):
        return ', '.join(record.exclude_values)

    def render_payload(self, record):
        result = ''
        if not record.payload:
            return result

        for k, v in sorted(record.payload.items()):
            if isinstance(v, list):
                result += '<li>{0}: {1}</li>'.format(
                    escape(str(k)), escape(', '.join([str(x) for x in v])))
            else:
                result += '<li>{0}: {1}</li>'.format(escape(str(k)),
                                                     escape(str(v)))
        return format_html(
            '<ul style="text-align:left;">{0}<ul>'.format(result))

    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>""".format(
            reverse('logs:view', kwargs={'pk': log_item.id}),
            log_item.modified.astimezone(pytz.timezone(settings.TIME_ZONE))))

    class Meta:
        model = ScheduledAction

        fields = ('name', 'description_text', 'action', 'execute', 'status',
                  'item_column', 'exclude_values', 'operations',
                  'last_executed_log')

        sequence = ('operations', 'name', 'description_text', 'type', 'action',
                    'execute', 'status', 'item_column', 'exclude_values',
                    'last_executed_log')

        attrs = {
            'class': 'table display table-bordered',
            'id': 'scheduler-table'
        }

        row_attrs = {
            'style': 'text-align:center;',
            'class': lambda record: 'success' \
                if record.status == ScheduledAction.STATUS_PENDING else ''
        }
Example #21
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'),
        attrs={
            'td': {
                'data-backcolor': lambda record: record.action_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': 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(object):
        """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',
        }