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