Dan 2fc4b44ef3 Create a path to directly download the spreadsheet file (and avoid the weird dance on the front end of making an API call to get file data.)
Fixing pagination.  Seems the front end uses a page_index that is 0 based, and sqlAlchemy prefers to start at 1.
2022-03-12 16:19:07 -05:00

118 lines
4.2 KiB
Python

import enum
import urllib
import flask
import marshmallow
from flask import url_for
from marshmallow.fields import Method
from crc import db, ma
from crc.models.study import StudyModel
from crc.models.workflow import WorkflowModel
from crc.services.workflow_spec_service import WorkflowSpecService
from sqlalchemy import func
class MyEnumMeta(enum.EnumMeta):
def __contains__(cls, item):
return item in [v.name for v in cls.__members__.values()]
class TaskLogLevels(enum.Enum, metaclass=MyEnumMeta):
critical = 50
error = 40
warning = 30
info = 20
debug = 10
metrics = 5
class TaskLogModel(db.Model):
__tablename__ = 'task_log'
id = db.Column(db.Integer, primary_key=True)
level = db.Column(db.String)
code = db.Column(db.String)
message = db.Column(db.String)
user_uid = db.Column(db.String)
study_id = db.Column(db.Integer, db.ForeignKey(StudyModel.id), nullable=False)
workflow_id = db.Column(db.Integer, db.ForeignKey(WorkflowModel.id), nullable=False)
workflow_spec_id = db.Column(db.String)
task = db.Column(db.String)
timestamp = db.Column(db.DateTime(timezone=True), server_default=func.now())
class TaskLogModelSchema(ma.Schema):
class Meta:
model = TaskLogModel
fields = ["id", "level", "code", "message", "study_id", "workflow", "workflow_id",
"workflow_spec_id", "category", "user_uid", "timestamp"]
category = marshmallow.fields.Method('get_category')
workflow = marshmallow.fields.Method('get_workflow')
@staticmethod
def get_category(obj):
if hasattr(obj, 'workflow_spec_id') and obj.workflow_spec_id is not None:
workflow_spec = WorkflowSpecService().get_spec(obj.workflow_spec_id)
category = WorkflowSpecService().get_category(workflow_spec.category_id)
return category.display_name
@staticmethod
def get_workflow(obj):
if hasattr(obj, 'workflow_spec_id') and obj.workflow_spec_id is not None:
workflow_spec = WorkflowSpecService().get_spec(obj.workflow_spec_id)
return workflow_spec.display_name
class TaskLogQuery:
"""Encapsulates the paginated queries and results when retrieving and filtering task logs over the
API"""
def __init__(self, study_id=None, code="", level="", user="", page=0, per_page=10,
sort_column=None, sort_reverse=False, items=None,
pages=0, total=0, has_next=False, has_prev=False, download_url=None):
self.study_id = study_id # Filter on Study.
self.code = code # Filter on code.
self.level = level # Filter on level.
self.user = user # Filter on user.
self.page = page
self.per_page = per_page
self.sort_column = sort_column
self.sort_reverse = sort_reverse
self.items = items
self.total = total
self.pages = pages
self.has_next = False
self.has_prev = False
self.download_url = None
def update_from_sqlalchemy_paginator(self, paginator):
"""Updates this with results that are returned from the paginator"""
self.items = paginator.items
self.page = paginator.page - 1
self.per_page = paginator.per_page
self.pages = paginator.pages
self.has_next = paginator.has_next
self.has_prev = paginator.has_prev
self.total = paginator.total
class TaskLogQuerySchema(ma.Schema):
class Meta:
model = TaskLogModel
fields = ["code", "level", "user",
"page", "per_page", "sort_column", "sort_reverse", "items", "pages", "total",
"has_next", "has_prev", "download_url"]
items = marshmallow.fields.List(marshmallow.fields.Nested(TaskLogModelSchema))
download_url = Method("get_url")
def get_url(self, obj):
token = 'not_available'
if hasattr(obj, 'study_id') and obj.study_id is not None:
file_url = url_for("/v1_0.crc_api_study_download_logs_for_study", study_id=obj.study_id, _external=True)
if hasattr(flask.g, 'user'):
token = flask.g.user.encode_auth_token()
url = file_url + '?auth_token=' + urllib.parse.quote_plus(token)
return url
else:
return ""