Update of Reagent usage ui for addition of new reagents.
This commit is contained in:
@@ -603,7 +603,7 @@ class BaseClass(Base):
|
|||||||
pyd = getattr(pydant, pyd_model_name)
|
pyd = getattr(pydant, pyd_model_name)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise AttributeError(f"Could not get pydantic class {pyd_model_name}")
|
raise AttributeError(f"Could not get pydantic class {pyd_model_name}")
|
||||||
return pyd(**self.details_dict())
|
return pyd(**self.details_dict(**kwargs))
|
||||||
|
|
||||||
def show_details(self, obj):
|
def show_details(self, obj):
|
||||||
logger.debug("Show Details")
|
logger.debug("Show Details")
|
||||||
|
|||||||
@@ -5,13 +5,11 @@ from __future__ import annotations
|
|||||||
import zipfile, logging, re
|
import zipfile, logging, re
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
from pprint import pformat
|
from pprint import pformat
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from sqlalchemy import Column, String, TIMESTAMP, JSON, INTEGER, ForeignKey, Interval, Table, FLOAT, BLOB
|
from sqlalchemy import Column, String, TIMESTAMP, JSON, INTEGER, ForeignKey, Interval, Table, FLOAT, BLOB
|
||||||
from sqlalchemy.orm import relationship, validates, Query
|
from sqlalchemy.orm import relationship, validates, Query
|
||||||
from sqlalchemy.ext.associationproxy import association_proxy
|
from sqlalchemy.ext.associationproxy import association_proxy
|
||||||
from datetime import date, datetime, timedelta
|
from datetime import date, datetime, timedelta
|
||||||
|
|
||||||
from tools import check_authorization, setup_lookup, Report, Result, check_regex_match, timezone, \
|
from tools import check_authorization, setup_lookup, Report, Result, check_regex_match, timezone, \
|
||||||
jinja_template_loading, flatten_list
|
jinja_template_loading, flatten_list
|
||||||
from typing import List, Literal, Generator, Any, Tuple, TYPE_CHECKING
|
from typing import List, Literal, Generator, Any, Tuple, TYPE_CHECKING
|
||||||
@@ -562,7 +560,8 @@ class ReagentRole(BaseClass):
|
|||||||
|
|
||||||
def get_reagents(self, kittype: str | KitType | None = None):
|
def get_reagents(self, kittype: str | KitType | None = None):
|
||||||
if not kittype:
|
if not kittype:
|
||||||
return [f"{reagent.name} - {reagent.lot}" for reagent in self.reagent]
|
# return [f"{reagent.name} - {reagent.lot} - {reagent.expiry}" for reagent in self.reagent]
|
||||||
|
return [reagent.to_pydantic() for reagent in self.reagent]
|
||||||
if isinstance(kittype, str):
|
if isinstance(kittype, str):
|
||||||
kittype = KitType.query(name=kittype)
|
kittype = KitType.query(name=kittype)
|
||||||
assoc = next((item for item in self.reagentrolekittypeassociation if item.kittype == kittype), None)
|
assoc = next((item for item in self.reagentrolekittypeassociation if item.kittype == kittype), None)
|
||||||
@@ -571,7 +570,8 @@ class ReagentRole(BaseClass):
|
|||||||
last_used = Reagent.query(name=assoc.last_used)
|
last_used = Reagent.query(name=assoc.last_used)
|
||||||
if last_used:
|
if last_used:
|
||||||
reagents.insert(0, reagents.pop(reagents.index(last_used)))
|
reagents.insert(0, reagents.pop(reagents.index(last_used)))
|
||||||
return [f"{reagent.name} - {reagent.lot}" for reagent in reagents]
|
# return [f"{reagent.name} - {reagent.lot} - {reagent.expiry}" for reagent in reagents]
|
||||||
|
return [reagent.to_pydantic(reagentrole=self.name) for reagent in reagents]
|
||||||
|
|
||||||
|
|
||||||
class Reagent(BaseClass, LogMixin):
|
class Reagent(BaseClass, LogMixin):
|
||||||
@@ -680,24 +680,24 @@ class Reagent(BaseClass, LogMixin):
|
|||||||
report.add_result(Result(msg=f"Updating last used {rt} was not performed.", status="Information"))
|
report.add_result(Result(msg=f"Updating last used {rt} was not performed.", status="Information"))
|
||||||
return report
|
return report
|
||||||
|
|
||||||
@classmethod
|
# @classmethod
|
||||||
def query_or_create(cls, **kwargs) -> Reagent:
|
# def query_or_create(cls, **kwargs) -> Reagent:
|
||||||
from backend.validators.pydant import PydReagent
|
# from backend.validators.pydant import PydReagent
|
||||||
new = False
|
# new = False
|
||||||
disallowed = ['expiry']
|
# disallowed = ['expiry']
|
||||||
sanitized_kwargs = {k: v for k, v in kwargs.items() if k not in disallowed}
|
# sanitized_kwargs = {k: v for k, v in kwargs.items() if k not in disallowed}
|
||||||
instance = cls.query(**sanitized_kwargs)
|
# instance = cls.query(**sanitized_kwargs)
|
||||||
if not instance or isinstance(instance, list):
|
# if not instance or isinstance(instance, list):
|
||||||
if "reagentrole" not in kwargs:
|
# if "reagentrole" not in kwargs:
|
||||||
try:
|
# try:
|
||||||
kwargs['reagentrole'] = kwargs['name']
|
# kwargs['reagentrole'] = kwargs['name']
|
||||||
except KeyError:
|
# except KeyError:
|
||||||
pass
|
# pass
|
||||||
instance = PydReagent(**kwargs)
|
# instance = PydReagent(**kwargs)
|
||||||
new = True
|
# new = True
|
||||||
instance = instance.to_sql()
|
# instance = instance.to_sql()
|
||||||
logger.info(f"Instance from query or create: {instance}")
|
# logger.info(f"Instance from query or create: {instance}")
|
||||||
return instance, new
|
# return instance, new
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@setup_lookup
|
@setup_lookup
|
||||||
@@ -800,6 +800,12 @@ class Reagent(BaseClass, LogMixin):
|
|||||||
expiry="Use exact date on reagent.\nEOL will be calculated from kittype automatically"
|
expiry="Use exact date on reagent.\nEOL will be calculated from kittype automatically"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def details_dict(self, reagentrole:str|None=None, **kwargs):
|
||||||
|
output = super().details_dict()
|
||||||
|
if reagentrole:
|
||||||
|
output['reagentrole'] = reagentrole
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
class Discount(BaseClass):
|
class Discount(BaseClass):
|
||||||
"""
|
"""
|
||||||
@@ -1278,7 +1284,7 @@ class ProcedureType(BaseClass):
|
|||||||
if self.plate_rows == 0 or self.plate_columns == 0:
|
if self.plate_rows == 0 or self.plate_columns == 0:
|
||||||
return "<br/>"
|
return "<br/>"
|
||||||
sample_dicts = self.pad_sample_dicts(sample_dicts=sample_dicts)
|
sample_dicts = self.pad_sample_dicts(sample_dicts=sample_dicts)
|
||||||
logger.debug(f"Sample dicts: {pformat(sample_dicts)}")
|
# logger.debug(f"Sample dicts: {pformat(sample_dicts)}")
|
||||||
vw = round((-0.07 * len(sample_dicts)) + 12.2, 1)
|
vw = round((-0.07 * len(sample_dicts)) + 12.2, 1)
|
||||||
# NOTE: An overly complicated list comprehension create a list of sample locations
|
# NOTE: An overly complicated list comprehension create a list of sample locations
|
||||||
# NOTE: next will return a blank cell if no value found for row/column
|
# NOTE: next will return a blank cell if no value found for row/column
|
||||||
@@ -1291,14 +1297,14 @@ class ProcedureType(BaseClass):
|
|||||||
def pad_sample_dicts(self, sample_dicts: List["PydSample"]):
|
def pad_sample_dicts(self, sample_dicts: List["PydSample"]):
|
||||||
from backend.validators.pydant import PydSample
|
from backend.validators.pydant import PydSample
|
||||||
output = []
|
output = []
|
||||||
logger.debug(f"Rows: {self.plate_rows}")
|
# logger.debug(f"Rows: {self.plate_rows}")
|
||||||
logger.debug(f"Columns: {self.plate_columns}")
|
# logger.debug(f"Columns: {self.plate_columns}")
|
||||||
for row, column in self.ranked_plate.values():
|
for row, column in self.ranked_plate.values():
|
||||||
sample = next((sample for sample in sample_dicts if sample.row == row and sample.column == column),
|
sample = next((sample for sample in sample_dicts if sample.row == row and sample.column == column),
|
||||||
PydSample(**dict(sample_id="", row=row, column=column, enabled=False)))
|
PydSample(**dict(sample_id="", row=row, column=column, enabled=False)))
|
||||||
sample.background_color = "#6ffe1d" if sample.enabled else "#ffffff"
|
sample.background_color = "#6ffe1d" if sample.enabled else "#ffffff"
|
||||||
output.append(sample)
|
output.append(sample)
|
||||||
logger.debug(f"Appending {sample} at row {row}, column {column}")
|
# logger.debug(f"Appending {sample} at row {row}, column {column}")
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
||||||
@@ -1453,6 +1459,8 @@ class Procedure(BaseClass):
|
|||||||
dlg = ProcedureCreation(parent=obj, procedure=self.to_pydantic(), edit=True)
|
dlg = ProcedureCreation(parent=obj, procedure=self.to_pydantic(), edit=True)
|
||||||
if dlg.exec():
|
if dlg.exec():
|
||||||
logger.debug("Edited")
|
logger.debug("Edited")
|
||||||
|
sql, _ = dlg.return_sql()
|
||||||
|
sql.save()
|
||||||
|
|
||||||
def add_comment(self, obj):
|
def add_comment(self, obj):
|
||||||
logger.debug("Add Comment!")
|
logger.debug("Add Comment!")
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ class PydReagent(PydBaseClass):
|
|||||||
case _:
|
case _:
|
||||||
return convert_nans_to_nones(str(value))
|
return convert_nans_to_nones(str(value))
|
||||||
if value is None:
|
if value is None:
|
||||||
value = date.today()
|
value = datetime.combine(date.today(), datetime.max.time())
|
||||||
return value
|
return value
|
||||||
|
|
||||||
@field_validator("expiry")
|
@field_validator("expiry")
|
||||||
@@ -201,6 +201,11 @@ class PydReagent(PydBaseClass):
|
|||||||
else:
|
else:
|
||||||
return values.data['reagentrole'].strip()
|
return values.data['reagentrole'].strip()
|
||||||
|
|
||||||
|
# @field_validator("reagentrole", mode="before")
|
||||||
|
# @classmethod
|
||||||
|
# def rescue_reagentrole(cls, value):
|
||||||
|
# if
|
||||||
|
|
||||||
def improved_dict(self) -> dict:
|
def improved_dict(self) -> dict:
|
||||||
"""
|
"""
|
||||||
Constructs a dictionary consisting of model.fields and model.extras
|
Constructs a dictionary consisting of model.fields and model.extras
|
||||||
@@ -226,23 +231,26 @@ class PydReagent(PydBaseClass):
|
|||||||
report = Report()
|
report = Report()
|
||||||
if self.model_extra is not None:
|
if self.model_extra is not None:
|
||||||
self.__dict__.update(self.model_extra)
|
self.__dict__.update(self.model_extra)
|
||||||
reagent = Reagent.query(lot=self.lot, name=self.name)
|
reagent, new = Reagent.query_or_create(lot=self.lot, name=self.name)
|
||||||
# logger.debug(f"Reagent: {reagent}")
|
# logger.debug(f"Reagent: {reagent}")
|
||||||
if reagent is None:
|
# if reagent is None:
|
||||||
reagent = Reagent()
|
# reagent = Reagent()
|
||||||
for key, value in self.__dict__.items():
|
# for key, value in self.__dict__.items():
|
||||||
if isinstance(value, dict):
|
# if isinstance(value, dict):
|
||||||
value = value['value']
|
# if key == "misc_info":
|
||||||
# NOTE: reagent method sets fields based on keys in dictionary
|
# value = value
|
||||||
reagent.set_attribute(key, value)
|
# else:
|
||||||
if procedure is not None and reagent not in procedure.reagents:
|
# value = value['value']
|
||||||
assoc = ProcedureReagentAssociation(reagent=reagent, procedure=procedure)
|
# # NOTE: reagent method sets fields based on keys in dictionary
|
||||||
assoc.comments = self.comment
|
# reagent.set_attribute(key, value)
|
||||||
else:
|
# if procedure is not None and reagent not in procedure.reagents:
|
||||||
assoc = None
|
# assoc = ProcedureReagentAssociation(reagent=reagent, procedure=procedure)
|
||||||
else:
|
# assoc.comments = self.comment
|
||||||
if submission is not None and reagent not in submission.reagents:
|
# else:
|
||||||
submission.update_reagentassoc(reagent=reagent, role=self.role)
|
# assoc = None
|
||||||
|
# else:
|
||||||
|
# if submission is not None and reagent not in submission.reagents:
|
||||||
|
# submission.update_reagentassoc(reagent=reagent, role=self.role)
|
||||||
return reagent, report
|
return reagent, report
|
||||||
|
|
||||||
|
|
||||||
@@ -1486,8 +1494,10 @@ class PydProcedure(PydBaseClass, arbitrary_types_allowed=True):
|
|||||||
if isinstance(kittype, str):
|
if isinstance(kittype, str):
|
||||||
kittype_obj = KitType.query(name=kittype)
|
kittype_obj = KitType.query(name=kittype)
|
||||||
try:
|
try:
|
||||||
self.reagentrole = {item.name: item.get_reagents(kittype=kittype_obj) + ["New"] for item in
|
self.reagentrole = {
|
||||||
kittype_obj.get_reagents(proceduretype=self.proceduretype)}
|
item.name: item.get_reagents(kittype=kittype_obj) + [PydReagent(name="--New--", lot="", reagentrole="")]
|
||||||
|
for item in
|
||||||
|
kittype_obj.get_reagents(proceduretype=self.proceduretype)}
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.reagentrole = {}
|
self.reagentrole = {}
|
||||||
|
|
||||||
@@ -1511,19 +1521,19 @@ class PydProcedure(PydBaseClass, arbitrary_types_allowed=True):
|
|||||||
logger.debug(f"Incoming sample_list:\n{pformat(sample_list)}")
|
logger.debug(f"Incoming sample_list:\n{pformat(sample_list)}")
|
||||||
for sample_dict in sample_list:
|
for sample_dict in sample_list:
|
||||||
if sample_dict['sample_id'].startswith("blank_"):
|
if sample_dict['sample_id'].startswith("blank_"):
|
||||||
continue
|
sample_dict['sample_id'] = ""
|
||||||
row, column = self.proceduretype.ranked_plate[sample_dict['index']]
|
row, column = self.proceduretype.ranked_plate[sample_dict['index']]
|
||||||
logger.debug(f"Row: {row}, Column: {column}")
|
logger.debug(f"Row: {row}, Column: {column}")
|
||||||
try:
|
try:
|
||||||
sample = next(
|
sample = next(
|
||||||
(item for item in self.samples if item.sample_id.upper() == sample_dict['sample_id'].upper()))
|
(item for item in self.sample if item.sample_id.upper() == sample_dict['sample_id'].upper()))
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
# NOTE: Code to check for added controls.
|
# NOTE: Code to check for added controls.
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"Sample not found by name: {sample_dict['sample_id']}, checking row {row} column {column}")
|
f"Sample not found by name: {sample_dict['sample_id']}, checking row {row} column {column}")
|
||||||
try:
|
try:
|
||||||
sample = next(
|
sample = next(
|
||||||
(item for item in self.samples if item.row == row and item.column == column))
|
(item for item in self.sample if item.row == row and item.column == column))
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
logger.error(f"Couldn't find sample: {pformat(sample_dict)}")
|
logger.error(f"Couldn't find sample: {pformat(sample_dict)}")
|
||||||
continue
|
continue
|
||||||
@@ -1532,7 +1542,23 @@ class PydProcedure(PydBaseClass, arbitrary_types_allowed=True):
|
|||||||
sample.well_id = sample_dict['sample_id']
|
sample.well_id = sample_dict['sample_id']
|
||||||
sample.row = row
|
sample.row = row
|
||||||
sample.column = column
|
sample.column = column
|
||||||
logger.debug(f"Updated samples:\n{pformat(self.samples)}")
|
# logger.debug(f"Updated samples:\n{pformat(self.sample)}")
|
||||||
|
|
||||||
|
def update_reagents(self, reagentrole: str, name: str, lot: str, expiry: str):
|
||||||
|
removable = next((item for item in self.reagent if item.reagentrole == reagentrole), None)
|
||||||
|
if removable:
|
||||||
|
idx = self.reagent.index(removable)
|
||||||
|
self.reagent.remove(removable)
|
||||||
|
else:
|
||||||
|
idx = 0
|
||||||
|
insertable = PydReagent(reagentrole=reagentrole, name=name, lot=lot, expiry=expiry)
|
||||||
|
self.reagent.insert(idx, insertable)
|
||||||
|
logger.debug(self.reagent)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def update_new_reagents(cls, reagent: PydReagent):
|
||||||
|
reg = reagent.to_sql()
|
||||||
|
reg.save()
|
||||||
|
|
||||||
def to_sql(self):
|
def to_sql(self):
|
||||||
from backend.db.models import RunSampleAssociation, ProcedureSampleAssociation
|
from backend.db.models import RunSampleAssociation, ProcedureSampleAssociation
|
||||||
@@ -1540,12 +1566,24 @@ class PydProcedure(PydBaseClass, arbitrary_types_allowed=True):
|
|||||||
# for result in self.results:
|
# for result in self.results:
|
||||||
# result, _ = result.to_sql()
|
# result, _ = result.to_sql()
|
||||||
sql = super().to_sql()
|
sql = super().to_sql()
|
||||||
logger.debug(f"Initial PYD: {pformat(self.__dict__)}")
|
# logger.debug(f"Initial PYD: {pformat(self.__dict__)}")
|
||||||
# sql.results = [result.to_sql() for result in self.results]
|
# sql.results = [result.to_sql() for result in self.results]
|
||||||
if self.run:
|
if self.run:
|
||||||
sql.run = self.run
|
sql.run = self.run
|
||||||
if self.proceduretype:
|
if self.proceduretype:
|
||||||
sql.proceduretype = self.proceduretype
|
sql.proceduretype = self.proceduretype
|
||||||
|
# Note: convert any new reagents to sql and save
|
||||||
|
for reagentrole, reagents in self.reagentrole.items():
|
||||||
|
for reagent in reagents:
|
||||||
|
if not reagent.lot or reagent.name == "--New--":
|
||||||
|
continue
|
||||||
|
self.update_new_reagents(reagent)
|
||||||
|
# NOTE: reset reagent associations.
|
||||||
|
sql.procedurereagentassociation = []
|
||||||
|
for reagent in self.reagent:
|
||||||
|
reagent = reagent.to_sql()
|
||||||
|
if reagent not in sql.reagent:
|
||||||
|
reagent_assoc = ProcedureReagentAssociation(reagent=reagent, procedure=sql)
|
||||||
try:
|
try:
|
||||||
start_index = max([item.id for item in ProcedureSampleAssociation.query()]) + 1
|
start_index = max([item.id for item in ProcedureSampleAssociation.query()]) + 1
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@@ -1571,13 +1609,15 @@ class PydProcedure(PydBaseClass, arbitrary_types_allowed=True):
|
|||||||
kittype = KitType.query(name=self.kittype['value'], limit=1)
|
kittype = KitType.query(name=self.kittype['value'], limit=1)
|
||||||
if kittype:
|
if kittype:
|
||||||
sql.kittype = kittype
|
sql.kittype = kittype
|
||||||
|
logger.debug(self.reagent)
|
||||||
for equipment in self.equipment:
|
for equipment in self.equipment:
|
||||||
equip = Equipment.query(name=equipment.name)
|
equip = Equipment.query(name=equipment.name)
|
||||||
if equip not in sql.equipment:
|
if equip not in sql.equipment:
|
||||||
equip_assoc = ProcedureEquipmentAssociation(equipment=equip, procedure=sql, equipmentrole=equip.equipmentrole[0])
|
equip_assoc = ProcedureEquipmentAssociation(equipment=equip, procedure=sql,
|
||||||
|
equipmentrole=equip.equipmentrole[0])
|
||||||
process = equipment.process.to_sql()
|
process = equipment.process.to_sql()
|
||||||
equip_assoc.process = process
|
equip_assoc.process = process
|
||||||
logger.debug(f"Output sql: {[pformat(item.__dict__) for item in sql.procedureequipmentassociation]}")
|
# logger.debug(f"Output sql: {[pformat(item.__dict__) for item in sql.procedureequipmentassociation]}")
|
||||||
return sql, None
|
return sql, None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import datetime
|
||||||
import os
|
import os
|
||||||
import sys, logging
|
import sys, logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -122,6 +123,24 @@ class ProcedureCreation(QDialog):
|
|||||||
def log(self, logtext: str):
|
def log(self, logtext: str):
|
||||||
logger.debug(logtext)
|
logger.debug(logtext)
|
||||||
|
|
||||||
|
@pyqtSlot(str, str, str, str)
|
||||||
|
def add_new_reagent(self, reagentrole: str, name: str, lot: str, expiry: str):
|
||||||
|
from backend.validators.pydant import PydReagent
|
||||||
|
expiry = datetime.datetime.strptime(expiry, "%Y-%m-%d")
|
||||||
|
pyd = PydReagent(reagentrole=reagentrole, name=name, lot=lot, expiry=expiry)
|
||||||
|
logger.debug(pyd)
|
||||||
|
self.procedure.reagentrole[reagentrole].insert(0, pyd)
|
||||||
|
logger.debug(pformat(self.procedure.__dict__))
|
||||||
|
self.set_html()
|
||||||
|
|
||||||
|
@pyqtSlot(str, str)
|
||||||
|
def update_reagent(self, reagentrole:str, name_lot_expiry:str):
|
||||||
|
try:
|
||||||
|
name, lot, expiry = name_lot_expiry.split(" - ")
|
||||||
|
except ValueError:
|
||||||
|
return
|
||||||
|
self.procedure.update_reagents(reagentrole=reagentrole, name=name, lot=lot, expiry=expiry)
|
||||||
|
|
||||||
def return_sql(self):
|
def return_sql(self):
|
||||||
return self.procedure.to_sql()
|
return self.procedure.to_sql()
|
||||||
|
|
||||||
|
|||||||
@@ -296,7 +296,7 @@ class SubmissionsTree(QTreeView):
|
|||||||
self.setAlternatingRowColors(True)
|
self.setAlternatingRowColors(True)
|
||||||
self.setIndentation(20)
|
self.setIndentation(20)
|
||||||
self.setItemsExpandable(True)
|
self.setItemsExpandable(True)
|
||||||
self.expanded.connect(self.expand_item)
|
# self.expanded.connect(self.expand_item)
|
||||||
|
|
||||||
for ii in range(2):
|
for ii in range(2):
|
||||||
self.resizeColumnToContents(ii)
|
self.resizeColumnToContents(ii)
|
||||||
|
|||||||
@@ -32,24 +32,24 @@ gridContainer.addEventListener("drop", (e) => {
|
|||||||
targetItem !== draggedItem //&&
|
targetItem !== draggedItem //&&
|
||||||
//targetItem.classList.contains("well")
|
//targetItem.classList.contains("well")
|
||||||
) {
|
) {
|
||||||
backend.log(targetItem.id);
|
// backend.log(targetItem.id);
|
||||||
const draggedIndex = [...gridContainer.children].indexOf(draggedItem);
|
const draggedIndex = [...gridContainer.children].indexOf(draggedItem);
|
||||||
const targetIndex = [...gridContainer.children].indexOf(targetItem);
|
const targetIndex = [...gridContainer.children].indexOf(targetItem);
|
||||||
if (draggedIndex < targetIndex) {
|
if (draggedIndex < targetIndex) {
|
||||||
backend.log(draggedIndex.toString() + " " + targetIndex.toString() + " Lesser");
|
// backend.log(draggedIndex.toString() + " " + targetIndex.toString() + " Lesser");
|
||||||
gridContainer.insertBefore(draggedItem, targetItem.nextSibling);
|
gridContainer.insertBefore(draggedItem, targetItem.nextSibling);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
backend.log(draggedIndex.toString() + " " + targetIndex.toString() + " Greater");
|
// backend.log(draggedIndex.toString() + " " + targetIndex.toString() + " Greater");
|
||||||
gridContainer.insertBefore(draggedItem, targetItem);
|
gridContainer.insertBefore(draggedItem, targetItem);
|
||||||
|
|
||||||
}
|
}
|
||||||
// output = [];
|
output = [];
|
||||||
// fullGrid = [...gridContainer.children];
|
fullGrid = [...gridContainer.children];
|
||||||
// fullGrid.forEach(function(item, index) {
|
fullGrid.forEach(function(item, index) {
|
||||||
// output.push({sample_id: item.id, index: index + 1})
|
output.push({sample_id: item.id, index: index + 1})
|
||||||
// });
|
});
|
||||||
// backend.rearrange_plate(output);
|
backend.rearrange_plate(output);
|
||||||
rearrange_plate();
|
// rearrange_plate();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -21,45 +21,39 @@ for(let i = 0; i < formtexts.length; i++) {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var changed_it = new Event('change');
|
||||||
|
|
||||||
var reagentRoles = document.getElementsByClassName("reagentrole");
|
var reagentRoles = document.getElementsByClassName("reagentrole");
|
||||||
|
|
||||||
for(let i = 0; i < reagentRoles.length; i++) {
|
for(let i = 0; i < reagentRoles.length; i++) {
|
||||||
reagentRoles[i].addEventListener("change", function() {
|
reagentRoles[i].addEventListener("change", function() {
|
||||||
if (reagentRoles[i].value === "New") {
|
if (reagentRoles[i].value.includes("--New--")) {
|
||||||
|
|
||||||
var br = document.createElement("br");
|
var br = document.createElement("br");
|
||||||
var new_reg = document.getElementById("new_" + reagentRoles[i].id);
|
var new_reg = document.getElementById("new_" + reagentRoles[i].id);
|
||||||
console.log(new_reg.id);
|
|
||||||
var new_form = document.createElement("form");
|
var new_form = document.createElement("form");
|
||||||
|
new_form.setAttribute("class", "new_reagent_form")
|
||||||
|
new_form.setAttribute("id", reagentRoles[i].id + "_addition")
|
||||||
var rr_name = document.createElement("input");
|
var rr_name = document.createElement("input");
|
||||||
rr_name.setAttribute("type", "text");
|
rr_name.setAttribute("type", "text");
|
||||||
rr_name.setAttribute("id", "new_" + reagentRoles[i].id + "_name");
|
rr_name.setAttribute("id", "new_" + reagentRoles[i].id + "_name");
|
||||||
|
|
||||||
var rr_name_label = document.createElement("label");
|
var rr_name_label = document.createElement("label");
|
||||||
rr_name_label.setAttribute("for", "new_" + reagentRoles[i].id + "_name");
|
rr_name_label.setAttribute("for", "new_" + reagentRoles[i].id + "_name");
|
||||||
rr_name_label.innerHTML = "Name:";
|
rr_name_label.innerHTML = "Name:";
|
||||||
|
|
||||||
var rr_lot = document.createElement("input");
|
var rr_lot = document.createElement("input");
|
||||||
rr_lot.setAttribute("type", "text");
|
rr_lot.setAttribute("type", "text");
|
||||||
rr_lot.setAttribute("id", "new_" + reagentRoles[i].id + "_lot");
|
rr_lot.setAttribute("id", "new_" + reagentRoles[i].id + "_lot");
|
||||||
|
|
||||||
var rr_lot_label = document.createElement("label");
|
var rr_lot_label = document.createElement("label");
|
||||||
rr_lot_label.setAttribute("for", "new_" + reagentRoles[i].id + "_lot");
|
rr_lot_label.setAttribute("for", "new_" + reagentRoles[i].id + "_lot");
|
||||||
rr_lot_label.innerHTML = "Lot:";
|
rr_lot_label.innerHTML = "Lot:";
|
||||||
|
|
||||||
var rr_expiry = document.createElement("input");
|
var rr_expiry = document.createElement("input");
|
||||||
rr_expiry.setAttribute("type", "date");
|
rr_expiry.setAttribute("type", "date");
|
||||||
rr_expiry.setAttribute("id", "new_" + reagentRoles[i].id + "_expiry");
|
rr_expiry.setAttribute("id", "new_" + reagentRoles[i].id + "_expiry");
|
||||||
|
|
||||||
var rr_expiry_label = document.createElement("label");
|
var rr_expiry_label = document.createElement("label");
|
||||||
rr_expiry_label.setAttribute("for", "new_" + reagentRoles[i].id + "_expiry");
|
rr_expiry_label.setAttribute("for", "new_" + reagentRoles[i].id + "_expiry");
|
||||||
rr_expiry_label.innerHTML = "Expiry:";
|
rr_expiry_label.innerHTML = "Expiry:";
|
||||||
|
|
||||||
var submit_btn = document.createElement("input");
|
var submit_btn = document.createElement("input");
|
||||||
submit_btn.setAttribute("type", "submit");
|
submit_btn.setAttribute("type", "submit");
|
||||||
submit_btn.setAttribute("value", "Submit");
|
submit_btn.setAttribute("value", "Submit");
|
||||||
|
|
||||||
new_form.appendChild(br.cloneNode());
|
new_form.appendChild(br.cloneNode());
|
||||||
new_form.appendChild(rr_name_label);
|
new_form.appendChild(rr_name_label);
|
||||||
new_form.appendChild(rr_name);
|
new_form.appendChild(rr_name);
|
||||||
@@ -72,19 +66,27 @@ for(let i = 0; i < reagentRoles.length; i++) {
|
|||||||
new_form.appendChild(br.cloneNode());
|
new_form.appendChild(br.cloneNode());
|
||||||
new_form.appendChild(submit_btn);
|
new_form.appendChild(submit_btn);
|
||||||
new_form.appendChild(br.cloneNode());
|
new_form.appendChild(br.cloneNode());
|
||||||
|
|
||||||
new_form.onsubmit = function(event) {
|
new_form.onsubmit = function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
alert(reagentRoles[i].id);
|
|
||||||
name = document.getElementById("new_" + reagentRoles[i].id + "_name").value;
|
name = document.getElementById("new_" + reagentRoles[i].id + "_name").value;
|
||||||
lot = document.getElementById("new_" + reagentRoles[i].id + "_lot").value;
|
lot = document.getElementById("new_" + reagentRoles[i].id + "_lot").value;
|
||||||
expiry = document.getElementById("new_" + reagentRoles[i].id + "_expiry").value;
|
expiry = document.getElementById("new_" + reagentRoles[i].id + "_expiry").value;
|
||||||
alert("Submitting: " + name + ", " + lot);
|
backend.add_new_reagent(reagentRoles[i].id, name, lot, expiry);
|
||||||
backend.log(name + " " + lot + " " + expiry);
|
new_form.remove();
|
||||||
|
reagentRoles[i].dispatchEvent(changed_it);
|
||||||
}
|
}
|
||||||
|
|
||||||
new_reg.appendChild(new_form);
|
new_reg.appendChild(new_form);
|
||||||
|
} else {
|
||||||
|
newregform = document.getElementById(reagentRoles[i].id + "_addition");
|
||||||
|
newregform.remove();
|
||||||
|
backend.update_reagent(reagentRoles[i].id, reagentRoles[i].value)
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.onload = function() {
|
||||||
|
for(let i = 0; i < reagentRoles.length; i++) {
|
||||||
|
backend.update_reagent(reagentRoles[i].id, reagentRoles[i].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,12 +31,14 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select><br>
|
</select><br>
|
||||||
{% if procedure['reagentrole'] %}
|
{% if procedure['reagentrole'] %}
|
||||||
<br><hr><br>
|
<br>
|
||||||
|
<h1><u>Reagents</u></h1>
|
||||||
|
<hr>
|
||||||
{% for key, value in procedure['reagentrole'].items() %}
|
{% for key, value in procedure['reagentrole'].items() %}
|
||||||
<label for="{{ key }}">{{ key }}:</label><br>
|
<label for="{{ key }}">{{ key }}:</label><br>
|
||||||
<select class="reagentrole dropdown" id="{{ key }}" name="{{ key }}"><br>
|
<select class="reagentrole dropdown" id="{{ key }}" name="{{ key }}"><br>
|
||||||
{% for reagent in value %}
|
{% for reagent in value %}
|
||||||
<option value="{{ reagent }}">{{ reagent }}</option>
|
<option value="{{ reagent.name }} {% if reagent.lot %}- {{ reagent.lot }} - {{ reagent.expiry.date() }}{% endif %}">{{ reagent.name }} {% if reagent.lot %}- {{ reagent.lot }} - {{ reagent.expiry.date() }}{% endif %}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
<div class="new_reagent" id="new_{{ key }}"></div>
|
<div class="new_reagent" id="new_{{ key }}"></div>
|
||||||
|
|||||||
Reference in New Issue
Block a user