Improved navigation and clarity in details view.
This commit is contained in:
@@ -1,14 +1,16 @@
|
||||
"""
|
||||
Webview to show submission and sample details.
|
||||
"""
|
||||
from PyQt6.QtWidgets import (QDialog, QPushButton, QVBoxLayout,
|
||||
QDialogButtonBox, QTextEdit)
|
||||
from PyQt6.QtGui import QColor
|
||||
from PyQt6.QtWidgets import (QDialog, QPushButton, QVBoxLayout,
|
||||
QDialogButtonBox, QTextEdit, QGridLayout)
|
||||
from PyQt6.QtWebEngineWidgets import QWebEngineView
|
||||
from PyQt6.QtWebChannel import QWebChannel
|
||||
from PyQt6.QtCore import Qt, pyqtSlot
|
||||
from jinja2 import TemplateNotFound
|
||||
|
||||
from backend.db.models import BasicSubmission, BasicSample
|
||||
from tools import is_power_user, html_to_pdf
|
||||
from backend.db.models import BasicSubmission, BasicSample, Reagent, KitType
|
||||
from tools import is_power_user, html_to_pdf, jinja_template_loading
|
||||
from .functions import select_save_file
|
||||
from pathlib import Path
|
||||
import logging
|
||||
@@ -25,8 +27,9 @@ logger = logging.getLogger(f"submissions.{__name__}")
|
||||
class SubmissionDetails(QDialog):
|
||||
"""
|
||||
a window showing text details of submission
|
||||
"""
|
||||
def __init__(self, parent, sub:BasicSubmission|BasicSample) -> None:
|
||||
"""
|
||||
|
||||
def __init__(self, parent, sub: BasicSubmission | BasicSample | Reagent) -> None:
|
||||
|
||||
super().__init__(parent)
|
||||
try:
|
||||
@@ -35,15 +38,20 @@ class SubmissionDetails(QDialog):
|
||||
self.app = None
|
||||
self.webview = QWebEngineView(parent=self)
|
||||
self.webview.setMinimumSize(900, 500)
|
||||
self.webview.setMaximumSize(900, 500)
|
||||
self.layout = QVBoxLayout()
|
||||
self.setFixedSize(900, 500)
|
||||
self.webview.setMaximumSize(900, 700)
|
||||
self.webview.loadFinished.connect(self.activate_export)
|
||||
self.layout = QGridLayout()
|
||||
# self.setFixedSize(900, 500)
|
||||
# NOTE: button to export a pdf version
|
||||
btn = QPushButton("Export DOCX")
|
||||
btn.setFixedWidth(875)
|
||||
btn.clicked.connect(self.export)
|
||||
self.layout.addWidget(btn)
|
||||
self.layout.addWidget(self.webview)
|
||||
self.btn = QPushButton("Export DOCX")
|
||||
self.btn.setFixedWidth(775)
|
||||
self.btn.clicked.connect(self.export)
|
||||
self.back = QPushButton("Back")
|
||||
self.back.setFixedWidth(100)
|
||||
self.back.clicked.connect(self.back_function)
|
||||
self.layout.addWidget(self.back, 0, 0, 1, 1)
|
||||
self.layout.addWidget(self.btn, 0, 1, 1, 9)
|
||||
self.layout.addWidget(self.webview, 1, 0, 10, 10)
|
||||
self.setLayout(self.layout)
|
||||
# NOTE: setup channel
|
||||
self.channel = QWebChannel()
|
||||
@@ -54,10 +62,26 @@ class SubmissionDetails(QDialog):
|
||||
self.rsl_plate_num = sub.rsl_plate_num
|
||||
case BasicSample():
|
||||
self.sample_details(sample=sub)
|
||||
case Reagent():
|
||||
self.reagent_details(reagent=sub)
|
||||
self.webview.page().setWebChannel(self.channel)
|
||||
|
||||
def back_function(self):
|
||||
self.webview.back()
|
||||
|
||||
# @pyqtSlot(bool)
|
||||
def activate_export(self):
|
||||
title = self.webview.title()
|
||||
self.setWindowTitle(title)
|
||||
if "Submission" in title:
|
||||
self.btn.setEnabled(True)
|
||||
self.export_plate = title.split(" ")[-1]
|
||||
logger.debug(f"Updating export plate to: {self.export_plate}")
|
||||
else:
|
||||
self.btn.setEnabled(False)
|
||||
|
||||
@pyqtSlot(str)
|
||||
def sample_details(self, sample:str|BasicSample):
|
||||
def sample_details(self, sample: str | BasicSample):
|
||||
"""
|
||||
Changes details view to summary of Sample
|
||||
|
||||
@@ -68,21 +92,49 @@ class SubmissionDetails(QDialog):
|
||||
sample = BasicSample.query(submitter_id=sample)
|
||||
base_dict = sample.to_sub_dict(full_data=True)
|
||||
base_dict, template = sample.get_details_template(base_dict=base_dict)
|
||||
html = template.render(sample=base_dict)
|
||||
template_path = Path(self.template.environment.loader.__getattribute__("searchpath")[0])
|
||||
with open(template_path.joinpath("css", "styles.css"), "r") as f:
|
||||
css = f.read()
|
||||
html = template.render(sample=base_dict, css=css)
|
||||
self.webview.setHtml(html)
|
||||
self.setWindowTitle(f"Sample Details - {sample.submitter_id}")
|
||||
|
||||
# self.btn.setEnabled(False)
|
||||
|
||||
@pyqtSlot(str, str)
|
||||
def reagent_details(self, reagent: str | Reagent, kit: str | KitType):
|
||||
if isinstance(reagent, str):
|
||||
reagent = Reagent.query(lot_number=reagent)
|
||||
if isinstance(kit, str):
|
||||
kit = KitType.query(name=kit)
|
||||
base_dict = reagent.to_sub_dict(extraction_kit=kit, full_data=True)
|
||||
env = jinja_template_loading()
|
||||
temp_name = "reagent_details.html"
|
||||
# logger.debug(f"Returning template: {temp_name}")
|
||||
try:
|
||||
template = env.get_template(temp_name)
|
||||
except TemplateNotFound as e:
|
||||
logger.error(f"Couldn't find template due to {e}")
|
||||
return
|
||||
template_path = Path(self.template.environment.loader.__getattribute__("searchpath")[0])
|
||||
with open(template_path.joinpath("css", "styles.css"), "r") as f:
|
||||
css = f.read()
|
||||
html = template.render(reagent=base_dict, css=css)
|
||||
self.webview.setHtml(html)
|
||||
self.setWindowTitle(f"Reagent Details - {reagent.name} - {reagent.lot}")
|
||||
# self.btn.setEnabled(False)
|
||||
|
||||
@pyqtSlot(str)
|
||||
def submission_details(self, submission:str|BasicSubmission):
|
||||
def submission_details(self, submission: str | BasicSubmission):
|
||||
"""
|
||||
Sets details view to summary of Submission.
|
||||
|
||||
Args:
|
||||
submission (str | BasicSubmission): Submission of interest.
|
||||
"""
|
||||
"""
|
||||
# logger.debug(f"Details for: {submission}")
|
||||
if isinstance(submission, str):
|
||||
submission = BasicSubmission.query(rsl_plate_num=submission)
|
||||
self.rsl_plate_num = submission.rsl_plate_num
|
||||
self.base_dict = submission.to_dict(full_data=True)
|
||||
# logger.debug(f"Submission details data:\n{pformat({k:v for k,v in self.base_dict.items() if k == 'reagents'})}")
|
||||
# NOTE: don't want id
|
||||
@@ -97,10 +149,10 @@ class SubmissionDetails(QDialog):
|
||||
# logger.debug(f"Submission_details: {pformat(self.base_dict)}")
|
||||
self.html = self.template.render(sub=self.base_dict, signing_permission=is_power_user(), css=css)
|
||||
self.webview.setHtml(self.html)
|
||||
self.setWindowTitle(f"Submission Details - {submission.rsl_plate_num}")
|
||||
# self.btn.setEnabled(True)
|
||||
|
||||
@pyqtSlot(str)
|
||||
def sign_off(self, submission:str|BasicSubmission):
|
||||
def sign_off(self, submission: str | BasicSubmission):
|
||||
# logger.debug(f"Signing off on {submission} - ({getuser()})")
|
||||
if isinstance(submission, str):
|
||||
submission = BasicSubmission.query(rsl_plate_num=submission)
|
||||
@@ -112,19 +164,23 @@ class SubmissionDetails(QDialog):
|
||||
"""
|
||||
Renders submission to html, then creates and saves .pdf file to user selected file.
|
||||
"""
|
||||
writer = DocxWriter(base_dict=self.base_dict)
|
||||
fname = select_save_file(obj=self, default_name=self.base_dict['plate_number'], extension="docx")
|
||||
export_plate = BasicSubmission.query(rsl_plate_num=self.export_plate)
|
||||
base_dict = export_plate.to_dict(full_data=True)
|
||||
writer = DocxWriter(base_dict=base_dict)
|
||||
fname = select_save_file(obj=self, default_name=base_dict['plate_number'], extension="docx")
|
||||
writer.save(fname)
|
||||
try:
|
||||
html_to_pdf(html=self.html, output_file=fname)
|
||||
except PermissionError as e:
|
||||
logger.error(f"Error saving pdf: {e}")
|
||||
|
||||
|
||||
class SubmissionComment(QDialog):
|
||||
"""
|
||||
a window for adding comment text to a submission
|
||||
"""
|
||||
def __init__(self, parent, submission:BasicSubmission) -> None:
|
||||
"""
|
||||
|
||||
def __init__(self, parent, submission: BasicSubmission) -> None:
|
||||
|
||||
super().__init__(parent)
|
||||
try:
|
||||
@@ -137,7 +193,8 @@ class SubmissionComment(QDialog):
|
||||
# NOTE: create text field
|
||||
self.txt_editor = QTextEdit(self)
|
||||
self.txt_editor.setReadOnly(False)
|
||||
self.txt_editor.setText("Add Comment")
|
||||
self.txt_editor.setPlaceholderText("Write your comment here.")
|
||||
self.txt_editor.setStyleSheet("background-color: rgb(255, 255, 255);")
|
||||
QBtn = QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
|
||||
self.buttonBox = QDialogButtonBox(QBtn)
|
||||
self.buttonBox.accepted.connect(self.accept)
|
||||
@@ -147,14 +204,16 @@ class SubmissionComment(QDialog):
|
||||
self.layout.addWidget(self.txt_editor)
|
||||
self.layout.addWidget(self.buttonBox, alignment=Qt.AlignmentFlag.AlignBottom)
|
||||
self.setLayout(self.layout)
|
||||
|
||||
|
||||
def parse_form(self) -> List[dict]:
|
||||
"""
|
||||
Adds comment to submission object.
|
||||
"""
|
||||
"""
|
||||
commenter = getuser()
|
||||
comment = self.txt_editor.toPlainText()
|
||||
if comment in ["", None]:
|
||||
return None
|
||||
dt = datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M:%S")
|
||||
full_comment = {"name":commenter, "time": dt, "text": comment}
|
||||
full_comment = {"name": commenter, "time": dt, "text": comment}
|
||||
# logger.debug(f"Full comment: {full_comment}")
|
||||
return full_comment
|
||||
|
||||
Reference in New Issue
Block a user