Various bugfixes, new template sub-docs
This commit is contained in:
BIN
requirements.txt
BIN
requirements.txt
Binary file not shown.
@@ -1499,7 +1499,7 @@ class Process(BaseClass):
|
|||||||
@setup_lookup
|
@setup_lookup
|
||||||
def query(cls,
|
def query(cls,
|
||||||
name: str | None = None,
|
name: str | None = None,
|
||||||
id: int = 1,
|
id: int | None = None,
|
||||||
limit: int = 0) -> Process | List[Process]:
|
limit: int = 0) -> Process | List[Process]:
|
||||||
"""
|
"""
|
||||||
Lookup Processes
|
Lookup Processes
|
||||||
@@ -1514,7 +1514,7 @@ class Process(BaseClass):
|
|||||||
query = cls.__database_session__.query(cls)
|
query = cls.__database_session__.query(cls)
|
||||||
match name:
|
match name:
|
||||||
case str():
|
case str():
|
||||||
# logger.debug(f"Lookup Process with name str {name}")
|
logger.debug(f"Lookup Process with name str {name}")
|
||||||
query = query.filter(cls.name == name)
|
query = query.filter(cls.name == name)
|
||||||
limit = 1
|
limit = 1
|
||||||
case _:
|
case _:
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ from dateutil.parser import parse
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from jinja2.exceptions import TemplateNotFound
|
from jinja2.exceptions import TemplateNotFound
|
||||||
from jinja2 import Template
|
from jinja2 import Template
|
||||||
|
from docxtpl import InlineImage
|
||||||
|
from io import BytesIO
|
||||||
|
|
||||||
logger = logging.getLogger(f"submissions.{__name__}")
|
logger = logging.getLogger(f"submissions.{__name__}")
|
||||||
|
|
||||||
@@ -730,7 +732,7 @@ class BasicSubmission(BaseClass):
|
|||||||
return input_excel
|
return input_excel
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def custom_docx_writer(cls, input_dict):
|
def custom_docx_writer(cls, input_dict:dict, tpl_obj=None):
|
||||||
|
|
||||||
return input_dict
|
return input_dict
|
||||||
|
|
||||||
@@ -1493,7 +1495,7 @@ class Wastewater(BasicSubmission):
|
|||||||
# self.report.add_result(Result(msg=f"We added PCR info to {sub.rsl_plate_num}.", status='Information'))
|
# self.report.add_result(Result(msg=f"We added PCR info to {sub.rsl_plate_num}.", status='Information'))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def custom_docx_writer(cls, input_dict):
|
def custom_docx_writer(cls, input_dict:dict, tpl_obj=None):
|
||||||
from backend.excel.writer import DocxWriter
|
from backend.excel.writer import DocxWriter
|
||||||
input_dict = super().custom_docx_writer(input_dict)
|
input_dict = super().custom_docx_writer(input_dict)
|
||||||
well_24 = []
|
well_24 = []
|
||||||
@@ -1551,7 +1553,7 @@ class WastewaterArtic(BasicSubmission):
|
|||||||
if report:
|
if report:
|
||||||
return output
|
return output
|
||||||
output['gel_info'] = self.gel_info
|
output['gel_info'] = self.gel_info
|
||||||
output['gel_image'] = self.gel_image
|
output['gel_image_path'] = self.gel_image
|
||||||
output['dna_core_submission_number'] = self.dna_core_submission_number
|
output['dna_core_submission_number'] = self.dna_core_submission_number
|
||||||
output['source_plates'] = self.source_plates
|
output['source_plates'] = self.source_plates
|
||||||
output['artic_date'] = self.artic_date or self.submitted_date
|
output['artic_date'] = self.artic_date or self.submitted_date
|
||||||
@@ -1856,7 +1858,7 @@ class WastewaterArtic(BasicSubmission):
|
|||||||
"""
|
"""
|
||||||
base_dict, template = super().get_details_template(base_dict=base_dict)
|
base_dict, template = super().get_details_template(base_dict=base_dict)
|
||||||
base_dict['excluded'] += ['gel_info', 'gel_image', 'headers', "dna_core_submission_number", "source_plates",
|
base_dict['excluded'] += ['gel_info', 'gel_image', 'headers', "dna_core_submission_number", "source_plates",
|
||||||
"gel_controls"]
|
"gel_controls, gel_image_path"]
|
||||||
base_dict['DNA Core ID'] = base_dict['dna_core_submission_number']
|
base_dict['DNA Core ID'] = base_dict['dna_core_submission_number']
|
||||||
# check = 'gel_info' in base_dict.keys() and base_dict['gel_info'] is not None
|
# check = 'gel_info' in base_dict.keys() and base_dict['gel_info'] is not None
|
||||||
if check_key_or_attr(key='gel_info', interest=base_dict, check_none=True):
|
if check_key_or_attr(key='gel_info', interest=base_dict, check_none=True):
|
||||||
@@ -1865,9 +1867,9 @@ class WastewaterArtic(BasicSubmission):
|
|||||||
base_dict['headers'] += headers
|
base_dict['headers'] += headers
|
||||||
# logger.debug(f"Gel info: {pformat(base_dict['headers'])}")
|
# logger.debug(f"Gel info: {pformat(base_dict['headers'])}")
|
||||||
# check = 'gel_image' in base_dict.keys() and base_dict['gel_image'] is not None
|
# check = 'gel_image' in base_dict.keys() and base_dict['gel_image'] is not None
|
||||||
if check_key_or_attr(key='gel_image', interest=base_dict, check_none=True):
|
if check_key_or_attr(key='gel_image_path', interest=base_dict, check_none=True):
|
||||||
with ZipFile(cls.__directory_path__.joinpath("submission_imgs.zip")) as zipped:
|
with ZipFile(cls.__directory_path__.joinpath("submission_imgs.zip")) as zipped:
|
||||||
base_dict['gel_image'] = base64.b64encode(zipped.read(base_dict['gel_image'])).decode('utf-8')
|
base_dict['gel_image'] = base64.b64encode(zipped.read(base_dict['gel_image_path'])).decode('utf-8')
|
||||||
return base_dict, template
|
return base_dict, template
|
||||||
|
|
||||||
# def adjust_to_dict_samples(self, backup: bool = False) -> List[dict]:
|
# def adjust_to_dict_samples(self, backup: bool = False) -> List[dict]:
|
||||||
@@ -1935,6 +1937,20 @@ class WastewaterArtic(BasicSubmission):
|
|||||||
zipf.write(img_path, self.gel_image)
|
zipf.write(img_path, self.gel_image)
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def custom_docx_writer(cls, input_dict:dict, tpl_obj=None):
|
||||||
|
input_dict = super().custom_docx_writer(input_dict)
|
||||||
|
if check_key_or_attr(key='gel_image_path', interest=input_dict, check_none=True):
|
||||||
|
with ZipFile(cls.__directory_path__.joinpath("submission_imgs.zip")) as zipped:
|
||||||
|
img = zipped.read(input_dict['gel_image_path'])
|
||||||
|
with tempfile.TemporaryFile(mode="wb", suffix=".jpg", delete=False) as tmp:
|
||||||
|
tmp.write(img)
|
||||||
|
logger.debug(f"Tempfile: {tmp.name}")
|
||||||
|
img = InlineImage(tpl_obj, image_descriptor=tmp.name)#, width=5.5)#, height=400)
|
||||||
|
input_dict['gel_image'] = img
|
||||||
|
return input_dict
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Sample Classes
|
# Sample Classes
|
||||||
|
|
||||||
|
|||||||
@@ -477,7 +477,7 @@ class DocxWriter(object):
|
|||||||
base_dict['excluded'] += ["platemap"]
|
base_dict['excluded'] += ["platemap"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
base_dict['excluded'] = ["platemap"]
|
base_dict['excluded'] = ["platemap"]
|
||||||
base_dict = self.sub_obj.custom_docx_writer(base_dict)
|
base_dict = self.sub_obj.custom_docx_writer(base_dict, tpl_obj=self.template)
|
||||||
# logger.debug(f"Base dict: {pformat(base_dict)}")
|
# logger.debug(f"Base dict: {pformat(base_dict)}")
|
||||||
self.template.render({"sub": base_dict})
|
self.template.render({"sub": base_dict})
|
||||||
|
|
||||||
|
|||||||
@@ -304,7 +304,10 @@ class PydEquipment(BaseModel, extra='ignore'):
|
|||||||
value = ['']
|
value = ['']
|
||||||
if len(value) == 0:
|
if len(value) == 0:
|
||||||
value = ['']
|
value = ['']
|
||||||
value = [item.strip() for item in value]
|
try:
|
||||||
|
value = [item.strip() for item in value]
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def toSQL(self, submission: BasicSubmission | str = None) -> Tuple[Equipment, SubmissionEquipmentAssociation]:
|
def toSQL(self, submission: BasicSubmission | str = None) -> Tuple[Equipment, SubmissionEquipmentAssociation]:
|
||||||
|
|||||||
@@ -59,7 +59,10 @@ class EquipmentUsage(QDialog):
|
|||||||
case _:
|
case _:
|
||||||
pass
|
pass
|
||||||
logger.debug(f"parsed output of Equsage form: {pformat(output)}")
|
logger.debug(f"parsed output of Equsage form: {pformat(output)}")
|
||||||
return [item.strip() for item in output if item is not None]
|
try:
|
||||||
|
return [item.strip() for item in output if item is not None]
|
||||||
|
except AttributeError:
|
||||||
|
return [item for item in output if item is not None]
|
||||||
|
|
||||||
class LabelRow(QWidget):
|
class LabelRow(QWidget):
|
||||||
|
|
||||||
@@ -131,8 +134,8 @@ class RoleComboBox(QWidget):
|
|||||||
"""
|
"""
|
||||||
Changes what tips are available when process is changed
|
Changes what tips are available when process is changed
|
||||||
"""
|
"""
|
||||||
process = self.process.currentText()
|
process = self.process.currentText().strip()
|
||||||
logger.debug(f"Checking process: {process}")
|
logger.debug(f"Checking process: {process} for equipment {self.role.name}")
|
||||||
process = Process.query(name=process)
|
process = Process.query(name=process)
|
||||||
if process.tip_roles:
|
if process.tip_roles:
|
||||||
for iii, tip_role in enumerate(process.tip_roles):
|
for iii, tip_role in enumerate(process.tip_roles):
|
||||||
|
|||||||
@@ -54,9 +54,11 @@ class GelBox(QDialog):
|
|||||||
layout = QGridLayout()
|
layout = QGridLayout()
|
||||||
layout.addWidget(QLabel("DNA Core Submission Number"),0,1)
|
layout.addWidget(QLabel("DNA Core Submission Number"),0,1)
|
||||||
self.core_number = QLineEdit()
|
self.core_number = QLineEdit()
|
||||||
|
self.core_number.setText(self.submission.dna_core_submission_number)
|
||||||
layout.addWidget(self.core_number, 0,2)
|
layout.addWidget(self.core_number, 0,2)
|
||||||
layout.addWidget(QLabel("Gel Barcode"),0,3)
|
layout.addWidget(QLabel("Gel Barcode"),0,3)
|
||||||
self.gel_barcode = QLineEdit()
|
self.gel_barcode = QLineEdit()
|
||||||
|
self.gel_barcode.setText(self.submission.gel_barcode)
|
||||||
layout.addWidget(self.gel_barcode, 0, 4)
|
layout.addWidget(self.gel_barcode, 0, 4)
|
||||||
# setting this layout to the widget
|
# setting this layout to the widget
|
||||||
# plot window goes on right side, spanning 3 rows
|
# plot window goes on right side, spanning 3 rows
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ from backend.db.models import BasicSubmission, BasicSample
|
|||||||
from tools import is_power_user, html_to_pdf
|
from tools import is_power_user, html_to_pdf
|
||||||
from .functions import select_save_file
|
from .functions import select_save_file
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from tempfile import TemporaryFile, TemporaryDirectory
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import logging, base64
|
import logging, base64
|
||||||
from getpass import getuser
|
from getpass import getuser
|
||||||
@@ -43,7 +42,7 @@ class SubmissionDetails(QDialog):
|
|||||||
self.layout = QVBoxLayout()
|
self.layout = QVBoxLayout()
|
||||||
self.setFixedSize(900, 500)
|
self.setFixedSize(900, 500)
|
||||||
# NOTE: button to export a pdf version
|
# NOTE: button to export a pdf version
|
||||||
btn = QPushButton("Export PDF")
|
btn = QPushButton("Export DOCX")
|
||||||
btn.setFixedWidth(875)
|
btn.setFixedWidth(875)
|
||||||
btn.clicked.connect(self.export)
|
btn.clicked.connect(self.export)
|
||||||
self.layout.addWidget(btn)
|
self.layout.addWidget(btn)
|
||||||
@@ -103,8 +102,6 @@ class SubmissionDetails(QDialog):
|
|||||||
logger.debug(f"Submission_details: {pformat(self.base_dict)}")
|
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.html = self.template.render(sub=self.base_dict, signing_permission=is_power_user(), css=css)
|
||||||
self.webview.setHtml(self.html)
|
self.webview.setHtml(self.html)
|
||||||
with open("test.html", "w") as f:
|
|
||||||
f.write(self.html)
|
|
||||||
self.setWindowTitle(f"Submission Details - {submission.rsl_plate_num}")
|
self.setWindowTitle(f"Submission Details - {submission.rsl_plate_num}")
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
|
|||||||
Reference in New Issue
Block a user