Esempio n. 1
0
 def test_task_completed_list(self):
     print("--list of completed tasks--start")
     self.client = APIClient()
     self.client.force_authenticate(user=self.user)
     self.assertIsNotNone(self.user)
     response1 = self.client.post(reverse('task_create'), {
         "title": "string",
         "description": "string",
         "user_assigned": 1,
     })
     response2 = self.client.put(
         reverse('update_task'), {
             "id": 1,
             "user_created": 1,
             "user_assigned": 1,
             "title": "updated_title",
             "description": "updated_description",
             "status": "finished"
         })
     response3 = self.client.get(reverse('completed_list'))
     print(response1.status_code)
     print(response2.status_code)
     print("-got tasks--")
     print(response3.json())
     print("--checking for completed status--")
     for task in response3.json():
         task_object = Task.objects.filter(id=task["id"]).first()
         print(
             str(task["id"]) + " : " +
             str("OK" if Task.is_finished(task_object) else
                 ("Wrong status: " + Task.get_status(task_object))))
     self.assertEqual(response3.status_code, 200)
     print("--list of completed tasks--end")
     print("")
Esempio n. 2
0
def project_progress(obj):
    sessions_status_data = {str(i.pk): i.status for i in obj.uploadsession_set.all()}
    completed_sessions = {k: v for k, v in sessions_status_data.items() if v == 'Parsed'}
    uncompleted_sessions = {k: v for k, v in sessions_status_data.items() if v != 'Parsed'}
    project_uploaded_documents_count = Document.objects.filter(
        upload_session__project=obj).count()

    stats = {'project_current_documents_count': obj.document_set.count(),
             'project_uploaded_documents_count': project_uploaded_documents_count,
             'project_tasks_progress': obj.project_tasks_progress,
             'project_tasks_completed': obj.project_tasks_completed,
             'completed_sessions': completed_sessions or None,
             'uncompleted_sessions': uncompleted_sessions or None}

    if obj.type is None:
        project_clusters_documents_count = obj.projectclustering_set.last() \
            .document_clusters.aggregate(c=Count('documents'))['c'] \
            if obj.projectclustering_set.exists() else 0
        project_unclustered_documents_count = project_uploaded_documents_count - \
                                              project_clusters_documents_count
        reassigning_ots = {'task_name': 'reassigning',
                           'old_project_id': obj.pk}
        stats.update({
            'project_clusters_documents_count': project_clusters_documents_count,
            'project_unclustered_documents_count': project_unclustered_documents_count,
            'reassigning_progress': Task.special_tasks_progress_groups(reassigning_ots),
            'reassigning_completed': Task.special_tasks_completed(reassigning_ots),
            'cleanup_completed': Task.special_tasks_completed({'task_name': 'clean-project',
                                                               '_project_id': obj.pk}),
        })

    return stats
Esempio n. 3
0
    def post(self, request, *args, **kwargs):
        form = self.form_class(request.POST)
        if not form.is_valid():
            return self.json_response(form.errors, status=404)
        data = form.cleaned_data
        task_names = set([i.split('_')[0] for i in data if i != 'parse'])
        custom_task_names = task_names & self.custom_tasks
        lexnlp_task_names = task_names - self.custom_tasks

        # custom tasks
        rejected_tasks = []
        started_tasks = []
        for task_name in custom_task_names:
            kwargs = {k.replace('%s_' % task_name, ''): v for k, v in data.items()
                      if k.startswith(task_name)}
            if any(kwargs.values()):
                kwargs['user_id'] = request.user.pk
                if Task.disallow_start(task_name):
                    rejected_tasks.append(task_name)
                else:
                    started_tasks.append(task_name)
                    locator_result_link = self.locator_result_links_map.get(task_name)
                    if locator_result_link:
                        kwargs['metadata'] = {'result_links': [locator_result_link]}
                    call_task(task_name, **kwargs)

        # lexnlp tasks
        lexnlp_task_data = dict()
        for task_name in lexnlp_task_names:
            kwargs = {k.replace('%s_' % task_name, ''): v for k, v in data.items()
                      if k.startswith(task_name)}
            if any(kwargs.values()):
                lexnlp_task_data[task_name] = kwargs

        if lexnlp_task_data:
            if Task.disallow_start('Locate'):
                rejected_tasks.append('Locate')
            else:
                started_tasks.append('Locate')
                call_task('Locate',
                          tasks=lexnlp_task_data,
                          parse=data['parse'],
                          user_id=request.user.pk,
                          metadata={
                              'description': [i for i, j in lexnlp_task_data.items()
                                              if j.get('locate')],
                              'result_links': [self.locator_result_links_map[i]
                                               for i, j in lexnlp_task_data.items()
                                               if j.get('locate')]})

        response_text = ''
        if started_tasks:
            response_text += 'The Task is started. It can take a while.<br />'
            response_text += 'Started tasks: [{}].<br />'.format(', '.join(started_tasks))
        if rejected_tasks:
            response_text += 'Some tasks were rejected (already started).<br />'
            response_text += 'Rejected Tasks: [{}]'.format(', '.join(rejected_tasks))
        return self.json_response(response_text)
Esempio n. 4
0
def create_tasks_sync(task_list, organizer):
    for task in task_list:
        # print(task['agents'])
        agents = task['agents']

        new_task = Task(manager=task['manager'],
                        title=task['title'],
                        address=task['address'],
                        deadline=set_duration(task['duration']))
        new_task.task_type = 'Custom Upload'
        custom_fields = {}
        if task['image_req']:
            new_task.image_required = True
        if task['demand']:
            custom_fields.update({
                'demand_keys': ['Item', 'Quantity'],
                'Demands': []
            })
        for field in task['other_fields']:
            custom_fields.update({field: ''})
        new_task.custom_fields = custom_fields
        new_task.save()
        if len(agents) > 1:
            new_task.agent_list.add(*agents)
            new_task.save()

    organizer.org.subscription.current_usage.consumed_tasks += len(task_list)
    organizer.org.subscription.current_usage.save()
Esempio n. 5
0
 def get_json_data(self, **kwargs):
     Task.update_calculated_fields()
     data = super().get_json_data()
     for item in data['data']:
         item['url'] = reverse('task:task-detail', args=[item['pk']])
         item['purge_url'] = reverse('task:purge-task')
         if item['metadata']:
             metadata = item['metadata']
             item['description'] = metadata.get('description')
             result_links = metadata.get('result_links', [])
             for link_data in result_links:
                 link_data['link'] = reverse(link_data['link'])
             item['result_links'] = result_links
         else:
             item['result_links'] = []
     return data
Esempio n. 6
0
    def post(self, request, *args, **kwargs):
        data = request.POST.dict()
        if not data:
            return self.json_response('error', status=404)
        data['user_id'] = request.user.pk

        rejected_tasks = []
        started_tasks = []
        for task_alias, metadata in self.tasks_map.items():
            task_name = metadata['task_name']
            if Task.disallow_start(task_name):
                rejected_tasks.append(task_name)
                continue
            repo_paths = [
                '{}/{}/{}'.format(settings.GIT_DATA_REPO_ROOT,
                                  j.replace('{}_locale_'.format(i), ''),
                                  DICTIONARY_DATA_URL_MAP[i]) for i in data
                if i.startswith(task_alias) and i in DICTIONARY_DATA_URL_MAP
                for j in data if j.startswith('{}_locale_'.format(i))
            ]
            file_path = data.get('{}_file_path'.format(task_alias)) or None
            delete = '{}_delete'.format(task_alias) in data
            if any([repo_paths, file_path, delete]):
                try:
                    call_task(task_name,
                              repo_paths=repo_paths,
                              file_path=file_path,
                              delete=delete,
                              metadata=metadata)
                except Exception as e:
                    return self.json_response(str(e), status=400)
                started_tasks.append(task_name)
        return self.json_response(TASK_STARTED_MESSAGE)
Esempio n. 7
0
    def post(self, request, *args, **kwargs):
        data = request.POST.dict()
        if not data:
            return self.json_response('error', status=404)
        data['user_id'] = request.user.pk

        rejected_tasks = []
        started_tasks = []
        for task_alias, metadata in self.tasks_map.items():
            task_name = metadata['task_name']
            if Task.disallow_start(task_name):
                rejected_tasks.append(task_name)
                continue
            repo_paths = [
                '{}/{}/{}'.format(settings.GIT_DATA_REPO_ROOT,
                                  j.replace('{}_locale_'.format(i), ''),
                                  self.paths_map[i]) for i in data
                if i.startswith(task_alias) and i in self.paths_map
                for j in data if j.startswith('{}_locale_'.format(i))
            ]
            file_path = data.get('{}_file_path'.format(task_alias)) or None
            delete = '{}_delete'.format(task_alias) in data
            if any([repo_paths, file_path, delete]):
                call_task(task_name,
                          repo_paths=repo_paths,
                          file_path=file_path,
                          delete=delete,
                          metadata=metadata)
                started_tasks.append(task_name)
        return self.json_response('The task is started. It can take a while.')
def cleanup_document_relations(document):

    # delete history
    document.history.all().delete()
    DocumentNote.history.filter(document=document).delete()
    TextUnitNote.history.filter(text_unit__document=document).delete()
    DocumentFieldValue.history.filter(document=document).delete()

    # delete empty Parties
    Party.objects.filter(
        # partyusage__text_unit__document=document,
        partyusage__isnull=True).delete()

    # delete empty Clusters
    DocumentCluster.objects.filter(documents__isnull=True).delete()
    TextUnitCluster.objects.filter(text_units__isnull=True).delete()

    # delete Tasks, Task history, TaskResults, child tasks
    task_kwargs = dict(file_name=document.name)
    if document.upload_session_id:
        task_kwargs['session_id'] = str(document.upload_session_id)
    file_tasks = Task.special_tasks(task_kwargs)
    for file_task in file_tasks:
        if file_task.metadata.get('file_name') == document.name:
            purge_task(file_task.id)
Esempio n. 9
0
def create_task(title,
                manager,
                agent_list=[],
                status=TSD['Unassigned'],
                task_type='Visit'):
    task = Task(
        title=title,
        task_type=task_type,
        manager=manager,
        status=status,
        org=manager.org,
    )
    task.save()
    if len(agent_list) > 0 and status == TSD['Unassigned']:
        task.status = TSD['Remaining']
    for agent in agent_list:
        agent.is_present = True
        if status == TSD['In progress']:
            agent.userstate.active_task = task
            agent.is_working = True
            agent.save()
            agent.userstate.save()
        task.agent_list.add(agent)
    task.save()
    return task
Esempio n. 10
0
 def get(self, request, *args, **kwargs):
     if Task.disallow_start(self.task_name):
         return HttpResponseForbidden(
             'Forbidden. Task "%s" is already started.' % self.task_name)
     else:
         form = self.form_class()
         data = dict(header=form.header,
                     form_class=self.html_form_class,
                     form_data=form.as_p())
     return self.json_response(data)
Esempio n. 11
0
    def process(self, **kwargs):
        project_id = kwargs.get('project_id')
        project = Project.objects.get(pk=project_id)

        # delete prev. CleanProject Task
        Task.special_tasks({
            'task_name': 'clean-project',
            '_project_id': project.pk
        }).delete()
        # delete prev. Reassigning Task
        Task.special_tasks({
            'task_name': 'reassigning',
            'old_project_id': project.pk
        }).delete()

        self.task.subtasks_total = 1
        self.task.metadata = {
            'task_name': 'clean-project',
            '_project_id':
            project_id  # added "_" to avoid detecting task as project task
        }
        self.task.save()

        # delete DocumentClusters
        for pcl in project.projectclustering_set.all():
            pcl.document_clusters.all().delete()
        # delete ProjectClustering
        project.projectclustering_set.all().delete()
        # delete Documents
        project.document_set.all().delete()
        # delete Project Tasks
        project.project_tasks.delete()
        # delete UploadSession Tasks
        for ups in project.uploadsession_set.all():
            ups.document_set.update(upload_session=None)
            ups.session_tasks.delete()

        # delete UploadSessions
        project.uploadsession_set.all().delete()

        self.task.push()
Esempio n. 12
0
    def cleanup(self, delete=False):

        project = self

        # delete prev. CleanProject Task
        Task.special_tasks({
            'task_name': 'clean-project',
            '_project_id': project.pk
        }).delete()
        # delete prev. Reassigning Task
        Task.special_tasks({
            'task_name': 'reassigning',
            'old_project_id': project.pk
        }).delete()

        # delete DocumentClusters
        for pcl in project.projectclustering_set.all():
            pcl.document_clusters.all().delete()

        # delete ProjectClustering
        project.projectclustering_set.all().delete()

        # delete Documents in loop to not hung a server
        for document in project.document_set.all():
            document.delete()

        # delete Project Tasks
        project.project_tasks.delete()

        # delete UploadSession Tasks
        for ups in project.uploadsession_set.all():
            ups.document_set.update(upload_session=None)
            ups.session_tasks.delete()

        # delete UploadSessions
        project.uploadsession_set.all().delete()

        # delete project itself
        if delete:
            project.delete()
Esempio n. 13
0
    def __init__(self, prefix, instance: Task, initial):
        super().__init__()
        self.fields['name'].initial = instance.name

        logs = list()
        # on this stage it was quite hard to implement proper formatting in templates
        # so putting some html/js right here.
        # TODO: Refactor, put formatting to the templates

        # Main problem is that this form's template uses some base template which replaces \n with <br />
        for record in instance.get_task_log_from_elasticsearch():
            color = 'green'
            if record.log_level == 'WARN':
                color = 'yellow'
            elif record.log_level == 'ERROR':
                color = 'red'

            if not record.timestamp:
                ts = ''
            else:
                ts = record.timestamp.strftime('%Y-%m-%d %H:%M:%S')

            level = record.log_level or 'INFO'
            message = record.message
            if message and '\n' in message:
                message = '<br />' + message

            log_add = f'<b><span style="color: {color}">{level}</span> {ts} | {record.task_name or "no task"} |</b> ' \
                      f'{message}'

            logs.append(log_add)

            if record.stack_trace:
                # Adding JS to toggle stack trace showing/hiding
                stack = record.stack_trace.replace('\n', '<br />')
                uid = str(fast_uuid())
                uid_toggle = uid + '_toggle'
                show_hide = f'''e = document.getElementById('{uid}');
                                e.style.display = e.style.display === 'block' ? 'none' : 'block';
                                document.getElementById('{uid_toggle}').innerText 
                                        = e.style.display === 'block' ? '[-] Stack trace:' : '[+] Stack trace';
                            '''.replace('\n', '')
                logs.append(
                    f'<a id="{uid_toggle}" onclick="{show_hide}">[+] Stack trace:</a>'
                )
                logs.append(
                    f'<div id="{uid}" style="display: none; border-left: 1px solid grey; padding-left: 16px">'
                    f'{stack}</div>')

        self.fields['log'].initial = '\n'.join(logs)
 def get_task_detail(cls, task: Task) -> TaskRecord:
     reason = f'is started at {task.date_work_start} and not finished yet' if task.status == PENDING else 'is failed'
     r = TaskRecord(task.pk, task.name, reason, task.status,
                    task.date_work_start or task.date_start,
                    task.date_done or task.own_date_done,
                    task.user_id)
     for record in task.get_task_log_from_elasticsearch():
         r.kibana_ref = kibana_root_url(record.record_id, record.file_index, add_protocol=False)
         if not hasattr(record, 'stack_trace') or not hasattr(record, 'message') \
                 or record.log_level != 'ERROR':
             continue
         r.error_message = record.message
         r.stack_trace = record.stack_trace
         break
     return r
Esempio n. 15
0
 def post(self, request, *args, **kwargs):
     if Task.disallow_start(self.task_name):
         return HttpResponseForbidden(
             'Forbidden. Such task is already started.')
     if self.form_class is None:
         data = request.POST.dict()
     else:
         form = self.form_class(request.POST)
         if not form.is_valid():
             return self.json_response(form.errors, status=400)
         data = form.cleaned_data
     data['user_id'] = request.user.pk
     data['metadata'] = self.get_metadata()
     call_task(self.task_name, **data)
     return self.json_response('The task is started. It can take a while.')
Esempio n. 16
0
    def addEditTask(self, param):

        if param.has_key('id'):
            id = int(param['id'])
        else:
            id = 0

        if id == 0:
            task = Task()
        else:
            task = self.getTaskId(id)

        if param.has_key('name'):
            task.name = str(param['name'].encode('utf-8'))

        if param.has_key('is_folder'):
            task.is_folder = int(param['is_folder'])

        if param.has_key('main'):
            task.main = int(param['main'])

        if param.has_key('percent'):
            task.percent = int(param['percent'])

        if param.has_key('important'):
            task.important = int(param['important'])

        if param.has_key('checked_id'):
            task.checked_id = int(param['checked_id'])

        if param.has_key('staff_id'):
            task.staff_id = int(param['staff_id'])

        if param.has_key('status_id'):
            task.status_id = int(param['status_id'])

        if param.has_key('date_start'):
            task.date_start = date_sql(str(param['date_start']))

        if param.has_key('date_end'):
            task.date_end = date_sql(str(param['date_end']))

        if param.has_key('date_checked'):
            task.date_checked = date_sql(str(param['date_checked']))

        if param.has_key('parent'):
            parent = self.getTaskId(int(param['parent']))
            if parent:
                task.parent = parent


        task.save()


        if param.has_key('responsible'):
            task.responsible.add(param['responsible'])

        return task
Esempio n. 17
0
    def post(self, request, *args, **kwargs):
        form = self.form_class(request.POST)
        if not form.is_valid():
            return self.json_response(form.errors, status=400)
        data = form.cleaned_data

        project_id = None
        project_ref = data.get('project')
        if project_ref:
            del data['project']
            project_id = project_ref.pk

        task_names = set([i.split('_')[0] for i in data if i != 'parse'])
        custom_task_names = task_names & self.custom_tasks
        lexnlp_task_names = task_names - self.custom_tasks

        # custom tasks
        rejected_tasks = []
        started_tasks = []
        for task_name in custom_task_names:
            kwargs = {
                k.replace('%s_' % task_name, ''): v
                for k, v in data.items() if k.startswith(task_name)
            }
            if any(kwargs.values()):
                kwargs['user_id'] = request.user.pk
                if Task.disallow_start(task_name):
                    rejected_tasks.append(task_name)
                else:
                    started_tasks.append(task_name)
                    locator_result_link = self.locator_result_links_map.get(
                        task_name)
                    if locator_result_link:
                        kwargs['metadata'] = {
                            'result_links': [locator_result_link]
                        }
                    try:
                        call_task(task_name, **kwargs)
                    except Exception as e:
                        return self.json_response(str(e), status=400)

        # lexnlp tasks
        lexnlp_task_data = dict()
        for task_name in lexnlp_task_names:
            kwargs = {
                k.replace('%s_' % task_name, ''): v
                for k, v in data.items() if k.startswith(task_name)
            }
            if any(kwargs.values()):
                lexnlp_task_data[task_name] = kwargs

        if lexnlp_task_data:
            # allow to start "Locate" task anytime
            started_tasks.append('Locate({})'.format(', '.join(
                lexnlp_task_data.keys())))
            try:
                call_task('Locate',
                          tasks=lexnlp_task_data,
                          parse=data['parse'],
                          user_id=request.user.pk,
                          project_id=project_id,
                          metadata={
                              'description': [
                                  i for i, j in lexnlp_task_data.items()
                                  if j.get('locate')
                              ],
                              'result_links': [
                                  self.locator_result_links_map[i]
                                  for i, j in lexnlp_task_data.items()
                                  if j.get('locate')
                              ]
                          })
            except Exception as e:
                return self.json_response(str(e), status=400)

        response_text = ''
        if started_tasks:
            response_text += f'{TASK_STARTED_MESSAGE}<br /><br />'
            response_text += 'Started tasks: [{}].<br />'.format(
                ', '.join(started_tasks))
        if rejected_tasks:
            response_text += 'Some tasks were rejected (already started).<br />'
            response_text += 'Rejected Tasks: [{}]'.format(
                ', '.join(rejected_tasks))
        return self.json_response(response_text)
Esempio n. 18
0
 def disallow_start(self):
     return Task.disallow_start(self.task_name)
 def session_tasks(self):
     """
     Get tasks related with session
     """
     return Task.special_tasks({'session_id': str(self.pk)})
 def project_tasks_completed(self):
     """
     Whether project tasks completed or not (None if no project tasks at all)
     """
     return Task.special_tasks_completed({'project_id': str(self.pk)})
 def project_tasks_progress(self):
     """
     Detailed Progress of project tasks like Clustering
     """
     return Task.special_tasks_progress({'project_id': str(self.pk)})
 def project_tasks(self):
     """
     Get tasks related with Project
     """
     return Task.special_tasks({'project_id': str(self.pk)})
Esempio n. 23
0
    def __init__(self, prefix, instance: Task, initial):
        super().__init__()
        display_name = instance.display_name or instance.name
        if display_name != instance.name:
            display_name += f' ({instance.name})'
        if instance.status != SUCCESS:
            display_name += f' STATUS: {instance.status}'
        if instance.progress < 100:
            display_name += f' ({instance.progress}%)'

        self.fields['task'].initial = display_name
        self.fields['parents'].initial = ''
        self.fields['child_tasks'].initial = ''

        logs = list()
        # on this stage it was quite hard to implement proper formatting in templates
        # so putting some html/js right here.
        # TODO: Refactor, put formatting to the templates

        # list ancestors (parent tasks) up to the root
        parents_markup = []
        this_task = instance
        while this_task.parent_task_id:
            parent = this_task.parent_task
            task_name = parent.display_name or parent.name
            url = reverse('task:task-detail', args=[parent.pk])
            color = self.COLOR_BY_STATUS.get(
                parent.status) or self.COLOR_BY_STATUS['default']
            link_name = task_name if parent.progress == 100 else f'{task_name} ({parent.progress}%)'
            parents_markup.append(
                f'<a style="{color}" href="{url}">{link_name}</a>')
            this_task = this_task.parent_task

        markup = ''
        if parents_markup:
            markup = ' &lt;- '.join(parents_markup)
        self.fields['parents'].initial = markup

        # list child tasks
        child_query = Task.objects.filter(parent_task_id=instance.pk)
        children_count = child_query.count()
        children = list(
            child_query.values_list('pk', 'name', 'display_name', 'status',
                                    'progress')[:30])
        children_markup = []
        for pk, name, display_name, status, progress in children:
            url = reverse('task:task-detail', args=[pk])
            color = self.COLOR_BY_STATUS.get(
                status) or self.COLOR_BY_STATUS['default']
            task_name = display_name or name
            link_name = task_name if progress == 100 else f'{task_name} ({progress}%)'
            children_markup.append(
                f'<a style="{color}" href="{url}">{link_name}</a>')
        if children_count > len(children):
            children_markup.append(
                f' ... and {children_count - len(children)} more')
        self.fields['child_tasks'].initial = ', '.join(children_markup)

        # Main problem is that this form's template uses some base template which replaces \n with <br />
        for record in instance.get_task_log_from_elasticsearch():
            color = 'green'
            if record.log_level == 'WARN':
                color = 'yellow'
            elif record.log_level == 'ERROR':
                color = 'red'

            if not record.timestamp:
                ts = ''
            else:
                ts = record.timestamp.strftime('%Y-%m-%d %H:%M:%S')

            level = record.log_level or 'INFO'
            message = record.message
            if message and '\n' in message:
                message = '<br />' + message

            log_add = f'<b><span style="color: {color}">{level}</span> {ts} | {record.task_name or "no task"} |</b> ' \
                      f'{message}'

            logs.append(log_add)

            if record.stack_trace:
                # Adding JS to toggle stack trace showing/hiding
                stack = record.stack_trace.replace('\n', '<br />')
                uid = str(fast_uuid())
                uid_toggle = uid + '_toggle'
                show_hide = f'''e = document.getElementById('{uid}');
                                e.style.display = e.style.display === 'block' ? 'none' : 'block';
                                document.getElementById('{uid_toggle}').innerText 
                                        = e.style.display === 'block' ? '[-] Stack trace:' : '[+] Stack trace';
                            '''.replace('\n', '')
                logs.append(
                    f'<a id="{uid_toggle}" onclick="{show_hide}">[+] Stack trace:</a>'
                )
                logs.append(
                    f'<div id="{uid}" style="display: none; border-left: 1px solid grey; padding-left: 16px">'
                    f'{stack}</div>')

        self.fields['log'].initial = '\n'.join(logs)
Esempio n. 24
0
    def __init__(self, prefix, instance: Task, initial):
        super().__init__()
        display_name = instance.display_name or instance.name
        if display_name != instance.name:
            display_name += f' ({instance.name})'
        if instance.status != SUCCESS:
            display_name += f' STATUS: {instance.status}'
        if instance.progress < 100:
            display_name += f' ({instance.progress}%)'

        self.fields['task'].initial = display_name
        self.fields['parents'].initial = ''
        self.fields['child_tasks'].initial = ''

        logs = list()  # type: List[str]
        # on this stage it was quite hard to implement proper formatting in templates
        # so putting some html/js right here.
        # TODO: Refactor, put formatting to the templates

        # list ancestors (parent tasks) up to the root
        parents_markup = []
        this_task = instance
        while this_task.parent_task_id:
            parent = this_task.parent_task
            task_name = parent.display_name or parent.name
            url = reverse('task:task-detail', args=[parent.pk])
            color = self.COLOR_BY_STATUS.get(parent.status) or self.COLOR_BY_STATUS['default']
            link_name = task_name if parent.progress == 100 else f'{task_name} ({parent.progress}%)'
            parents_markup.append(f'<a style="{color}" href="{url}">{link_name}</a>')
            this_task = this_task.parent_task

        markup = ''
        if parents_markup:
            markup = ' &lt;- '.join(parents_markup)
        self.fields['parents'].initial = markup

        # list child tasks
        child_query = Task.objects.filter(parent_task_id=instance.pk)
        children_count = child_query.count()
        children = list(child_query.values_list(
            'pk', 'name', 'display_name', 'status', 'progress')[:30])
        children_markup = []
        for pk, name, display_name, status, progress in children:
            url = reverse('task:task-detail', args=[pk])
            color = self.COLOR_BY_STATUS.get(status) or self.COLOR_BY_STATUS['default']
            task_name = display_name or name
            link_name = task_name if progress == 100 else f'{task_name} ({progress}%)'
            children_markup.append(f'<a style="{color}" href="{url}">{link_name}</a>')
        if children_count > len(children):
            children_markup.append(f' ... and {children_count - len(children)} more')
        self.fields['child_tasks'].initial = ', '.join(children_markup)

        if this_task.result and 'exc_type' in this_task.result:
            ex_module = this_task.result.get('exc_module') or '-'
            ex_message = this_task.result.get('exc_message') or '-'
            msg = f'<b><span style="color:red">ERROR</span> {this_task.result["exc_type"]} ' + \
                  f'in {ex_module}:\n{ex_message}'
            logs.append(msg)

        # Main problem is that this form's template uses some base template which replaces \n with <br />
        should_search_errors = this_task.status in {FAILURE, REVOKED} or \
            this_task.own_status in {FAILURE, REVOKED}
        all_records = instance.get_task_log_from_elasticsearch(should_search_errors)
        task_records = [r for r in all_records if r.task_name]
        genr_records = [r for r in all_records if not r.task_name]

        for record in task_records:
            color = self.get_task_record_color(record)
            ts = record.timestamp.strftime('%Y-%m-%d %H:%M:%S') if record.timestamp else ''
            level = record.log_level or 'INFO'
            message = record.message or ''
            message = '<br />' + message if '\n' in message else message

            log_add = f'<b><span style="color: {color}">{level}</span> {ts} | {record.task_name or "no task"} |</b> ' \
                      f'{message}'
            logs.append(log_add)

            if record.stack_trace:
                # Adding JS to toggle stack trace showing/hiding
                stack = record.stack_trace.replace('<', '&lt;').replace(
                    '>', '&gt;').replace('\n', '<br />')
                self.render_collapsible_block(logs, stack, 'Stack trace')

        # show system-wide errors in collapsible block
        if genr_records:
            logs.append(f'<br/><h4>{len(genr_records)} error(s) also occurred after completing the task</h4>')
            inner_block = ''
            for record in genr_records:
                color = self.get_task_record_color(record)
                ts = record.timestamp.strftime('%Y-%m-%d %H:%M:%S') if record.timestamp else ''
                level = record.log_level or 'INFO'
                message = record.message or ''
                message = '<br />' + message if '\n' in message else message
                log_add = f'<b><span style="color: {color}">{level}</span> {ts} </b> ' \
                          f'{message}<br/>'
                inner_block += log_add
            self.render_collapsible_block(logs, inner_block, 'System-wide errors')

        self.fields['log'].initial = '\n'.join(logs)
Esempio n. 25
0
 def __init__(self, prefix, instance: Task, initial):
     super().__init__()
     self.fields['name'].initial = instance.name
     self.fields['log'].initial = instance.get_task_log_from_elasticsearch()