Basic outline of yeast sample page.

None of the controls do anything yet.
This commit is contained in:
Chris Giacofei 2024-06-07 07:54:23 -04:00
parent e91a01f0bf
commit c3634141a3
4 changed files with 162 additions and 37 deletions

View File

@ -1,6 +1,8 @@
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
from config.extras import BREWFATHER_APP_ROOT
import logging import logging
logger = logging.getLogger('django') logger = logging.getLogger('django')
@ -18,6 +20,10 @@ class Batch(CustomModel):
brewfather_name = models.CharField(max_length=500, default='name') brewfather_name = models.CharField(max_length=500, default='name')
recipe = models.ForeignKey('BatchRecipe', on_delete=models.CASCADE, default=1) recipe = models.ForeignKey('BatchRecipe', on_delete=models.CASCADE, default=1)
@property
def brewfather_url(self):
return '{}/tabs/batches/batch/{}'.format(BREWFATHER_APP_ROOT, self.brewfather_id)
def __str__(self): def __str__(self):
# Return a string that represents the instance # Return a string that represents the instance
return 'BF #{num}: {name}'.format(name=self.brewfather_name, num=self.brewfather_num) return 'BF #{num}: {name}'.format(name=self.brewfather_name, num=self.brewfather_num)

View File

@ -8,12 +8,12 @@
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<!-- JS, Popper.js, and jQuery --> <!-- JS, Popper.js, and jQuery -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.min.js" <!-- <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.min.js" -->
integrity="sha384-0pUGZvbkm6XF6gxjEnlmuGrJXVbNuzT9qBBavbLwCsOGabYfZo0T0to5eqruptLy" <!-- integrity="sha384-0pUGZvbkm6XF6gxjEnlmuGrJXVbNuzT9qBBavbLwCsOGabYfZo0T0to5eqruptLy" -->
crossorigin="anonymous"></script> <!-- crossorigin="anonymous"></script> -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
crossorigin="anonymous"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
{% block script %}{% endblock %} {% block script %}{% endblock %}
<style> <style>
{% block style %}{% endblock %} {% block style %}{% endblock %}
@ -23,6 +23,15 @@
label { label {
margin-right: 10px; margin-right: 10px;
} }
.table-borderless > tbody > tr > td,
.table-borderless > tbody > tr > th,
.table-borderless > tfoot > tr > td,
.table-borderless > tfoot > tr > th,
.table-borderless > thead > tr > td,
.table-borderless > thead > tr > th {
border: none;
background-color: rgba(0,0,0, 0.0) !important;
}
</style> </style>
</head> </head>
<body> <body>
@ -90,8 +99,6 @@
{% block content %}{% endblock %} {% block content %}{% endblock %}
</main> </main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
</body> </body>
{% block endscript %}{% endblock %} {% block endscript %}{% endblock %}
</html> </html>

View File

@ -2,33 +2,143 @@
{% load mathfilters %} {% load mathfilters %}
{% block title %}Yeast Samples{% endblock %} {% block title %}Yeast Samples{% endblock %}
{% block jumbotron %}Yeast Sample:{% endblock %} {% block style %}
{% block jumbotronsub %}<a href="{% url 'admin:yeast_yeast_change' sample.id %}">{{ sample.id }}</a>{% endblock %} .table td.fit,
.table th.fit {
white-space: nowrap;
width: 1%;
}
{% endblock %}
{% block jumbotron %}Yeast Sample{% endblock %}
{% block jumbotronsub %}
<table class="table table-borderless">
<tbody>
<tr><th class="fit">{{ batch.strain.manufacturer.name }} {{ batch.strain.name }}</th><td><a href="{% url 'admin:yeast_yeast_change' sample.id %}">{{ sample.id }}</a></td></tr>
<tr><th class="fit">Batch Source</th>
<td>{{ batch.get_source_display }}
{% if batch.source_batch %}
from <a href="{{ batch.beer_url }}" target="_blank" rel="noopener noreferrer">#{{ batch.beer_num }}: {{ batch.beer_name }}</a><br>
{% endif %}
</td>
</tr>
<tr><th class="fit">Production Date</th><td>{{ sample.batch.production_date }}</td></tr>
<tr><th class="fit">Storage</th>
<td>
{{ sample.storage }}
{% if sample.pitched %}
(Pitched <a href="{{ sample.pitched_batch.brewfather_url }}" target="_blank" rel="noopener noreferrer">#{{ sample.pitched_batch.brewfather_num }}: {{ sample.pitched_batch.brewfather_name }}</a>)
{% endif %}
</td>
</tr>
</tbody>
</table>
{% endblock %}
{% block content %} {% block content %}
<!-- Information Header -->
<div class="container"> <div class="container">
<h3>{{ batch.strain.name }}</h3>
<b>Batch Source:</b> {{ batch.get_source_display }}
{% if batch.source_batch %}
from <a href="{{ batch.beer_url }}" target="_blank" rel="noopener noreferrer">#{{ batch.beer_num }}: {{ batch.beer_name }}</a>
{% endif %}<br>
<b>Production Date:</b> {{ sample.batch.production_date }}<br>
<p><p>
{% if batch.remaining_samples %}<h4>Batch Samples Remaining</h4>
<ul>
{% for sample in batch.remaining_samples %}
<li><a href="{% url 'yeast:yeast' sample.id %}">{{ sample.id }}</a> - Storage method: {{ sample.storage.name }} for {{ sample.age }} days, Viability: {{ sample.viability|mul:100|floatformat:1 }}%</li>
{% endfor %}
</ul>
{% endif %}
{% if batch.used_samples %}<h4>Batch Samples Used</h4>
<ul>
{% for sample in batch.used_samples %}
<li><a href="{% url 'yeast:yeast' sample.id %}">{{ sample.id }}</a></li>
{% endfor %}
</ul>
{% endif %}
</div> <!-- /container --> </div> <!-- /container -->
<!-- End Information Header -->
<!-- Main Data Container -->
<div class="container mt-4 mb-4">
<div class="row">
<!-- Tabbed Forms -->
<div class="col-lg-6" style="{% if sample.pitched %}display:none{% endif %}">
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item">
<a class="nav-link active" data-bs-toggle="tab" href="#propogate">Propogate Sample</a>
</li>
<li class="nav-item">
<a class="nav-link" data-bs-toggle="tab" href="#pitch">Pitch Sample</a>
</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div id="propogate" class="container tab-pane active"><br>
<!-- Sample Propogation Form -->
<div class="container" style="border:1px solid #cecece;">
<form >
<legend>Propogate Yeast Sample</legend>
<div class="mb-3">
<label for="new-samples" class="form-label"># New Samples</label>
<input type="number" class="form-control" id="new-samples" aria-describedby="numHelp">
<div id="numHelp" class="form-text">New samples will be automatically created</div>
</div>
<div class="mb-3">
<label for="parent" class="form-label">Default Storage Method</label>
<select class="form-select" id="parent" name="parent" aria-describedby="storageHelp">
<option selected>-- Choose an Option --</option>
{% for method in storage %}
<option value="{{ method.id }}">{{ method }}</option>
{% endfor %}
</select>
<div id="storageHelp" class="form-text">How will samples be stored?</div>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
<!-- End Sample Propogation Form -->
</div>
<div id="pitch" class="container tab-pane fade"><br>
<!-- Sample Pitch Form -->
<div class="container" style="border:1px solid #cecece;">
<form >
<legend>Pitch Yeast Sample</legend>
<div class="mb-3">
<label for="beer-batch" class="form-label">Beer Batch</label>
<select class="form-select" id="beer-batch" name="beer-batch" aria-describedby="batchHelp">
<option selected>Beer Batch</option>
<option value="1">#16 So So Special</option>
<option value="2">#17 Some other beer</option>
<option value="3">#18 Another Thing</option>
</select>
<div id="batchHelp" class="form-text">Select batch of beer sample is pitched into.</div>
</div>
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="starterCheck">
<label class="form-check-label" for="starterCheck">Pitched into starter?</label>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
<!-- End Sample Pitch Form -->
</div>
</div>
</div>
<!-- End Tabbed Forms -->
<!-- Remain Sample List -->
<div class="col-lg-6">
{% if batch.remaining_samples %}<h4>Other Remaining Batch Samples</h4>
<ul>
{% for s in batch.remaining_samples|dictsort:"storage.name" %}
{% if s.id != sample.id %}
<li><a href="{% url 'yeast:yeast' s.id %}">{{ s.id }}</a> - {{ s.storage.name }} for {{ s.age }} days, {{ s.viability|mul:100|floatformat:1 }}%</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
{% if batch.used_samples %}<h4>Other Samples Used</h4>
<ul>
{% for s in batch.used_samples %}
{% if s.id != sample.id %}
<li><a href="{% url 'yeast:yeast' s.id %}">{{ s.id }}</a></li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
</div>
<!-- End Remain Sample List -->
</div>
</div>
<!-- End Main Data Container -->
{% endblock %} {% endblock %}

View File

@ -6,7 +6,7 @@ from django.urls import reverse
from django.http import JsonResponse from django.http import JsonResponse
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from yeast.models import Yeast, Batch, Strain from yeast.models import Yeast, Batch, Strain, Storage
from config.extras import AveryLabel from config.extras import AveryLabel
from yeast.forms import BatchAddForm, StrainAddForm from yeast.forms import BatchAddForm, StrainAddForm
@ -21,10 +21,12 @@ class BatchListView(ListView):
model = Batch model = Batch
def sample(request, yeast_id): def sample(request, yeast_id):
sample = get_object_or_404(Yeast, pk=yeast_id) sample = get_object_or_404(Yeast, pk=yeast_id)
sample_batch = get_object_or_404(Batch, pk=sample.batch_id) return render(request, 'yeast/sample.html', {
return render(request, 'yeast/sample.html', {'sample': sample, 'batch':sample_batch}) 'sample': sample,
'batch': get_object_or_404(Batch, pk=sample.batch_id),
'storage': list(Storage.objects.all()),
})
# @login_required # @login_required
# def get_batches(request): # def get_batches(request):