Replaced some list comprehension with generators, javascript in templates to create click event.
This commit is contained in:
@@ -283,6 +283,17 @@ class BasicSubmission(BaseClass):
|
|||||||
del input_dict['id']
|
del input_dict['id']
|
||||||
return input_dict
|
return input_dict
|
||||||
|
|
||||||
|
def generate_associations(self, name:str, extra:str|None=None):
|
||||||
|
try:
|
||||||
|
field = self.__getattribute__(name)
|
||||||
|
except AttributeError:
|
||||||
|
return None
|
||||||
|
for item in field:
|
||||||
|
if extra:
|
||||||
|
yield item.to_sub_dict(extra)
|
||||||
|
else:
|
||||||
|
yield item.to_sub_dict()
|
||||||
|
|
||||||
def to_dict(self, full_data: bool = False, backup: bool = False, report: bool = False) -> dict:
|
def to_dict(self, full_data: bool = False, backup: bool = False, report: bool = False) -> dict:
|
||||||
"""
|
"""
|
||||||
Constructs dictionary used in submissions summary
|
Constructs dictionary used in submissions summary
|
||||||
@@ -332,6 +343,10 @@ class BasicSubmission(BaseClass):
|
|||||||
try:
|
try:
|
||||||
reagents = [item.to_sub_dict(extraction_kit=self.extraction_kit) for item in
|
reagents = [item.to_sub_dict(extraction_kit=self.extraction_kit) for item in
|
||||||
self.submission_reagent_associations]
|
self.submission_reagent_associations]
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"We got an error retrieving reagents: {e}")
|
||||||
|
reagents = []
|
||||||
|
finally:
|
||||||
for k, v in self.extraction_kit.construct_xl_map_for_use(self.submission_type):
|
for k, v in self.extraction_kit.construct_xl_map_for_use(self.submission_type):
|
||||||
if k == 'info':
|
if k == 'info':
|
||||||
continue
|
continue
|
||||||
@@ -341,26 +356,26 @@ class BasicSubmission(BaseClass):
|
|||||||
reagents.append(
|
reagents.append(
|
||||||
dict(role=k, name="Not Applicable", lot="NA", expiry=expiry,
|
dict(role=k, name="Not Applicable", lot="NA", expiry=expiry,
|
||||||
missing=True))
|
missing=True))
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"We got an error retrieving reagents: {e}")
|
|
||||||
reagents = None
|
|
||||||
# logger.debug(f"Running samples.")
|
# logger.debug(f"Running samples.")
|
||||||
samples = self.adjust_to_dict_samples(backup=backup)
|
# samples = self.adjust_to_dict_samples(backup=backup)
|
||||||
|
samples = self.generate_associations(name="submission_sample_associations")
|
||||||
# logger.debug("Running equipment")
|
# logger.debug("Running equipment")
|
||||||
try:
|
equipment = self.generate_associations(name="submission_equipment_associations")
|
||||||
equipment = [item.to_sub_dict() for item in self.submission_equipment_associations]
|
# try:
|
||||||
if not equipment:
|
# equipment = [item.to_sub_dict() for item in self.submission_equipment_associations]
|
||||||
equipment = None
|
# if not equipment:
|
||||||
except Exception as e:
|
# equipment = None
|
||||||
logger.error(f"Error setting equipment: {e}")
|
# except Exception as e:
|
||||||
equipment = None
|
# logger.error(f"Error setting equipment: {e}")
|
||||||
try:
|
# equipment = None
|
||||||
tips = [item.to_sub_dict() for item in self.submission_tips_associations]
|
tips = self.generate_associations(name="submission_tips_associations")
|
||||||
if not tips:
|
# try:
|
||||||
tips = None
|
# tips = [item.to_sub_dict() for item in self.submission_tips_associations]
|
||||||
except Exception as e:
|
# if not tips:
|
||||||
logger.error(f"Error setting tips: {e}")
|
# tips = None
|
||||||
tips = None
|
# except Exception as e:
|
||||||
|
# logger.error(f"Error setting tips: {e}")
|
||||||
|
# tips = None
|
||||||
cost_centre = self.cost_centre
|
cost_centre = self.cost_centre
|
||||||
custom = self.custom
|
custom = self.custom
|
||||||
else:
|
else:
|
||||||
@@ -1013,18 +1028,18 @@ class BasicSubmission(BaseClass):
|
|||||||
logger.info(f"Hello from {cls.__mapper_args__['polymorphic_identity']} sampler")
|
logger.info(f"Hello from {cls.__mapper_args__['polymorphic_identity']} sampler")
|
||||||
return samples
|
return samples
|
||||||
|
|
||||||
def adjust_to_dict_samples(self, backup: bool = False) -> List[dict]:
|
# def adjust_to_dict_samples(self, backup: bool = False) -> List[dict]:
|
||||||
"""
|
# """
|
||||||
Updates sample dictionaries with custom values
|
# Updates sample dictionaries with custom values
|
||||||
|
#
|
||||||
Args:
|
# Args:
|
||||||
backup (bool, optional): Whether to perform backup. Defaults to False.
|
# backup (bool, optional): Whether to perform backup. Defaults to False.
|
||||||
|
#
|
||||||
Returns:
|
# Returns:
|
||||||
List[dict]: Updated dictionaries
|
# List[dict]: Updated dictionaries
|
||||||
"""
|
# """
|
||||||
# logger.debug(f"Hello from {self.__class__.__name__} dictionary sample adjuster.")
|
# # logger.debug(f"Hello from {self.__class__.__name__} dictionary sample adjuster.")
|
||||||
return [item.to_sub_dict() for item in self.submission_sample_associations]
|
# return [item.to_sub_dict() for item in self.submission_sample_associations]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_details_template(cls, base_dict: dict) -> Tuple[dict, Template]:
|
def get_details_template(cls, base_dict: dict) -> Tuple[dict, Template]:
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ class SheetParser(object):
|
|||||||
self.parse_samples()
|
self.parse_samples()
|
||||||
self.parse_equipment()
|
self.parse_equipment()
|
||||||
self.parse_tips()
|
self.parse_tips()
|
||||||
# self.finalize_parse()
|
|
||||||
# logger.debug(f"Parser.sub after info scrape: {pformat(self.sub)}")
|
# logger.debug(f"Parser.sub after info scrape: {pformat(self.sub)}")
|
||||||
|
|
||||||
def parse_info(self):
|
def parse_info(self):
|
||||||
@@ -63,6 +62,8 @@ class SheetParser(object):
|
|||||||
parser = InfoParser(xl=self.xl, submission_type=self.submission_type, sub_object=self.sub_object)
|
parser = InfoParser(xl=self.xl, submission_type=self.submission_type, sub_object=self.sub_object)
|
||||||
info = parser.parse_info()
|
info = parser.parse_info()
|
||||||
self.info_map = parser.map
|
self.info_map = parser.map
|
||||||
|
# NOTE: in order to accommodate generic submission types we have to check for the type in the excel sheet and
|
||||||
|
# rerun accordingly
|
||||||
try:
|
try:
|
||||||
check = info['submission_type']['value'] not in [None, "None", "", " "]
|
check = info['submission_type']['value'] not in [None, "None", "", " "]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@@ -78,13 +79,15 @@ class SheetParser(object):
|
|||||||
else:
|
else:
|
||||||
self.submission_type = RSLNamer.retrieve_submission_type(filename=self.filepath)
|
self.submission_type = RSLNamer.retrieve_submission_type(filename=self.filepath)
|
||||||
self.parse_info()
|
self.parse_info()
|
||||||
for k, v in info.items():
|
[self.sub.__setitem__(k, v) for k, v in info.items()]
|
||||||
match k:
|
# for k, v in info.items():
|
||||||
# NOTE: exclude samples.
|
# match k:
|
||||||
case "sample":
|
# # NOTE: exclude samples.
|
||||||
continue
|
# case "sample":
|
||||||
case _:
|
# logger.debug(f"Sample found: {k}: {v}")
|
||||||
self.sub[k] = v
|
# continue
|
||||||
|
# case _:
|
||||||
|
# self.sub[k] = v
|
||||||
|
|
||||||
def parse_reagents(self, extraction_kit: str | None = None):
|
def parse_reagents(self, extraction_kit: str | None = None):
|
||||||
"""
|
"""
|
||||||
@@ -105,7 +108,7 @@ class SheetParser(object):
|
|||||||
Calls sample parser to pull info from the excel sheet
|
Calls sample parser to pull info from the excel sheet
|
||||||
"""
|
"""
|
||||||
parser = SampleParser(xl=self.xl, submission_type=self.submission_type)
|
parser = SampleParser(xl=self.xl, submission_type=self.submission_type)
|
||||||
self.sub['samples'] = parser.reconcile_samples()
|
self.sub['samples'] = parser.parse_samples()
|
||||||
|
|
||||||
def parse_equipment(self):
|
def parse_equipment(self):
|
||||||
"""
|
"""
|
||||||
@@ -145,29 +148,29 @@ class SheetParser(object):
|
|||||||
PydSubmission: output pydantic model
|
PydSubmission: output pydantic model
|
||||||
"""
|
"""
|
||||||
# logger.debug(f"Submission dictionary coming into 'to_pydantic':\n{pformat(self.sub)}")
|
# logger.debug(f"Submission dictionary coming into 'to_pydantic':\n{pformat(self.sub)}")
|
||||||
pyd_dict = copy(self.sub)
|
# pyd_dict = copy(self.sub)
|
||||||
pyd_dict['samples'] = [PydSample(**sample) for sample in self.sub['samples']]
|
# self.sub['samples'] = [PydSample(**sample) for sample in self.sub['samples']]
|
||||||
# logger.debug(f"Reagents: {pformat(self.sub['reagents'])}")
|
# logger.debug(f"Reagents: {pformat(self.sub['reagents'])}")
|
||||||
pyd_dict['reagents'] = [PydReagent(**reagent) for reagent in self.sub['reagents']]
|
# self.sub['reagents'] = [PydReagent(**reagent) for reagent in self.sub['reagents']]
|
||||||
# logger.debug(f"Equipment: {self.sub['equipment']}")
|
# logger.debug(f"Equipment: {self.sub['equipment']}")
|
||||||
try:
|
# try:
|
||||||
check = bool(self.sub['equipment'])
|
# check = bool(self.sub['equipment'])
|
||||||
except TypeError:
|
# except TypeError:
|
||||||
check = False
|
# check = False
|
||||||
if check:
|
# if check:
|
||||||
pyd_dict['equipment'] = [PydEquipment(**equipment) for equipment in self.sub['equipment']]
|
# self.sub['equipment'] = [PydEquipment(**equipment) for equipment in self.sub['equipment']]
|
||||||
else:
|
# else:
|
||||||
pyd_dict['equipment'] = None
|
# self.sub['equipment'] = None
|
||||||
try:
|
# try:
|
||||||
check = bool(self.sub['tips'])
|
# check = bool(self.sub['tips'])
|
||||||
except TypeError:
|
# except TypeError:
|
||||||
check = False
|
# check = False
|
||||||
if check:
|
# if check:
|
||||||
pyd_dict['tips'] = [PydTips(**tips) for tips in self.sub['tips']]
|
# self.sub['tips'] = [PydTips(**tips) for tips in self.sub['tips']]
|
||||||
else:
|
# else:
|
||||||
pyd_dict['tips'] = None
|
# self.sub['tips'] = None
|
||||||
psm = PydSubmission(filepath=self.filepath, run_custom=True, **pyd_dict)
|
return PydSubmission(filepath=self.filepath, run_custom=True, **self.sub)
|
||||||
return psm
|
# return psm
|
||||||
|
|
||||||
|
|
||||||
class InfoParser(object):
|
class InfoParser(object):
|
||||||
@@ -287,7 +290,7 @@ class ReagentParser(object):
|
|||||||
extraction_kit (str): Extraction kit used.
|
extraction_kit (str): Extraction kit used.
|
||||||
sub_object (BasicSubmission | None, optional): Submission object holding methods. Defaults to None.
|
sub_object (BasicSubmission | None, optional): Submission object holding methods. Defaults to None.
|
||||||
"""
|
"""
|
||||||
# logger.debug("\n\nHello from ReagentParser!\n\n")
|
logger.debug("\n\nHello from ReagentParser!\n\n")
|
||||||
if isinstance(submission_type, str):
|
if isinstance(submission_type, str):
|
||||||
submission_type = SubmissionType.query(name=submission_type)
|
submission_type = SubmissionType.query(name=submission_type)
|
||||||
self.submission_type_obj = submission_type
|
self.submission_type_obj = submission_type
|
||||||
@@ -382,7 +385,7 @@ class SampleParser(object):
|
|||||||
sample_map (dict | None, optional): Locations in database where samples are found. Defaults to None.
|
sample_map (dict | None, optional): Locations in database where samples are found. Defaults to None.
|
||||||
sub_object (BasicSubmission | None, optional): Submission object holding methods. Defaults to None.
|
sub_object (BasicSubmission | None, optional): Submission object holding methods. Defaults to None.
|
||||||
"""
|
"""
|
||||||
# logger.debug("\n\nHello from SampleParser!\n\n")
|
logger.debug("\n\nHello from SampleParser!\n\n")
|
||||||
self.samples = []
|
self.samples = []
|
||||||
self.xl = xl
|
self.xl = xl
|
||||||
if isinstance(submission_type, str):
|
if isinstance(submission_type, str):
|
||||||
@@ -477,49 +480,50 @@ class SampleParser(object):
|
|||||||
lookup_samples.append(self.samp_object.parse_sample(row_dict))
|
lookup_samples.append(self.samp_object.parse_sample(row_dict))
|
||||||
return lookup_samples
|
return lookup_samples
|
||||||
|
|
||||||
def parse_samples(self) -> Tuple[Report | None, List[dict] | List[PydSample]]:
|
# def parse_samples(self) -> Tuple[Report | None, List[dict] | List[PydSample]]:
|
||||||
"""
|
# """
|
||||||
Parse merged platemap/lookup info into dicts/samples
|
# Parse merged platemap/lookup info into dicts/samples
|
||||||
|
#
|
||||||
|
# Returns:
|
||||||
|
# List[dict]|List[models.BasicSample]: List of samples
|
||||||
|
# """
|
||||||
|
# result = None
|
||||||
|
# new_samples = []
|
||||||
|
# # logger.debug(f"Starting samples: {pformat(self.samples)}")
|
||||||
|
# for sample in self.samples:
|
||||||
|
# translated_dict = {}
|
||||||
|
# for k, v in sample.items():
|
||||||
|
# match v:
|
||||||
|
# case dict():
|
||||||
|
# v = None
|
||||||
|
# case float():
|
||||||
|
# v = convert_nans_to_nones(v)
|
||||||
|
# case _:
|
||||||
|
# v = v
|
||||||
|
# translated_dict[k] = convert_nans_to_nones(v)
|
||||||
|
# translated_dict['sample_type'] = f"{self.submission_type} Sample"
|
||||||
|
# translated_dict = self.sub_object.parse_samples(translated_dict)
|
||||||
|
# translated_dict = self.samp_object.parse_sample(translated_dict)
|
||||||
|
# # logger.debug(f"Here is the output of the custom parser:\n{translated_dict}")
|
||||||
|
# new_samples.append(PydSample(**translated_dict))
|
||||||
|
# return result, new_samples
|
||||||
|
|
||||||
Returns:
|
def parse_samples(self) -> Generator[dict, None, None]:
|
||||||
List[dict]|List[models.BasicSample]: List of samples
|
|
||||||
"""
|
|
||||||
result = None
|
|
||||||
new_samples = []
|
|
||||||
# logger.debug(f"Starting samples: {pformat(self.samples)}")
|
|
||||||
for sample in self.samples:
|
|
||||||
translated_dict = {}
|
|
||||||
for k, v in sample.items():
|
|
||||||
match v:
|
|
||||||
case dict():
|
|
||||||
v = None
|
|
||||||
case float():
|
|
||||||
v = convert_nans_to_nones(v)
|
|
||||||
case _:
|
|
||||||
v = v
|
|
||||||
translated_dict[k] = convert_nans_to_nones(v)
|
|
||||||
translated_dict['sample_type'] = f"{self.submission_type} Sample"
|
|
||||||
translated_dict = self.sub_object.parse_samples(translated_dict)
|
|
||||||
translated_dict = self.samp_object.parse_sample(translated_dict)
|
|
||||||
# logger.debug(f"Here is the output of the custom parser:\n{translated_dict}")
|
|
||||||
new_samples.append(PydSample(**translated_dict))
|
|
||||||
return result, new_samples
|
|
||||||
|
|
||||||
def reconcile_samples(self) -> Generator[dict, None, None]:
|
|
||||||
"""
|
"""
|
||||||
Merges sample info from lookup table and plate map.
|
Merges sample info from lookup table and plate map.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List[dict]: Reconciled samples
|
List[dict]: Reconciled samples
|
||||||
"""
|
"""
|
||||||
if self.plate_map_samples is None or self.lookup_samples is None:
|
if not self.plate_map_samples or not self.lookup_samples:
|
||||||
|
logger.error(f"No separate samples, returning")
|
||||||
self.samples = self.lookup_samples or self.plate_map_samples
|
self.samples = self.lookup_samples or self.plate_map_samples
|
||||||
return
|
return
|
||||||
merge_on_id = self.sample_info_map['lookup_table']['merge_on_id']
|
merge_on_id = self.sample_info_map['lookup_table']['merge_on_id']
|
||||||
plate_map_samples = sorted(copy(self.plate_map_samples), key=lambda d: d['id'])
|
plate_map_samples = sorted(copy(self.plate_map_samples), key=lambda d: d['id'])
|
||||||
lookup_samples = sorted(copy(self.lookup_samples), key=lambda d: d[merge_on_id])
|
lookup_samples = sorted(copy(self.lookup_samples), key=lambda d: d[merge_on_id])
|
||||||
print(pformat(plate_map_samples))
|
# print(pformat(plate_map_samples))
|
||||||
print(pformat(lookup_samples))
|
# print(pformat(lookup_samples))
|
||||||
for ii, psample in enumerate(plate_map_samples):
|
for ii, psample in enumerate(plate_map_samples):
|
||||||
try:
|
try:
|
||||||
check = psample['id'] == lookup_samples[ii][merge_on_id]
|
check = psample['id'] == lookup_samples[ii][merge_on_id]
|
||||||
@@ -563,6 +567,7 @@ class EquipmentParser(object):
|
|||||||
xl (Workbook): Openpyxl workbook from submitted excel file.
|
xl (Workbook): Openpyxl workbook from submitted excel file.
|
||||||
submission_type (str | SubmissionType): Type of submission expected (Wastewater, Bacterial Culture, etc.)
|
submission_type (str | SubmissionType): Type of submission expected (Wastewater, Bacterial Culture, etc.)
|
||||||
"""
|
"""
|
||||||
|
logger.debug("\n\nHello from EquipmentParser!\n\n")
|
||||||
if isinstance(submission_type, str):
|
if isinstance(submission_type, str):
|
||||||
submission_type = SubmissionType.query(name=submission_type)
|
submission_type = SubmissionType.query(name=submission_type)
|
||||||
self.submission_type = submission_type
|
self.submission_type = submission_type
|
||||||
@@ -649,6 +654,7 @@ class TipParser(object):
|
|||||||
xl (Workbook): Openpyxl workbook from submitted excel file.
|
xl (Workbook): Openpyxl workbook from submitted excel file.
|
||||||
submission_type (str | SubmissionType): Type of submission expected (Wastewater, Bacterial Culture, etc.)
|
submission_type (str | SubmissionType): Type of submission expected (Wastewater, Bacterial Culture, etc.)
|
||||||
"""
|
"""
|
||||||
|
logger.debug("\n\nHello from TipParser!\n\n")
|
||||||
if isinstance(submission_type, str):
|
if isinstance(submission_type, str):
|
||||||
submission_type = SubmissionType.query(name=submission_type)
|
submission_type = SubmissionType.query(name=submission_type)
|
||||||
self.submission_type = submission_type
|
self.submission_type = submission_type
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from datetime import date, datetime, timedelta
|
|||||||
from dateutil.parser import parse
|
from dateutil.parser import parse
|
||||||
from dateutil.parser import ParserError
|
from dateutil.parser import ParserError
|
||||||
from typing import List, Tuple, Literal
|
from typing import List, Tuple, Literal
|
||||||
|
from types import GeneratorType
|
||||||
from . import RSLNamer
|
from . import RSLNamer
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from tools import check_not_nan, convert_nans_to_nones, Report, Result
|
from tools import check_not_nan, convert_nans_to_nones, Report, Result
|
||||||
@@ -395,16 +396,32 @@ class PydSubmission(BaseModel, extra='allow'):
|
|||||||
submission_category: dict | None = Field(default=dict(value=None, missing=True), validate_default=True)
|
submission_category: dict | None = Field(default=dict(value=None, missing=True), validate_default=True)
|
||||||
comment: dict | None = Field(default=dict(value="", missing=True), validate_default=True)
|
comment: dict | None = Field(default=dict(value="", missing=True), validate_default=True)
|
||||||
reagents: List[dict] | List[PydReagent] = []
|
reagents: List[dict] | List[PydReagent] = []
|
||||||
samples: List[PydSample]
|
samples: List[PydSample] | Generator
|
||||||
equipment: List[PydEquipment] | None = []
|
equipment: List[PydEquipment] | None = []
|
||||||
cost_centre: dict | None = Field(default=dict(value=None, missing=True), validate_default=True)
|
cost_centre: dict | None = Field(default=dict(value=None, missing=True), validate_default=True)
|
||||||
contact: dict | None = Field(default=dict(value=None, missing=True), validate_default=True)
|
contact: dict | None = Field(default=dict(value=None, missing=True), validate_default=True)
|
||||||
|
tips: List[PydTips] | None =[]
|
||||||
|
|
||||||
|
@field_validator("tips", mode="before")
|
||||||
|
@classmethod
|
||||||
|
def expand_tips(cls, value):
|
||||||
|
# print(f"\n{type(value)}\n")
|
||||||
|
if isinstance(value, dict):
|
||||||
|
value = value['value']
|
||||||
|
if isinstance(value, Generator):
|
||||||
|
logger.debug("We have a generator")
|
||||||
|
return [PydTips(**tips) for tips in value]
|
||||||
|
if not value:
|
||||||
|
return []
|
||||||
|
return value
|
||||||
|
|
||||||
@field_validator('equipment', mode='before')
|
@field_validator('equipment', mode='before')
|
||||||
@classmethod
|
@classmethod
|
||||||
def convert_equipment_dict(cls, value):
|
def convert_equipment_dict(cls, value):
|
||||||
# logger.debug(f"Equipment: {value}")
|
# logger.debug(f"Equipment: {value}")
|
||||||
|
if isinstance(value, Generator):
|
||||||
|
logger.debug("We have a generator")
|
||||||
|
return [PydEquipment(**equipment) for equipment in value]
|
||||||
if isinstance(value, dict):
|
if isinstance(value, dict):
|
||||||
return value['value']
|
return value['value']
|
||||||
return value
|
return value
|
||||||
@@ -580,6 +597,24 @@ class PydSubmission(BaseModel, extra='allow'):
|
|||||||
value['value'] = values.data['submission_type']['value']
|
value['value'] = values.data['submission_type']['value']
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
@field_validator("reagents", mode="before")
|
||||||
|
@classmethod
|
||||||
|
def expand_reagents(cls, value):
|
||||||
|
# print(f"\n{type(value)}\n")
|
||||||
|
if isinstance(value, Generator):
|
||||||
|
logger.debug("We have a generator")
|
||||||
|
return [PydReagent(**reagent) for reagent in value]
|
||||||
|
return value
|
||||||
|
|
||||||
|
@field_validator("samples", mode="before")
|
||||||
|
@classmethod
|
||||||
|
def expand_samples(cls, value):
|
||||||
|
# print(f"\n{type(value)}\n")
|
||||||
|
if isinstance(value, Generator):
|
||||||
|
logger.debug("We have a generator")
|
||||||
|
return [PydSample(**sample) for sample in value]
|
||||||
|
return value
|
||||||
|
|
||||||
@field_validator("samples")
|
@field_validator("samples")
|
||||||
@classmethod
|
@classmethod
|
||||||
def assign_ids(cls, value):
|
def assign_ids(cls, value):
|
||||||
|
|||||||
@@ -93,15 +93,16 @@ class SubmissionDetails(QDialog):
|
|||||||
Args:
|
Args:
|
||||||
sample (str): Submitter Id of the sample.
|
sample (str): Submitter Id of the sample.
|
||||||
"""
|
"""
|
||||||
|
logger.debug(f"Details: {sample}")
|
||||||
if isinstance(sample, str):
|
if isinstance(sample, str):
|
||||||
sample = BasicSample.query(submitter_id=sample)
|
sample = BasicSample.query(submitter_id=sample)
|
||||||
base_dict = sample.to_sub_dict(full_data=True)
|
base_dict = sample.to_sub_dict(full_data=True)
|
||||||
exclude = ['submissions', 'excluded', 'colour', 'tooltip']
|
exclude = ['submissions', 'excluded', 'colour', 'tooltip']
|
||||||
try:
|
# try:
|
||||||
base_dict['excluded'] += exclude
|
# base_dict['excluded'] += exclude
|
||||||
except KeyError:
|
# except KeyError:
|
||||||
base_dict['excluded'] = exclude
|
base_dict['excluded'] = exclude
|
||||||
template = sample.get_details_template(base_dict=base_dict)
|
template = sample.get_details_template()
|
||||||
template_path = Path(self.template.environment.loader.__getattribute__("searchpath")[0])
|
template_path = Path(self.template.environment.loader.__getattribute__("searchpath")[0])
|
||||||
with open(template_path.joinpath("css", "styles.css"), "r") as f:
|
with open(template_path.joinpath("css", "styles.css"), "r") as f:
|
||||||
css = f.read()
|
css = f.read()
|
||||||
@@ -158,6 +159,8 @@ class SubmissionDetails(QDialog):
|
|||||||
# logger.debug(f"Submission_details: {pformat(self.base_dict)}")
|
# logger.debug(f"Submission_details: {pformat(self.base_dict)}")
|
||||||
# logger.debug(f"User is power user: {is_power_user()}")
|
# 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)
|
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)
|
||||||
self.webview.setHtml(self.html)
|
self.webview.setHtml(self.html)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
<h3><u>Reagents:</u></h3>
|
<h3><u>Reagents:</u></h3>
|
||||||
<p>{% for item in sub['reagents'] %}
|
<p>{% for item in sub['reagents'] %}
|
||||||
<b>{{ item['role'] }}</b>: <a class="data-link" id="{{ item['lot'] }}">{{ item['lot'] }} (EXP: {{ item['expiry'] }})</a><br>
|
<b>{{ item['role'] }}</b>: <a class="data-link reagent" id="{{ item['lot'] }}">{{ item['lot'] }} (EXP: {{ item['expiry'] }})</a><br>
|
||||||
{% endfor %}</p>
|
{% endfor %}</p>
|
||||||
|
|
||||||
{% if sub['equipment'] %}
|
{% if sub['equipment'] %}
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
{% if sub['samples'] %}
|
{% if sub['samples'] %}
|
||||||
<h3><u>Samples:</u></h3>
|
<h3><u>Samples:</u></h3>
|
||||||
<p>{% for item in sub['samples'] %}
|
<p>{% for item in sub['samples'] %}
|
||||||
<b>{{ item['well'] }}:</b><a class="data-link" id="{{ item['submitter_id'] }}_alpha">{% if item['organism'] %} {{ item['name'] }} - ({{ item['organism']|replace('\n\t', '<br> ') }}){% else %} {{ item['name']|replace('\n\t', '<br> ') }}{% endif %}</a><br>
|
<b>{{ item['well'] }}:</b><a class="data-link sample" id="{{ item['submitter_id'] }}">{% if item['organism'] %} {{ item['name'] }} - ({{ item['organism']|replace('\n\t', '<br> ') }}){% else %} {{ item['name']|replace('\n\t', '<br> ') }}{% endif %}</a><br>
|
||||||
{% endfor %}</p>
|
{% endfor %}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
@@ -83,22 +83,25 @@
|
|||||||
<script>
|
<script>
|
||||||
{% block script %}
|
{% block script %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
{% for sample in sub['samples'] %}
|
|
||||||
document.getElementById("{{ sample['submitter_id'] }}").addEventListener("click", function(){
|
|
||||||
backend.sample_details("{{ sample['submitter_id'] }}");
|
|
||||||
});
|
|
||||||
document.getElementById("{{ sample['submitter_id'] }}_alpha").addEventListener("click", function(){
|
|
||||||
backend.sample_details("{{ sample['submitter_id'] }}");
|
|
||||||
});
|
|
||||||
{% endfor %}
|
|
||||||
{% for reagent in sub['reagents'] %}
|
|
||||||
document.getElementById("{{ reagent['lot'] }}").addEventListener("click", function(){
|
|
||||||
backend.reagent_details("{{ reagent['lot'] }}", "{{ sub['extraction_kit'] }}");
|
|
||||||
});
|
|
||||||
{% endfor %}
|
|
||||||
document.getElementById("sign_btn").addEventListener("click", function(){
|
document.getElementById("sign_btn").addEventListener("click", function(){
|
||||||
backend.sign_off("{{ sub['plate_number'] }}");
|
backend.sign_off("{{ sub['plate_number'] }}");
|
||||||
});
|
});
|
||||||
|
var sampleSelection = document.getElementsByClassName('sample');
|
||||||
|
|
||||||
|
for(let i = 0; i < sampleSelection.length; i++) {
|
||||||
|
sampleSelection[i].addEventListener("click", function() {
|
||||||
|
backend.sample_details(sampleSelection[i].id);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var reagentSelection = document.getElementsByClassName('reagent');
|
||||||
|
|
||||||
|
for(let i = 0; i < reagentSelection.length; i++) {
|
||||||
|
reagentSelection[i].addEventListener("click", function() {
|
||||||
|
backend.reagent_details(reagentSelection[i].id, "{{ sub['extraction_kit'] }}");
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<div class="gallery" style="display: grid;grid-template-columns: repeat({{ PLATE_COLUMNS }}, 7.5vw);grid-template-rows: repeat({{ PLATE_ROWS }}, 7.5vw);grid-gap: 2px;">
|
<div class="gallery" style="display: grid;grid-template-columns: repeat({{ PLATE_COLUMNS }}, 7.5vw);grid-template-rows: repeat({{ PLATE_ROWS }}, 7.5vw);grid-gap: 2px;">
|
||||||
{% for sample in samples %}
|
{% for sample in samples %}
|
||||||
<div class="well data-link" id="{{sample['submitter_id']}}" style="background-color: {{sample['background_color']}};
|
<div class="well data-link sample" id="{{sample['submitter_id']}}" style="background-color: {{sample['background_color']}};
|
||||||
border: 1px solid #000;
|
border: 1px solid #000;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
grid-column-start: {{sample['column']}};
|
grid-column-start: {{sample['column']}};
|
||||||
|
|||||||
Reference in New Issue
Block a user