diff --git a/CHANGELOG.md b/CHANGELOG.md index 61ccd40..e093436 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## 202409.05 +- Replaced some lists with generators to improve speed, added javascript to templates for click events. - Added in custom field for BasicSubmission which will allow limited new fields to be added to generic submission types. ## 202409.04 diff --git a/src/submissions/backend/db/models/submissions.py b/src/submissions/backend/db/models/submissions.py index 073165c..0048192 100644 --- a/src/submissions/backend/db/models/submissions.py +++ b/src/submissions/backend/db/models/submissions.py @@ -1042,7 +1042,7 @@ class BasicSubmission(BaseClass): # return [item.to_sub_dict() for item in self.submission_sample_associations] @classmethod - def get_details_template(cls, base_dict: dict) -> Tuple[dict, Template]: + def get_details_template(cls, base_dict: dict) -> Template: """ Get the details jinja template for the correct class @@ -1357,13 +1357,13 @@ class BasicSubmission(BaseClass): if fname.name == "": # logger.debug(f"export cancelled.") return - if full_backup: - backup = self.to_dict(full_data=True) - try: - with open(self.__backup_path__.joinpath(fname.with_suffix(".yml")), "w") as f: - yaml.dump(backup, f) - except KeyError as e: - logger.error(f"Problem saving yml backup file: {e}") + # if full_backup: + # backup = self.to_dict(full_data=True) + # try: + # with open(self.__backup_path__.joinpath(fname.with_suffix(".yml")), "w") as f: + # yaml.dump(backup, f) + # except KeyError as e: + # logger.error(f"Problem saving yml backup file: {e}") writer = pyd.to_writer() writer.xl.save(filename=fname.with_suffix(".xlsx")) @@ -1632,6 +1632,8 @@ class Wastewater(BasicSubmission): dict: Updated information """ input_dict = super().finalize_details(input_dict) + # NOTE: Currently this is preserving the generator items, can we come up with a better way? + input_dict['samples'] = [sample for sample in input_dict['samples']] dummy_samples = [] for item in input_dict['samples']: # logger.debug(f"Sample dict: {item}") @@ -1681,12 +1683,10 @@ class Wastewater(BasicSubmission): for sample in self.samples: # logger.debug(f"Running update on: {sample}") try: - # sample_dict = [item for item in parser.samples if item['sample'] == sample.rsl_number][0] sample_dict = next(item for item in parser.samples if item['sample'] == sample.rsl_number) except StopIteration: continue self.update_subsampassoc(sample=sample, input_dict=sample_dict) - # self.report.add_result(Result(msg=f"We added PCR info to {sub.rsl_plate_num}.", status='Information')) @classmethod def custom_docx_writer(cls, input_dict: dict, tpl_obj=None) -> dict: @@ -1703,6 +1703,7 @@ class Wastewater(BasicSubmission): from backend.excel.writer import DocxWriter input_dict = super().custom_docx_writer(input_dict) well_24 = [] + input_dict['samples'] = [item for item in input_dict['samples']] samples_copy = deepcopy(input_dict['samples']) for sample in sorted(samples_copy, key=itemgetter('column', 'row')): try: diff --git a/src/submissions/backend/excel/writer.py b/src/submissions/backend/excel/writer.py index 79e5296..61f8104 100644 --- a/src/submissions/backend/excel/writer.py +++ b/src/submissions/backend/excel/writer.py @@ -519,6 +519,7 @@ class DocxWriter(object): Args: base_dict (dict): dictionary of info to be written to template. """ + logger.debug(f"Incoming base dict: {pformat(base_dict)}") self.sub_obj = BasicSubmission.find_polymorphic_subclass(polymorphic_identity=base_dict['submission_type']) env = jinja_template_loading() temp_name = f"{base_dict['submission_type'].replace(' ', '').lower()}_subdocument.docx" @@ -528,8 +529,8 @@ class DocxWriter(object): if subdocument.exists(): main_template = self.create_merged_template(main_template, subdocument) self.template = DocxTemplate(main_template) - base_dict['platemap'] = self.create_plate_map(base_dict['samples'], rows=8, columns=12) - # logger.debug(pformat(base_dict['plate_map'])) + base_dict['platemap'] = [item for item in self.create_plate_map(base_dict['samples'], rows=8, columns=12)] + # logger.debug(pformat(base_dict['platemap'])) try: base_dict['excluded'] += ["platemap"] except KeyError: diff --git a/src/submissions/backend/validators/pydant.py b/src/submissions/backend/validators/pydant.py index 82e29ac..5942616 100644 --- a/src/submissions/backend/validators/pydant.py +++ b/src/submissions/backend/validators/pydant.py @@ -739,11 +739,22 @@ class PydSubmission(BaseModel, extra='allow'): pass else: # logger.debug("Extracting 'value' from attributes") - output = {k: (getattr(self, k) if not isinstance(getattr(self, k), dict) else getattr(self, k)['value']) for - k in fields} - + output = {k: self.filter_field(k) for k in fields} return output + def filter_field(self, key:str): + item = getattr(self, key) + # logger.debug(f"Attempting deconstruction of {key}: {item} with type {type(item)}") + match item: + case dict(): + try: + item = item['value'] + except KeyError: + logger.error(f"Couldn't get dict value: {item}") + case _: + pass + return item + def find_missing(self) -> Tuple[dict, dict]: """ Retrieves info and reagents marked as missing. diff --git a/src/submissions/frontend/widgets/submission_details.py b/src/submissions/frontend/widgets/submission_details.py index 30e2a51..ab15294 100644 --- a/src/submissions/frontend/widgets/submission_details.py +++ b/src/submissions/frontend/widgets/submission_details.py @@ -1,12 +1,13 @@ """ Webview to show submission and sample details. """ -from PyQt6.QtGui import QColor +from PyQt6.QtGui import QColor, QPageSize, QPageLayout +from PyQt6.QtPrintSupport import QPrinter 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 PyQt6.QtCore import Qt, pyqtSlot, QMarginsF from jinja2 import TemplateNotFound from backend.db.models import BasicSubmission, BasicSample, Reagent, KitType @@ -43,7 +44,7 @@ class SubmissionDetails(QDialog): self.layout = QGridLayout() # self.setFixedSize(900, 500) # NOTE: button to export a pdf version - self.btn = QPushButton("Export DOCX") + self.btn = QPushButton("Export PDF") self.btn.setFixedWidth(775) self.btn.clicked.connect(self.export) self.back = QPushButton("Back") @@ -151,7 +152,8 @@ class SubmissionDetails(QDialog): self.base_dict = submission.finalize_details(self.base_dict) # logger.debug(f"Creating barcode.") # logger.debug(f"Making platemap...") - self.base_dict['platemap'] = BasicSubmission.make_plate_map(sample_list=submission.hitpick_plate()) + self.base_dict['platemap'] = submission.make_plate_map(sample_list=submission.hitpick_plate()) + self.base_dict['excluded'] = submission.get_default_info("details_ignore") self.base_dict, self.template = submission.get_details_template(base_dict=self.base_dict) template_path = Path(self.template.environment.loader.__getattribute__("searchpath")[0]) with open(template_path.joinpath("css", "styles.css"), "r") as f: @@ -159,11 +161,10 @@ class SubmissionDetails(QDialog): # logger.debug(f"Submission_details: {pformat(self.base_dict)}") # logger.debug(f"User is power user: {is_power_user()}") self.html = self.template.render(sub=self.base_dict, signing_permission=is_power_user(), css=css) - with open("test.html", "w") as f: - f.write(self.html) + # with open("test.html", "w") as f: + # f.write(self.html) self.webview.setHtml(self.html) - @pyqtSlot(str) def sign_off(self, submission: str | BasicSubmission): # logger.debug(f"Signing off on {submission} - ({getuser()})") @@ -177,18 +178,12 @@ class SubmissionDetails(QDialog): """ Renders submission to html, then creates and saves .pdf file to user selected file. """ - export_plate = BasicSubmission.query(rsl_plate_num=self.export_plate) - base_dict = export_plate.to_dict(full_data=True) - base_dict['excluded'] = export_plate.get_default_info('details_ignore') - logger.debug(f"base dict: {pformat(base_dict)}") - 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}") - + fname = select_save_file(obj=self, default_name=self.export_plate, extension="pdf") + page_layout = QPageLayout() + page_layout.setPageSize(QPageSize(QPageSize.PageSizeId.A4)) + page_layout.setOrientation(QPageLayout.Orientation.Portrait) + page_layout.setMargins(QMarginsF(25, 25, 25, 25)) + self.webview.page().printToPdf(fname.with_suffix(".pdf").__str__(), page_layout) class SubmissionComment(QDialog): """ diff --git a/src/submissions/templates/wastewater_subdocument.docx b/src/submissions/templates/wastewater_subdocument.docx index 0d6d186..17c21c4 100644 Binary files a/src/submissions/templates/wastewater_subdocument.docx and b/src/submissions/templates/wastewater_subdocument.docx differ