WIP pdf embedding

This commit is contained in:
vabene1111
2020-02-19 16:55:13 +01:00
parent fc1cc70870
commit 88dc713683
12 changed files with 134 additions and 90 deletions

View File

@ -0,0 +1,23 @@
# Generated by Django 3.0.2 on 2020-02-19 15:05
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cookbook', '0025_userpreference_nav_color'),
]
operations = [
migrations.AddField(
model_name='recipe',
name='cors_link',
field=models.CharField(blank=True, max_length=1024, null=True),
),
migrations.AlterField(
model_name='recipe',
name='link',
field=models.CharField(blank=True, max_length=512, null=True),
),
]

View File

@ -84,7 +84,8 @@ class Recipe(models.Model):
storage = models.ForeignKey(Storage, on_delete=models.PROTECT, blank=True, null=True)
file_uid = models.CharField(max_length=256, default="")
file_path = models.CharField(max_length=512, default="")
link = models.CharField(max_length=512, default="")
link = models.CharField(max_length=512, null=True, blank=True)
cors_link = models.CharField(max_length=1024, null=True, blank=True)
keywords = models.ManyToManyField(Keyword, blank=True)
working_time = models.IntegerField(default=0)
waiting_time = models.IntegerField(default=0)

View File

@ -88,6 +88,16 @@ class Dropbox(Provider):
response = Dropbox.create_share_link(recipe)
return response['url']
@staticmethod
def get_cors_link(recipe):
if not recipe.link:
recipe.link = Dropbox.get_share_link(recipe)
recipe.save()
recipe.cors_link = recipe.link.replace('www.dropbox.', 'dl.dropboxusercontent.')
return recipe.cors_link
@staticmethod
def rename_file(recipe, new_name):
url = "https://api.dropboxapi.com/2/files/move_v2"

View File

@ -11,10 +11,14 @@ class Provider:
def get_share_link(recipe):
raise Exception('Method not implemented in storage provider')
@staticmethod
def get_cors_link(recipe):
raise Exception('Method not implemented in storage provider')
@staticmethod
def rename_file(recipe, new_name):
raise Exception('Method not implemented in storage provider')
@staticmethod
def delete_file(recipe, new_name):
def delete_file(recipe):
raise Exception('Method not implemented in storage provider')

View File

@ -8,8 +8,7 @@ from .models import *
class RecipeTable(tables.Table):
id = tables.LinkColumn('edit_recipe', args=[A('id')])
name = tables.TemplateColumn(
"<a href='#' onClick='openRecipe({{record.id}})'>{{record.name}}</a>")
name = tables.LinkColumn('view_recipe', args=[A('id')])
all_tags = tables.Column(
attrs={'td': {'class': 'd-none d-lg-table-cell'}, 'th': {'class': 'd-none d-lg-table-cell'}})

View File

@ -41,7 +41,7 @@
{% for r in b.recipes %}
<div class="row">
<div class="col col-md-10">
<li><a href="#" onClick='openRecipe({{ r.recipe.pk }})'>{{ r.recipe.name }}</a></li>
<li><a href="{% url 'view_recipe' r.recipe.pk %}">{{ r.recipe.name }}</a></li>
</div>
<div class="col col-md-2" style="text-align: right">
<a href="{% url 'delete_recipe_book_entry' r.pk %}"><i class="fas fa-trash-alt"></i></a>
@ -58,5 +58,4 @@
<br/>
{% endfor %}
{% include 'include/recipe_open_modal.html' %}
{% endblock %}

View File

@ -43,15 +43,12 @@
</div>
<script type="text/javascript">
function openRecipe(id, force_external = false) {
function openRecipe(id) {
var link = $('#a_recipe_open');
link.hide();
$('#div_loader').show();
var url = "{% url 'api_get_file_link' recipe_id=12345 %}".replace(/12345/, id);
if (force_external) {
url = "{% url 'api_get_external_file_link' recipe_id=12345 %}".replace(/12345/, id);
}
var url = "{% url 'api_get_external_file_link' recipe_id=12345 %}".replace(/12345/, id);
link.text("{% trans 'Open Recipe' %}");
$('#modal_recipe').modal('show');

View File

@ -63,6 +63,4 @@
</div>
{% endif %}
{% include 'include/recipe_open_modal.html' %}
{% endblock %}

View File

@ -56,7 +56,7 @@
<td>
{% for mp in days_value %}
<a href="{% url 'edit_plan' mp.pk %}"><i class="fas fa-edit"></i></a>
<a href="#" onclick="openRecipe({{ mp.recipe.id }})">{{ mp.recipe.name }}</a><br/>
<a href="{% url 'view_recipe' mp.recipe.id %}">{{ mp.recipe.name }}</a><br/>
{% endfor %}
</td>
{% endfor %}
@ -67,6 +67,4 @@
</div>
</div>
{% include 'include/recipe_open_modal.html' %}
{% endblock %}

View File

@ -134,84 +134,96 @@
{% if recipe.storage %}
<div class="row">
{% if recipe.internal %}
<a href='#' onClick='openRecipe({{ recipe.id }}, true)'
<a href='#' onClick='openRecipe({{ recipe.id }})'
class="d-print-none">{% trans 'View external recipe' %} <i class="fas fa-external-link-alt"></i></a>
{% else %}
<canvas id="id_pdf_canvas" class="border"></canvas>
<div class="col col-md-12" style="margin-top: 2vh">
<div class="loader" id="id_loader"></div>
<canvas id="id_pdf_canvas" class="border"></canvas>
</div>
<br/>
<br/>
<br/>
<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>
</p>
<div class="col col-md-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 type="text/javascript">
var url = "{% url 'api_get_external_file_link' recipe_id=12345 %}".replace(/12345/, {{ recipe.id }});
var url = "{% url 'api_get_cors_file_link' recipe_id=12345 %}".replace(/12345/, {{ recipe.id }});
$('#id_pdf_canvas').hide();
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState === 4 && this.status === 200) {
var url = this.responseText;
$('#id_loader').hide();
var loadingTask = pdfjsLib.getDocument(url.replace('www.dropbox.', 'dl.dropboxusercontent.'));
loadingTask.promise.then(function (pdf) {
console.log('PDF loaded');
if (url === "None") {
// direct previews are not supported for this provider
//TODO implement something useful for providers not allowing cors links
} else {
var loadingTask = pdfjsLib.getDocument(url);
loadingTask.promise.then(function (pdf) {
$('#id_pdf_canvas').show();
// Fetch the first page
var pageNumber = 1;
pdf.getPage(pageNumber).then(function (page) {
console.log('Page loaded');
// Fetch the first page
var pageNumber = 1;
pdf.getPage(pageNumber).then(function (page) {
var scale = 1.5;
var viewport = page.getViewport({scale: scale*0.8});
// Prepare canvas using PDF page dimensions
var canvas = document.getElementById('id_pdf_canvas');
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
var scale = 1.5;
var viewport = page.getViewport({scale: scale * 0.8});
// Render PDF page into canvas context
var renderContext = {
canvasContext: context,
viewport: viewport
};
var renderTask = page.render(renderContext);
renderTask.promise.then(function () {
console.log('Page rendered');
// Prepare canvas using PDF page dimensions
var canvas = document.getElementById('id_pdf_canvas');
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context
var renderContext = {
canvasContext: context,
viewport: viewport
};
var renderTask = page.render(renderContext);
renderTask.promise.then(function () {
console.log('Page rendered');
});
});
}, function (reason) {
// PDF loading error
console.error(reason);
});
}, function (reason) {
// PDF loading error
console.error(reason);
});
}
}
};
xhttp.open("GET", url, true);
xhttp.send();
</script>
{% endif %}
</div>

View File

@ -60,8 +60,8 @@ urlpatterns = [
path('data/sync/wait', data.sync_wait, name='data_sync_wait'),
path('data/statistics', data.statistics, name='data_stats'),
path('api/get_file_link/<int:recipe_id>/', api.get_file_link, name='api_get_file_link'),
path('api/get_external_file_link/<int:recipe_id>/', api.get_external_file_link, name='api_get_external_file_link'),
path('api/get_cors_file_link/<int:recipe_id>/', api.get_cors_file_link, name='api_get_cors_file_link'),
path('api/sync_all/', api.sync_all, name='api_sync'),

View File

@ -10,40 +10,43 @@ from cookbook.provider.dropbox import Dropbox
from cookbook.provider.nextcloud import Nextcloud
@login_required
def get_file_link(request, recipe_id):
recipe = Recipe.objects.get(id=recipe_id)
def update_recipe_links(recipe):
if recipe.storage.method == Storage.DROPBOX:
provider = Dropbox
elif recipe.storage.method == Storage.NEXTCLOUD:
provider = Nextcloud
else:
raise Exception('Provider not implemented')
if recipe.internal:
return HttpResponse(reverse('view_recipe', args=[recipe_id]))
if recipe.storage.method == Storage.DROPBOX: # TODO move to central location (as all provider related functions)
if recipe.link == "":
recipe.link = Dropbox.get_share_link(recipe) # TODO response validation
recipe.save()
if recipe.storage.method == Storage.NEXTCLOUD:
if recipe.link == "":
recipe.link = Nextcloud.get_share_link(recipe) # TODO response validation
recipe.save()
if not recipe.link:
recipe.link = provider.get_share_link(recipe) # TODO response validation in apis
if not recipe.cors_link:
try:
recipe.cors_link = provider.get_cors_link(recipe)
except Exception:
pass
return HttpResponse(recipe.link)
recipe.save()
@login_required
def get_external_file_link(request, recipe_id):
recipe = Recipe.objects.get(id=recipe_id)
if recipe.storage.method == Storage.DROPBOX: # TODO move to central location (as all provider related functions)
if recipe.link == "":
recipe.link = Dropbox.get_share_link(recipe) # TODO response validation
recipe.save()
if recipe.storage.method == Storage.NEXTCLOUD:
if recipe.link == "":
recipe.link = Nextcloud.get_share_link(recipe) # TODO response validation
recipe.save()
if not recipe.link:
update_recipe_links(recipe)
return HttpResponse(recipe.link)
@login_required
def get_cors_file_link(request, recipe_id):
recipe = Recipe.objects.get(id=recipe_id)
if not recipe.cors_link:
update_recipe_links(recipe)
return HttpResponse(recipe.cors_link)
@login_required
def sync_all(request):
monitors = Sync.objects.filter(active=True)