Added report tab with HTML and excel export.

This commit is contained in:
lwark
2024-10-04 11:30:22 -05:00
parent c5470b9062
commit c89ec2b62c
12 changed files with 295 additions and 181 deletions

View File

@@ -2,17 +2,20 @@
Contains miscellaneous widgets for frontend functions
'''
from datetime import date
from PyQt6.QtGui import QPageLayout, QPageSize, QStandardItem, QStandardItemModel
from PyQt6.QtWebEngineWidgets import QWebEngineView
from PyQt6.QtWidgets import (
QLabel, QVBoxLayout,
QLineEdit, QComboBox, QDialog,
QDialogButtonBox, QDateEdit, QPushButton, QFormLayout
QLineEdit, QComboBox, QDialog,
QDialogButtonBox, QDateEdit, QPushButton, QFormLayout, QWidget, QHBoxLayout, QSizePolicy
)
from PyQt6.QtCore import Qt, QDate
from PyQt6.QtCore import Qt, QDate, QSize, QMarginsF, pyqtSlot, pyqtSignal, QEvent
from tools import jinja_template_loading
from backend.db.models import *
import logging
from .pop_ups import AlertPop
from .functions import select_open_file
from .functions import select_open_file, select_save_file
logger = logging.getLogger(f"submissions.{__name__}")
@@ -22,8 +25,10 @@ env = jinja_template_loading()
class AddReagentForm(QDialog):
"""
dialog to add gather info about new reagent
"""
def __init__(self, reagent_lot:str|None=None, reagent_role: str | None=None, expiry: date | None=None, reagent_name: str | None=None) -> None:
"""
def __init__(self, reagent_lot: str | None = None, reagent_role: str | None = None, expiry: date | None = None,
reagent_name: str | None = None) -> None:
super().__init__()
if reagent_lot is None:
reagent_lot = reagent_role
@@ -71,7 +76,8 @@ class AddReagentForm(QDialog):
self.layout.addWidget(self.name_input)
self.layout.addWidget(QLabel("Lot:"))
self.layout.addWidget(self.lot_input)
self.layout.addWidget(QLabel("Expiry:\n(use exact date on reagent.\nEOL will be calculated from kit automatically)"))
self.layout.addWidget(
QLabel("Expiry:\n(use exact date on reagent.\nEOL will be calculated from kit automatically)"))
self.layout.addWidget(self.exp_input)
self.layout.addWidget(QLabel("Type:"))
self.layout.addWidget(self.type_input)
@@ -85,57 +91,57 @@ class AddReagentForm(QDialog):
Returns:
dict: Output info
"""
return dict(name=self.name_input.currentText().strip(),
lot=self.lot_input.text().strip(),
"""
return dict(name=self.name_input.currentText().strip(),
lot=self.lot_input.text().strip(),
expiry=self.exp_input.date().toPyDate(),
role=self.type_input.currentText().strip())
def update_names(self):
"""
Updates reagent names form field with examples from reagent type
"""
"""
# logger.debug(self.type_input.currentText())
self.name_input.clear()
lookup = Reagent.query(reagent_role=self.type_input.currentText())
self.name_input.addItems(list(set([item.name for item in lookup])))
class ReportDatePicker(QDialog):
"""
custom dialog to ask for report start/stop dates
"""
def __init__(self) -> None:
super().__init__()
self.setWindowTitle("Select Report Date Range")
# NOTE: make confirm/reject buttons
QBtn = QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
self.buttonBox = QDialogButtonBox(QBtn)
self.buttonBox.accepted.connect(self.accept)
self.buttonBox.rejected.connect(self.reject)
# NOTE: widgets to ask for dates
self.start_date = QDateEdit(calendarPopup=True)
self.start_date.setObjectName("start_date")
self.start_date.setDate(QDate.currentDate())
self.end_date = QDateEdit(calendarPopup=True)
self.end_date.setObjectName("end_date")
self.end_date.setDate(QDate.currentDate())
self.layout = QVBoxLayout()
self.layout.addWidget(QLabel("Start Date"))
self.layout.addWidget(self.start_date)
self.layout.addWidget(QLabel("End Date"))
self.layout.addWidget(self.end_date)
self.layout.addWidget(self.buttonBox)
self.setLayout(self.layout)
def parse_form(self) -> dict:
"""
Converts information in this object to a dict
Returns:
dict: output dict.
"""
return dict(start_date=self.start_date.date().toPyDate(), end_date = self.end_date.date().toPyDate())
# class ReportDatePicker(QDialog):
# """
# custom dialog to ask for report start/stop dates
# """
# def __init__(self) -> None:
# super().__init__()
# self.setWindowTitle("Select Report Date Range")
# # NOTE: make confirm/reject buttons
# QBtn = QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
# self.buttonBox = QDialogButtonBox(QBtn)
# self.buttonBox.accepted.connect(self.accept)
# self.buttonBox.rejected.connect(self.reject)
# # NOTE: widgets to ask for dates
# self.start_date = QDateEdit(calendarPopup=True)
# self.start_date.setObjectName("start_date")
# self.start_date.setDate(QDate.currentDate())
# self.end_date = QDateEdit(calendarPopup=True)
# self.end_date.setObjectName("end_date")
# self.end_date.setDate(QDate.currentDate())
# self.layout = QVBoxLayout()
# self.layout.addWidget(QLabel("Start Date"))
# self.layout.addWidget(self.start_date)
# self.layout.addWidget(QLabel("End Date"))
# self.layout.addWidget(self.end_date)
# self.layout.addWidget(self.buttonBox)
# self.setLayout(self.layout)
#
# def parse_form(self) -> dict:
# """
# Converts information in this object to a dict
#
# Returns:
# dict: output dict.
# """
# return dict(start_date=self.start_date.date().toPyDate(), end_date = self.end_date.date().toPyDate())
class LogParser(QDialog):
@@ -160,13 +166,13 @@ class LogParser(QDialog):
def filelookup(self):
"""
Select file to search
"""
"""
self.fname = select_open_file(self, "tabular")
def runsearch(self):
"""
Gets total/percent occurences of string in tabular file.
"""
"""
count: int = 0
total: int = 0
# logger.debug(f"Current search term: {self.phrase_looker.currentText()}")
@@ -177,7 +183,7 @@ class LogParser(QDialog):
for line in chunk:
if self.phrase_looker.currentText().lower() in line.lower():
count += 1
percent = (count/total)*100
percent = (count / total) * 100
msg = f"I found {count} instances of the search phrase out of {total} = {percent:.2f}%."
status = "Information"
except AttributeError:
@@ -186,3 +192,56 @@ class LogParser(QDialog):
dlg = AlertPop(message=msg, status=status)
dlg.exec()
class StartEndDatePicker(QWidget):
"""
custom widget to pick start and end dates for controls graphs
"""
def __init__(self, default_start: int) -> None:
super().__init__()
self.start_date = QDateEdit(calendarPopup=True)
# NOTE: start date is two months prior to end date by default
default_start = QDate.currentDate().addDays(default_start)
self.start_date.setDate(default_start)
self.end_date = QDateEdit(calendarPopup=True)
self.end_date.setDate(QDate.currentDate())
self.layout = QHBoxLayout()
self.layout.addWidget(QLabel("Start Date"))
self.layout.addWidget(self.start_date)
self.layout.addWidget(QLabel("End Date"))
self.layout.addWidget(self.end_date)
self.setLayout(self.layout)
self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
def sizeHint(self) -> QSize:
return QSize(80, 20)
def save_pdf(obj: QWebEngineView, filename: Path):
page_layout = QPageLayout()
page_layout.setPageSize(QPageSize(QPageSize.PageSizeId.A4))
page_layout.setOrientation(QPageLayout.Orientation.Portrait)
page_layout.setMargins(QMarginsF(25, 25, 25, 25))
obj.page().printToPdf(filename.absolute().__str__(), page_layout)
# subclass
class CheckableComboBox(QComboBox):
# once there is a checkState set, it is rendered
# here we assume default Unchecked
def addItem(self, item, header: bool = False):
super(CheckableComboBox, self).addItem(item)
item: QStandardItem = self.model().item(self.count() - 1, 0)
if not header:
item.setFlags(Qt.ItemFlag.ItemIsUserCheckable | Qt.ItemFlag.ItemIsEnabled)
item.setCheckState(Qt.CheckState.Checked)
def itemChecked(self, index):
item = self.model().item(index, 0)
return item.checkState() == Qt.CheckState.Checked
def changed(self):
logger.debug("emitting updated")
self.updated.emit()