class WorkflowShareTable(tables.Table): """Class to render the table of shared users.""" email = tables.Column( attrs={'td': { 'class': 'dt-body-center' }}, verbose_name=_('User'), ) operations = OperationsColumn( orderable=False, template_file='workflow/includes/partial_share_operations.html', template_context=lambda elems: {'id': elems['id']}, verbose_name='', attrs={'td': { 'class': 'dt-body-center' }}, ) class Meta: """Fields, sequence and attributes.""" fields = ('email', 'id') sequence = ('email', 'operations') attrs = { 'class': 'table', 'id': 'share-table', 'th': { 'class': 'dt-body-center' }, }
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): """Render name field as a link. Impossible to use LinkColumn because href="#". A template may be an overkill. """ 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: """Select fields and attributes.""" fields = ('name', 'value', 'operations') attrs = {'class': 'table', 'id': 'attribute-table'}
def athena_connection_admin_index(request: HttpRequest) -> HttpResponse: """Show and handle the connections. :param request: Request :return: Render the appropriate page. """ remove_workflow_from_session(request) op_column = OperationsColumn( verbose_name='', template_file='dataops/includes/partial_connection_adminop.html', template_context=lambda record: { 'id': record['id'], 'view_url': reverse('dataops:athenaconn_view', kwargs={'pk': record['id']}), 'clone_url': reverse('dataops:athenaconn_clone', kwargs={'pk': record['id']}), 'delete_url': reverse('dataops:athenaconn_delete', kwargs={'pk': record['id']}) }) table = AthenaConnectionTableAdmin( AthenaConnection.objects.values('id', 'name', 'description_text', 'enabled'), orderable=False, extra_columns=[('operations', op_column)]) return render( request, 'dataops/connections_admin.html', { 'table': table, 'title': _('Athena Connections'), 'data_url': reverse('dataops:athenaconn_add') })
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_text') sequence = ('name', 'description_text', 'operations') attrs = { 'class': 'table table-hover table-bordered shadow', 'style': 'width: 100%;', 'id': 'sqlconn-instructor-table', }
def sql_connection_instructor_index( request: HttpRequest, workflow: Optional[Workflow] = None, ) -> HttpResponse: """Render a page showing a table with the available SQL connections. :param request: HTML request :return: HTML response """ del workflow operation_column = OperationsColumn( verbose_name='', template_file='dataops/includes/partial_connection_run.html', template_context=lambda record: { 'id': record['id'], 'run_url': reverse('dataops:sqlupload_start', kwargs={'pk': record['id']}) }) table = SQLConnectionTableRun( SQLConnection.objects.filter(enabled=True).values( 'id', 'name', 'description_text'), orderable=False, extra_columns=[('operations', operation_column)]) return render(request, 'dataops/connections.html', { 'table': table, 'is_sql': True, 'title': _('SQL Connections') })
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: """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', }
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', }
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)
class ScheduleActionTable(tables.Table): """Table to show the email actions scheduled for a workflow.""" 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')) operation_type = tables.Column(verbose_name=_('Type')) execute = tables.DateTimeColumn(verbose_name=_('From')) frequency = tables.Column(verbose_name=_('Frequency')) execute_until = tables.DateTimeColumn(verbose_name=_('Until')) enabled = tables.BooleanColumn(verbose_name=_('Enabled?'), default=True, accessor=A('task__enabled')) status = tables.Column(verbose_name=_('Status'), accessor=A('get_status_display')) @staticmethod def render_operation_type(record): """Create the string with the operation type.""" return models.Log.LOG_TYPES[record.operation_type] @staticmethod def render_frequency(record): """Create the cron description.""" if not record.frequency: return '' return str( ExpressionDescriptor(record.frequency, casing_type=CasingTypeEnum.LowerCase)) @staticmethod def render_enabled(record): """Render the is enabled as a checkbox.""" return render_to_string( 'scheduler/includes/partial_scheduler_enable.html', context={'record': record}, request=None) @staticmethod def render_status(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: """Choose model, fields and sequence in the table.""" model = models.ScheduledOperation fields = ('name', 'operation_type', 'execute', 'frequency', 'execute_until', 'status') sequence = ('operations', 'name', 'operation_type', 'execute', 'frequency', 'execute_until', 'enabled', 'status') attrs = { 'class': 'table table-hover table-bordered shadow', 'style': 'width: 100%;', 'id': 'scheduler-table' }
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'), }, }, ) 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'}