398 lines
16 KiB
HTML
398 lines
16 KiB
HTML
{% extends "base.html" %}
|
|
{% load crispy_forms_tags %}
|
|
{% load i18n %}
|
|
{% load l10n %}
|
|
{% load custom_tags %}
|
|
|
|
{% block title %}{{ recipe.name }}{% endblock %}
|
|
|
|
{% block extra_head %}
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pretty-checkbox@3.0/dist/pretty-checkbox.min.css"
|
|
integrity="sha384-ICB8i/maQ/5+tGLDUEcswB7Ch+OO9Oj8Z4Ov/Gs0gxqfTgLLkD3F43MhcEJ2x6/D" crossorigin="anonymous">
|
|
|
|
|
|
<!-- prevent weired character stuff escaping the pdf box -->
|
|
<style>
|
|
.textLayer > span {
|
|
color: transparent;
|
|
position: absolute;
|
|
white-space: pre;
|
|
cursor: text;
|
|
transform-origin: 0% 0%;
|
|
}
|
|
|
|
blockquote {
|
|
background: #f9f9f9;
|
|
border-left: 4px solid #ccc;
|
|
margin: 1.5em 10px;
|
|
padding: .5em 10px;
|
|
quotes: none;
|
|
}
|
|
|
|
blockquote:before {
|
|
color: #ccc;
|
|
content: open-quote;
|
|
font-size: 4em;
|
|
line-height: .1em;
|
|
margin-right: .25em;
|
|
vertical-align: -.4em;
|
|
}
|
|
|
|
blockquote p {
|
|
display: inline;
|
|
}
|
|
</style>
|
|
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="row">
|
|
<div class="col col-md-9">
|
|
<h3>{{ recipe.name }} <a href="{% url 'edit_recipe' recipe.pk %}" class="d-print-none"><i
|
|
class="fas fa-pencil-alt"></i></a></h3>
|
|
</div>
|
|
<div class="col col-md-3 d-print-none" style="text-align: right">
|
|
<button class="btn btn-success" onclick="$('#bookmarkModal').modal({'show':true})" data-toggle="tooltip"
|
|
data-placement="top" title="{% trans 'Add to Book' %}"><i
|
|
class="fas fa-bookmark"></i></button>
|
|
{% if ingredients %}
|
|
<a class="btn btn-warning" href="{% url 'view_shopping' %}?r={{ recipe.pk }}" data-toggle="tooltip"
|
|
data-placement="top" title="{% trans 'Generate shopping list' %}"><i
|
|
class="fas fa-shopping-cart"></i></a>
|
|
{% endif %}
|
|
<a class="btn btn-info" href="{% url 'new_meal_plan' %}?recipe={{ recipe.pk }}" data-toggle="tooltip"
|
|
data-placement="top" title="{% trans 'Add to Mealplan' %}"><i
|
|
class="fas fa-calendar"></i></a>
|
|
<a class="btn btn-light" onclick="window.print()" data-toggle="tooltip"
|
|
data-placement="top" title="{% trans 'Print' %}"><i
|
|
class="fas fa-print"></i></a>
|
|
<a class="btn btn-primary" href="{% url 'view_export' %}?r={{ recipe.pk }}" target="_blank"
|
|
data-toggle="tooltip"
|
|
data-placement="top" title="{% trans 'Export recipe' %}"><i
|
|
class="fas fa-file-export"></i></a>
|
|
</div>
|
|
</div>
|
|
|
|
{% if recipe.storage %}
|
|
<small>{% trans 'in' %} <a
|
|
href="{% url 'edit_storage' recipe.storage.pk %}">{{ recipe.storage.name }}</a></small><br/>
|
|
{% endif %}
|
|
|
|
{% if recipe.internal %}
|
|
<small>{% trans 'by' %} {{ recipe.created_by.get_user_name }}<br/></small>
|
|
{% endif %}
|
|
|
|
{% if recipe.keywords %}
|
|
{% for x in recipe.keywords.all %}
|
|
<span class="badge badge-pill badge-light">{{ x }}</span>
|
|
{% endfor %}
|
|
<br/>
|
|
<br/>
|
|
{% endif %}
|
|
|
|
{% if recipe.working_time and recipe.working_time != 0 %}
|
|
<span class="badge badge-secondary"><i
|
|
class="fas fa-user-clock"></i> {% trans 'Preparation time ca.' %} {{ recipe.working_time }} min </span>
|
|
{% endif %}
|
|
|
|
{% if recipe.waiting_time and recipe.waiting_time != 0 %}
|
|
<span
|
|
class="badge badge-secondary"><i
|
|
class="far fa-clock"></i> {% trans 'Waiting time ca.' %} {{ recipe.waiting_time }} min </span>
|
|
{% endif %}
|
|
|
|
{% if recipe.waiting_time and recipe.waiting_time != 0 or recipe.working_time and recipe.working_time != 0 %}
|
|
<br/>
|
|
<br/>
|
|
{% endif %}
|
|
|
|
<div class="row">
|
|
{% if ingredients %}
|
|
<div class="col-md-6 order-md-1 col-sm-12 order-sm-2 col-12 order-2">
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col col-md-9">
|
|
<h4 class="card-title">{% trans 'Ingredients' %}</h4>
|
|
</div>
|
|
<div class="col col-md-3">
|
|
|
|
<div class="input-group d-print-none">
|
|
<input type="number" value="1" maxlength="3" class="form-control" id="in_factor"
|
|
onchange="reloadIngredients()"/>
|
|
<div class="input-group-append">
|
|
<span class="input-group-text"><i class="fas fa-calculator"></i></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<br/>
|
|
<table class="table table-sm">
|
|
{% for i in ingredients %}
|
|
<tr>
|
|
<td style="vertical-align: middle!important;">
|
|
<div class="pretty p-default p-curve">
|
|
<input type="checkbox"/>
|
|
<div class="state p-success">
|
|
<label>
|
|
{% if i.amount != 0 %}
|
|
<span id="ing_{{ i.pk }}">{{ i.amount.normalize }}</span>
|
|
{{ i.unit }}
|
|
{% else %}
|
|
<span>⁣</span>
|
|
{% endif %}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
</td>
|
|
<td style="vertical-align: middle!important;">
|
|
{% if i.ingredient.recipe %}
|
|
<a href="{% url 'view_recipe' i.ingredient.recipe.pk %}" target="_blank">
|
|
{% endif %}
|
|
{{ i.ingredient.name }}
|
|
{% if i.ingredient.recipe %}
|
|
</a>
|
|
{% endif %}
|
|
|
|
</td>
|
|
<td style="vertical-align: middle!important;">
|
|
{% if i.note %}
|
|
<button class="btn btn-light btn-sm d-print-none" type="button"
|
|
data-container="body"
|
|
data-toggle="popover"
|
|
data-placement="right" data-html="true" data-trigger="focus"
|
|
data-content="{{ i.note }}">
|
|
<i class="fas fa-info"></i>
|
|
</button>
|
|
<div class="d-none d-print-block">
|
|
<i class="far fa-comment-alt"></i> {{ i.note }}
|
|
</div>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
<!-- Bottom border -->
|
|
<tr>
|
|
<td></td>
|
|
<td></td>
|
|
<td></td>
|
|
</tr>
|
|
</table>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% endif %}
|
|
{% if recipe.image %}
|
|
<div class="col-12 order-1 col-sm-12 order-sm-1 col-md-6 order-md-2" style="text-align: center">
|
|
<img class="img img-fluid rounded" src="{{ recipe.image.url }}" style="max-height: 30vh;"
|
|
alt="{% trans 'Recipe Image' %}">
|
|
<br/>
|
|
<br/>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% if ingredients or recipe.image %}
|
|
<br/>
|
|
<br/>
|
|
{% endif %}
|
|
|
|
<div style="font-size: large">
|
|
{% if recipe.instructions %}
|
|
{{ recipe.instructions | urlize | markdown | safe }}
|
|
{% endif %}
|
|
</div>
|
|
|
|
|
|
{% if recipe.storage %}
|
|
<div class="row">
|
|
{% if recipe.internal %}
|
|
<div class="col col-12" style="margin-top: 2vh">
|
|
<a href='#' onClick='openRecipe({{ recipe.id }})'
|
|
class="d-print-none">{% trans 'View external recipe' %} <i class="fas fa-external-link-alt"></i></a>
|
|
</div>
|
|
{% else %}
|
|
|
|
<div class="col col-12" style="margin-top: 2vh">
|
|
<div class="loader" id="id_loader"></div>
|
|
|
|
<div id="viewerContainer" class="border">
|
|
<div id="viewer" class="pdfViewer"></div>
|
|
</div>
|
|
|
|
<div class="alert alert-warning" role="alert" id="id_warning_no_preview" style="display: none">
|
|
{% trans 'Cloud not show a file preview. Maybe its not a PDF ?' %}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col col-12" style="margin-top: 2vh">
|
|
<div class="card border-info">
|
|
<div class="card-body text-info">
|
|
<h5 class="card-title">{% trans 'External recipe' %}</h5>
|
|
<p class="card-text">
|
|
{% blocktrans %}
|
|
This is an external recipe, which means you can only view it by opening the link
|
|
above.
|
|
You can convert this recipe to a fancy recipe by pressing the convert button. The
|
|
original
|
|
file
|
|
will still be accessible.
|
|
{% endblocktrans %}.
|
|
<br/>
|
|
<br/>
|
|
<a href="{% url 'edit_convert_recipe' recipe.pk %}"
|
|
class="card-link btn btn-info">{% trans 'Convert now!' %}</a>
|
|
<a href='#' onClick='openRecipe({{ recipe.id }})'
|
|
class="d-print-none btn btn-warning">{% trans 'View external recipe' %} <i
|
|
class="fas fa-external-link-alt"></i></a>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.3.200/pdf.min.js"
|
|
integrity="sha256-J4Z8Fhj2MITUakMQatkqOVdtqodUlwHtQ/ey6fSsudE="
|
|
crossorigin="anonymous"></script>
|
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.3.200/pdf_viewer.js"
|
|
integrity="sha256-JW7ackRikw8/UM/hHV6vKaZBYc+t2ZQ77sd3LWR8vh8="
|
|
crossorigin="anonymous"></script>
|
|
|
|
<script type="text/javascript">
|
|
var url = "{% url 'api_get_recipe_file' recipe_id=12345 %}".replace(/12345/, {{ recipe.id }});
|
|
$('#viewerContainer').hide();
|
|
|
|
var xhttp = new XMLHttpRequest();
|
|
xhttp.onreadystatechange = function () {
|
|
if (this.readyState === 4 && this.status === 200) {
|
|
var base64Pdf = atob(this.responseText);
|
|
$('#id_loader').hide();
|
|
$('#viewerContainer').show();
|
|
|
|
var container = document.getElementById("viewerContainer");
|
|
|
|
var pdfViewer = new pdfjsViewer.PDFViewer({
|
|
container: container,
|
|
});
|
|
|
|
document.addEventListener("pagesinit", function () {
|
|
// We can use pdfViewer now, e.g. let's change default scale.
|
|
pdfViewer.currentScaleValue = "page-width";
|
|
|
|
});
|
|
|
|
var loadingTask = pdfjsLib.getDocument({
|
|
data: base64Pdf
|
|
});
|
|
|
|
loadingTask.promise.then(function (pdfDocument) {
|
|
// Document loaded, specifying document for the viewer and
|
|
// the (optional) linkService.
|
|
pdfViewer.setDocument(pdfDocument);
|
|
|
|
});
|
|
}
|
|
|
|
};
|
|
xhttp.open("GET", url, true);
|
|
xhttp.send();
|
|
|
|
</script>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<br/>
|
|
<br/>
|
|
|
|
<h5 {% if not comments %}class="d-print-none" {% endif %}><i class="far fa-comments"></i> {% trans 'Comments' %}
|
|
</h5>
|
|
{% for c in comments %}
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<small class="card-title">{{ c.updated_at }} {% trans 'by' %} {{ c.created_by.username }}</small> <a
|
|
href="{% url 'edit_comment' c.pk %}" class="d-print-none"><i class="fas fa-pencil-alt"></i></a><br/>
|
|
{{ c.text }}
|
|
</div>
|
|
</div>
|
|
<br/>
|
|
{% endfor %}
|
|
|
|
<div class="d-print-none">
|
|
|
|
<form method="POST" class="post-form">
|
|
{% csrf_token %}
|
|
<div class="input-group mb-3">
|
|
<textarea name="comment-text" cols="15" rows="2" class="textarea form-control" required
|
|
id="comment-id_text"></textarea>
|
|
<div class="input-group-append">
|
|
<input type="submit" value="{% trans 'Comment' %}" class="btn btn-success">
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
{% if recipe.storage %}
|
|
{% include 'include/recipe_open_modal.html' %}
|
|
{% endif %}
|
|
|
|
<!-- Bookmark Modal -->
|
|
<div class="modal fade" id="bookmarkModal" tabindex="-1" role="dialog" aria-labelledby="bookmarkModalLabel"
|
|
aria-hidden="true">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="bookmarkModalLabel">Modal title</h5>
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
<form method="POST" class="post-form">
|
|
<div class="modal-body">
|
|
|
|
{% csrf_token %}
|
|
{{ bookmark_form|crispy }}
|
|
|
|
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
|
<input type="submit" value="{% trans 'Save' %}" class="btn btn-success">
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script type="text/javascript">
|
|
|
|
$(function () {
|
|
$('[data-toggle="popover"]').popover()
|
|
});
|
|
|
|
$('.popover-dismiss').popover({
|
|
trigger: 'focus'
|
|
});
|
|
|
|
function reloadIngredients() {
|
|
factor = Number($('#in_factor').val());
|
|
ingredients = {
|
|
{% for i in ingredients %}
|
|
{{ i.pk }}: {{ i.amount|unlocalize }},
|
|
{% endfor %}
|
|
}
|
|
|
|
for (var key in ingredients) {
|
|
$('#ing_' + key).html(Math.round(ingredients[key] * factor))
|
|
}
|
|
}
|
|
|
|
$(function () {
|
|
$('[data-toggle="tooltip"]').tooltip()
|
|
})
|
|
|
|
</script>
|
|
{% endblock %} |