Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/genlab_bestilling/libs/genlabid.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ def get_current_sequences(order_id: int | str) -> Any:
return sequences


def generate(order_id: int | str) -> None:
def generate(
order_id: int | str,
sorting_order: list[str] | None = None,
selected_samples: list[Any] | None = None,
) -> None:
"""
wrapper to handle errors and reset the sequence to the current sequence value
"""
Expand Down
25 changes: 25 additions & 0 deletions src/genlab_bestilling/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,10 @@ def to_draft(self) -> None:
def get_type(self) -> str:
return "order"

@property
def filled_genlab_count(self) -> int:
return self.samples.filter(genlab_id__isnull=False).count()

@property
def next_status(self) -> OrderStatus | None:
current_index = self.STATUS_ORDER.index(self.status)
Expand Down Expand Up @@ -461,6 +465,27 @@ def order_manually_checked(self) -> None:
self.save()
app.configure_task(name="generate-genlab-ids").defer(order_id=self.id)

def order_selected_checked(
self,
sorting_order: list[str] | None = None,
selected_samples: list[str] | None = None,
) -> None:
"""
Partially set the order as checked by the lab staff,
generate a genlab id for the samples selected
"""
self.internal_status = self.Status.CHECKED
self.status = self.OrderStatus.PROCESSING
self.save()

selected_sample_names = list(selected_samples.values_list("id", flat=True))

app.configure_task(name="generate-genlab-ids").defer(
order_id=self.id,
sorting_order=sorting_order,
selected_samples=selected_sample_names,
)


class AnalysisOrder(Order):
samples = models.ManyToManyField(
Expand Down
14 changes: 12 additions & 2 deletions src/genlab_bestilling/tasks.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# from .libs.isolation import isolate
from typing import Any

from django.db.utils import OperationalError
from procrastinate import RetryStrategy
from procrastinate.contrib.django import app
Expand All @@ -12,6 +14,14 @@
max_attempts=5, linear_wait=5, retry_exceptions={OperationalError}
),
)
def generate_ids(order_id: str | int) -> None:
generate_genlab_id(order_id=order_id)
def generate_ids(
order_id: int | str,
sorting_order: list[str] | None = None,
selected_samples: list[Any] | None = None,
) -> None:
generate_genlab_id(
order_id=order_id,
sorting_order=sorting_order,
selected_samples=selected_samples,
)
# isolate(order_id=order_id)
41 changes: 39 additions & 2 deletions src/staff/tables.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from typing import Any

import django_tables2 as tables
from django.db.models import IntegerField
from django.db.models.functions import Cast
from django.utils.safestring import mark_safe

from genlab_bestilling.models import (
Expand Down Expand Up @@ -139,6 +141,17 @@ class SampleBaseTable(tables.Table):
verbose_name="",
)

checked = tables.CheckBoxColumn(
attrs={
"th__input": {"type": "checkbox", "id": "select-all-checkbox"},
},
accessor="pk",
orderable=False,
empty_values=(),
)

name = tables.Column(order_by=("name_as_int",))

class Meta:
model = Sample
fields = [
Expand All @@ -154,17 +167,41 @@ class Meta:
"plate_positions",
]
attrs = {"class": "w-full table-auto tailwind-table table-sm"}
sequence = ("is_prioritised", "genlab_id", "guid", "name", "species", "type")
order_by = ("-is_prioritised", "species", "genlab_id", "name")
sequence = (
"checked",
"is_prioritised",
"genlab_id",
"guid",
"name",
"species",
"type",
)
order_by = (
"-is_prioritised",
"species",
"genlab_id",
"name_as_int",
)

empty_text = "No Samples"

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

if hasattr(self.data, "data"):
self.data.data = self.data.data.annotate(
name_as_int=Cast("name", output_field=IntegerField())
)

def render_plate_positions(self, value: Any) -> str:
if value:
return ", ".join([str(v) for v in value.all()])

return ""

def render_checked(self, record: Any) -> str:
return mark_safe(f'<input type="checkbox" name="checked" value="{record.id}">') # noqa: S308


def create_sample_table(base_fields: list[str] | None = None) -> type[tables.Table]:
class CustomSampleTable(tables.Table):
Expand Down
14 changes: 14 additions & 0 deletions src/staff/templates/staff/analysisorder_filter.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
{% extends "staff/base_filter.html" %}
{% load crispy_forms_tags static %}
{% load render_table from django_tables2 %}

{% block page-title %}
Analysis Orders
{% endblock page-title %}

{% block page-inner %}
<form method="get" class="py-3 px-4 border mb-3 ">
<div class="flex flex-wrap gap-4">
{{ filter.form | crispy }}
</div>
<button class="btn bg-primary" type="submit">Search</button>
</form>

{% render_table table %}

{% endblock page-inner %}
22 changes: 13 additions & 9 deletions src/staff/templates/staff/base_filter.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,23 @@
{% block content %}
<h3 class="text-4xl mb-5">{% block page-title %}{% endblock page-title %}</h3>
{% block page-inner %}{% endblock page-inner %}

<form method="get" class="py-3 px-4 border mb-3 ">
<div class="flex flex-wrap gap-4">
{{ filter.form | crispy }}
</div>
<button class="btn bg-primary" type="submit">Search</button>
</form>

{% render_table table %}
{% endblock %}

{% block body_javascript %}
{{ block.super }}
<script type="text/javascript" src="{% static 'admin/js/vendor/jquery/jquery.js' %}"></script>
{{ filter.form.media }}
<script>
document.addEventListener('DOMContentLoaded', function () {
const selectAll = document.getElementById('select-all-checkbox');
if (selectAll) {
selectAll.addEventListener('change', function () {
const checkboxes = document.querySelectorAll('input[name="checked"]');
checkboxes.forEach(cb => {
cb.checked = selectAll.checked;
});
});
}
});
</script>
{% endblock body_javascript %}
14 changes: 14 additions & 0 deletions src/staff/templates/staff/equipmentorder_filter.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
{% extends "staff/base_filter.html" %}
{% load crispy_forms_tags static %}
{% load render_table from django_tables2 %}

{% block page-title %}
Equipment Orders
{% endblock page-title %}

{% block page-inner %}
<form method="get" class="py-3 px-4 border mb-3 ">
<div class="flex flex-wrap gap-4">
{{ filter.form | crispy }}
</div>
<button class="btn bg-primary" type="submit">Search</button>
</form>

{% render_table table %}

{% endblock page-inner %}
14 changes: 14 additions & 0 deletions src/staff/templates/staff/extractionorder_filter.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
{% extends "staff/base_filter.html" %}
{% load crispy_forms_tags static %}
{% load render_table from django_tables2 %}

{% block page-title %}
Extraction Orders
{% endblock page-title %}

{% block page-inner %}
<form method="get" class="py-3 px-4 border mb-3 ">
<div class="flex flex-wrap gap-4">
{{ filter.form | crispy }}
</div>
<button class="btn bg-primary" type="submit">Search</button>
</form>

{% render_table table %}

{% endblock page-inner %}
11 changes: 11 additions & 0 deletions src/staff/templates/staff/extractionplate_filter.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{% extends "staff/base_filter.html" %}
{% load crispy_forms_tags static %}
{% load render_table from django_tables2 %}

{% block page-title %}
Extraction plates
Expand All @@ -8,4 +10,13 @@
<div class="flex justify-end my-3">
<a class="btn bg-primary" href="{% url 'staff:plates-create' %}">Create</a>
</div>

<form method="get" class="py-3 px-4 border mb-3 ">
<div class="flex flex-wrap gap-4">
{{ filter.form | crispy }}
</div>
<button class="btn bg-primary" type="submit">Search</button>
</form>

{% render_table table %}
{% endblock page-inner %}
14 changes: 14 additions & 0 deletions src/staff/templates/staff/project_filter.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
{% extends "staff/base_filter.html" %}
{% load crispy_forms_tags static %}
{% load render_table from django_tables2 %}

{% block page-title %}
Projects
{% endblock page-title %}

{% block page-inner %}
<form method="get" class="py-3 px-4 border mb-3 ">
<div class="flex flex-wrap gap-4">
{{ filter.form | crispy }}
</div>
<button class="btn bg-primary" type="submit">Search</button>
</form>

{% render_table table %}

{% endblock page-inner %}
29 changes: 28 additions & 1 deletion src/staff/templates/staff/sample_filter.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
{% extends "staff/base_filter.html" %}
{% load crispy_forms_tags static %}
{% load render_table from django_tables2 %}

{% block page-title %}
{% if order %}{{ order }} - Samples{% else %}Samples{% endif %}
<div class="flex justify-between items-center w-full">
<div>
{% if order %}
{{ order }} - Samples
{% else %}
Samples
{% endif %}
</div>
{% if order %}
<div>
{{ order.filled_genlab_count }} / {{ order.samples.count }} Genlabs generated
</div>
{% endif %}
</div>
{% endblock page-title %}

{% block page-inner %}
Expand All @@ -11,5 +26,17 @@
<a class="btn bg-yellow-500" href="{% url 'samples-csv' %}?order={{ order.pk }}"><i class="fas fa-download"></i> Download CSV</a>
<a class="btn bg-primary" href="{% url 'staff:order-extraction-samples-lab' order.pk %}"><i class="fas fa-flask"></i> Lab</a>
</div>

<form method="post" action="{% url 'staff:generate-genlab-ids' pk=order.pk %}">
{% csrf_token %}
<input type="hidden" name="sort" value="{{ request.GET.sort|default:'' }}">
<button class="btn bg-blue-500 text-white mt-4" type="submit" name="generate_genlab_ids">
<i class="fa-solid fa-id-badge"></i> Generate genlab IDs
</button>

<div class="text-right text-sm text-red-500"> This page is under development. The genlab IDs will generate for all, and without sorting as per now. </div>

{% render_table table %}
</form>
{% endif %}
{% endblock page-inner %}
12 changes: 12 additions & 0 deletions src/staff/templates/staff/samplemarkeranalysis_filter.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{% extends "staff/base_filter.html" %}
{% load crispy_forms_tags static %}
{% load render_table from django_tables2 %}

{% block page-title %}
{% if order %}{{ order }} - Samples{% else %}Samples{% endif %}
Expand All @@ -10,4 +12,14 @@
<a class="btn bg-primary" href="../"><i class="fas fa-arrow-left"></i> back</a>
</div>
{% endif %}

<form method="get" class="py-3 px-4 border mb-3 ">
<div class="flex flex-wrap gap-4">
{{ filter.form | crispy }}
</div>
<button class="btn bg-primary" type="submit">Search</button>
</form>

{% render_table table %}

{% endblock page-inner %}
6 changes: 6 additions & 0 deletions src/staff/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
ExtractionPlateCreateView,
ExtractionPlateDetailView,
ExtractionPlateListView,
GenerateGenlabIDsView,
ManaullyCheckedOrderActionView,
OrderAnalysisSamplesListView,
OrderExtractionSamplesListView,
Expand Down Expand Up @@ -85,6 +86,11 @@
SampleLabView.as_view(),
name="order-extraction-samples-lab",
),
path(
"orders/extraction/<int:pk>/samples/generate-genlab-ids/",
GenerateGenlabIDsView.as_view(),
name="generate-genlab-ids",
),
path(
"orders/analysis/<int:pk>/samples/",
OrderAnalysisSamplesListView.as_view(),
Expand Down
Loading