forked from CGM_Public/pretix_original
Revert "PDF editor improvements (#2529)"
This reverts commit e4c1f30b9d.
This commit is contained in:
@@ -37,7 +37,6 @@ import hashlib
|
|||||||
import itertools
|
import itertools
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
import uuid
|
import uuid
|
||||||
@@ -55,7 +54,6 @@ from django.utils.functional import SimpleLazyObject
|
|||||||
from django.utils.html import conditional_escape
|
from django.utils.html import conditional_escape
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from i18nfield.strings import LazyI18nString
|
|
||||||
from PyPDF2 import PdfFileReader
|
from PyPDF2 import PdfFileReader
|
||||||
from pytz import timezone
|
from pytz import timezone
|
||||||
from reportlab.graphics import renderPDF
|
from reportlab.graphics import renderPDF
|
||||||
@@ -204,11 +202,6 @@ DEFAULT_VARIABLES = OrderedDict((
|
|||||||
"editor_sample": 'foo@bar.com',
|
"editor_sample": 'foo@bar.com',
|
||||||
"evaluate": lambda op, order, ev: op.attendee_email or (op.addon_to.attendee_email if op.addon_to else '')
|
"evaluate": lambda op, order, ev: op.attendee_email or (op.addon_to.attendee_email if op.addon_to else '')
|
||||||
}),
|
}),
|
||||||
("pseudonymization_id", {
|
|
||||||
"label": _("Pseudonymization ID (lead scanning)"),
|
|
||||||
"editor_sample": "GG89JUJDTA",
|
|
||||||
"evaluate": lambda orderposition, order, event: orderposition.pseudonymization_id,
|
|
||||||
}),
|
|
||||||
("event_name", {
|
("event_name", {
|
||||||
"label": _("Event name"),
|
"label": _("Event name"),
|
||||||
"editor_sample": _("Sample event name"),
|
"editor_sample": _("Sample event name"),
|
||||||
@@ -623,14 +616,12 @@ class Renderer:
|
|||||||
preserveAspectRatio=True, anchor='n',
|
preserveAspectRatio=True, anchor='n',
|
||||||
mask='auto')
|
mask='auto')
|
||||||
|
|
||||||
def _draw_barcodearea(self, canvas: Canvas, op: OrderPosition, order: Order, o: dict):
|
def _draw_barcodearea(self, canvas: Canvas, op: OrderPosition, o: dict):
|
||||||
content = o.get('content', 'secret')
|
content = o.get('content', 'secret')
|
||||||
if content == 'secret':
|
if content == 'secret':
|
||||||
# do not use get_text_content because it uses a shortened version of secret
|
|
||||||
# and does not deal with our default value here properly
|
|
||||||
content = op.secret
|
content = op.secret
|
||||||
else:
|
elif content == 'pseudonymization_id':
|
||||||
content = self._get_text_content(op, order, o)
|
content = op.pseudonymization_id
|
||||||
|
|
||||||
level = 'H'
|
level = 'H'
|
||||||
if len(content) > 32:
|
if len(content) > 32:
|
||||||
@@ -657,45 +648,20 @@ class Renderer:
|
|||||||
return self._get_text_content(op, order, o, True)
|
return self._get_text_content(op, order, o, True)
|
||||||
|
|
||||||
ev = self._get_ev(op, order)
|
ev = self._get_ev(op, order)
|
||||||
|
|
||||||
if not o['content']:
|
if not o['content']:
|
||||||
return '(error)'
|
return '(error)'
|
||||||
|
if o['content'] == 'other':
|
||||||
if o['content'] == 'other' or o['content'] == 'other_i18n':
|
return o['text']
|
||||||
if o['content'] == 'other_i18n':
|
|
||||||
text = str(LazyI18nString(o['text_i18n']))
|
|
||||||
else:
|
|
||||||
text = o['text']
|
|
||||||
|
|
||||||
def replace(x):
|
|
||||||
if x.group(1) not in self.variables:
|
|
||||||
return x.group(0)
|
|
||||||
if x.group(1) == 'secret':
|
|
||||||
# Do not use shortened version
|
|
||||||
return op.secret
|
|
||||||
try:
|
|
||||||
return self.variables[x.group(1)]['evaluate'](op, order, ev)
|
|
||||||
except:
|
|
||||||
logger.exception('Failed to process variable.')
|
|
||||||
return '(error)'
|
|
||||||
|
|
||||||
# We do not use str.format like in emails so we (a) can evaluate lazily and (b) can re-implement this
|
|
||||||
# 1:1 on other platforms that render PDFs through our API (libpretixprint)
|
|
||||||
return re.sub(r'\{([a-zA-Z0-9_]+)\}', replace, text)
|
|
||||||
|
|
||||||
elif o['content'].startswith('itemmeta:'):
|
elif o['content'].startswith('itemmeta:'):
|
||||||
return op.item.meta_data.get(o['content'][9:]) or ''
|
return op.item.meta_data.get(o['content'][9:]) or ''
|
||||||
|
|
||||||
elif o['content'].startswith('meta:'):
|
elif o['content'].startswith('meta:'):
|
||||||
return ev.meta_data.get(o['content'][5:]) or ''
|
return ev.meta_data.get(o['content'][5:]) or ''
|
||||||
|
|
||||||
elif o['content'] in self.variables:
|
elif o['content'] in self.variables:
|
||||||
try:
|
try:
|
||||||
return self.variables[o['content']]['evaluate'](op, order, ev)
|
return self.variables[o['content']]['evaluate'](op, order, ev)
|
||||||
except:
|
except:
|
||||||
logger.exception('Failed to process variable.')
|
logger.exception('Failed to process variable.')
|
||||||
return '(error)'
|
return '(error)'
|
||||||
|
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
def _draw_imagearea(self, canvas: Canvas, op: OrderPosition, order: Order, o: dict):
|
def _draw_imagearea(self, canvas: Canvas, op: OrderPosition, order: Order, o: dict):
|
||||||
@@ -788,30 +754,20 @@ class Renderer:
|
|||||||
p.drawOn(canvas, 0, -h - ad[1])
|
p.drawOn(canvas, 0, -h - ad[1])
|
||||||
canvas.restoreState()
|
canvas.restoreState()
|
||||||
|
|
||||||
def draw_page(self, canvas: Canvas, order: Order, op: OrderPosition, show_page=True, only_page=None):
|
def draw_page(self, canvas: Canvas, order: Order, op: OrderPosition, show_page=True):
|
||||||
page_count = self.bg_pdf.getNumPages()
|
for o in self.layout:
|
||||||
|
if o['type'] == "barcodearea":
|
||||||
if not only_page and not show_page:
|
self._draw_barcodearea(canvas, op, o)
|
||||||
raise ValueError("only_page=None and show_page=False cannot be combined")
|
elif o['type'] == "imagearea":
|
||||||
|
self._draw_imagearea(canvas, op, order, o)
|
||||||
for page in range(page_count):
|
elif o['type'] == "textarea":
|
||||||
if only_page and only_page != page + 1:
|
self._draw_textarea(canvas, op, order, o)
|
||||||
continue
|
elif o['type'] == "poweredby":
|
||||||
for o in self.layout:
|
self._draw_poweredby(canvas, op, o)
|
||||||
if o.get('page', 1) != page + 1:
|
if self.bg_pdf:
|
||||||
continue
|
canvas.setPageSize((self.bg_pdf.getPage(0).mediaBox[2], self.bg_pdf.getPage(0).mediaBox[3]))
|
||||||
if o['type'] == "barcodearea":
|
if show_page:
|
||||||
self._draw_barcodearea(canvas, op, order, o)
|
canvas.showPage()
|
||||||
elif o['type'] == "imagearea":
|
|
||||||
self._draw_imagearea(canvas, op, order, o)
|
|
||||||
elif o['type'] == "textarea":
|
|
||||||
self._draw_textarea(canvas, op, order, o)
|
|
||||||
elif o['type'] == "poweredby":
|
|
||||||
self._draw_poweredby(canvas, op, o)
|
|
||||||
if self.bg_pdf:
|
|
||||||
canvas.setPageSize((self.bg_pdf.getPage(page).mediaBox[2], self.bg_pdf.getPage(page).mediaBox[3]))
|
|
||||||
if show_page:
|
|
||||||
canvas.showPage()
|
|
||||||
|
|
||||||
def render_background(self, buffer, title=_('Ticket')):
|
def render_background(self, buffer, title=_('Ticket')):
|
||||||
if settings.PDFTK:
|
if settings.PDFTK:
|
||||||
@@ -824,7 +780,7 @@ class Renderer:
|
|||||||
subprocess.run([
|
subprocess.run([
|
||||||
settings.PDFTK,
|
settings.PDFTK,
|
||||||
os.path.join(d, 'front.pdf'),
|
os.path.join(d, 'front.pdf'),
|
||||||
'multibackground',
|
'background',
|
||||||
os.path.join(d, 'back.pdf'),
|
os.path.join(d, 'back.pdf'),
|
||||||
'output',
|
'output',
|
||||||
os.path.join(d, 'out.pdf'),
|
os.path.join(d, 'out.pdf'),
|
||||||
@@ -838,8 +794,8 @@ class Renderer:
|
|||||||
new_pdf = PdfFileReader(buffer)
|
new_pdf = PdfFileReader(buffer)
|
||||||
output = PdfFileWriter()
|
output = PdfFileWriter()
|
||||||
|
|
||||||
for i, page in enumerate(new_pdf.pages):
|
for page in new_pdf.pages:
|
||||||
bg_page = copy.copy(self.bg_pdf.getPage(i))
|
bg_page = copy.copy(self.bg_pdf.getPage(0))
|
||||||
bg_page.mergePage(page)
|
bg_page.mergePage(page)
|
||||||
output.addPage(bg_page)
|
output.addPage(bg_page)
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
</script>
|
</script>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
<div class="panel panel-default panel-pdf-editor">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<div class="pull-right flip">
|
<div class="pull-right flip">
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
@@ -48,8 +48,6 @@
|
|||||||
{% trans "Editor" %}
|
{% trans "Editor" %}
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<ul class="nav nav-pills" id="page_nav">
|
|
||||||
</ul>
|
|
||||||
<div id="editor-canvas-area">
|
<div id="editor-canvas-area">
|
||||||
<canvas id="pdf-canvas"
|
<canvas id="pdf-canvas"
|
||||||
data-pdf-url="{{ pdf }}"
|
data-pdf-url="{{ pdf }}"
|
||||||
@@ -195,7 +193,7 @@
|
|||||||
<span class="btn btn-default fileinput-button background-button">
|
<span class="btn btn-default fileinput-button background-button">
|
||||||
<i class="fa fa-upload"></i>
|
<i class="fa fa-upload"></i>
|
||||||
<span>{% trans "Upload custom background" %}</span>
|
<span>{% trans "Upload custom background" %}</span>
|
||||||
<input id="fileupload" type="file" name="background" accept="application/pdf">
|
<input id="fileupload" type="file" name="background">
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-12 help-inline">
|
<div class="col-sm-12 help-inline">
|
||||||
@@ -206,14 +204,6 @@
|
|||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-12">
|
|
||||||
<p>
|
|
||||||
<a class="btn btn-default background-download-button" href="{{ pdf }}" target="_blank">
|
|
||||||
<i class="fa fa-download"></i>
|
|
||||||
<span>{% trans "Download current background" %}</span>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row control-group pdf-info">
|
<div class="row control-group pdf-info">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
@@ -367,9 +357,9 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row control-group text textcontent">
|
<div class="row control-group text">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<label>{% trans "Content" %}</label><br>
|
<label>{% trans "Text content" %}</label><br>
|
||||||
<select class="input-block-level form-control" id="toolbox-content">
|
<select class="input-block-level form-control" id="toolbox-content">
|
||||||
{% for varname, var in variables.items %}
|
{% for varname, var in variables.items %}
|
||||||
<option data-sample="{{ var.editor_sample }}" value="{{ varname }}">{{ var.label }}</option>
|
<option data-sample="{{ var.editor_sample }}" value="{{ varname }}">{{ var.label }}</option>
|
||||||
@@ -384,16 +374,10 @@
|
|||||||
{% trans "Item attribute:" %} {{ p.name }}
|
{% trans "Item attribute:" %} {{ p.name }}
|
||||||
</option>
|
</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<option value="other_i18n">{% trans "Other… (multilingual)" %}</option>
|
|
||||||
<option value="other">{% trans "Other…" %}</option>
|
<option value="other">{% trans "Other…" %}</option>
|
||||||
</select>
|
</select>
|
||||||
<textarea type="text" value="" class="input-block-level form-control"
|
<textarea type="text" value="" class="input-block-level form-control"
|
||||||
id="toolbox-content-other"></textarea>
|
id="toolbox-content-other"></textarea>
|
||||||
<div class="i18n-form-group" id="toolbox-content-other-i18n">
|
|
||||||
{% for l in request.event.settings.locales %}
|
|
||||||
<textarea id="toolbox-content-other-{{ l }}" rows="3" class="input-block-level form-control" title="{{ l }}" lang="{{ l }}"></textarea>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -417,20 +401,13 @@
|
|||||||
<span class="fa fa-qrcode"></span>
|
<span class="fa fa-qrcode"></span>
|
||||||
{% trans "QR code for Lead Scanning" %}
|
{% trans "QR code for Lead Scanning" %}
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-default btn-block" id="editor-add-qrcode-other"
|
|
||||||
data-content="secret"
|
|
||||||
disabled>
|
|
||||||
<span class="fa fa-qrcode"></span>
|
|
||||||
{% trans "Other QR code" %}
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-default btn-block" id="editor-add-poweredby"
|
<button class="btn btn-default btn-block" id="editor-add-poweredby"
|
||||||
data-content="dark"
|
data-content="dark"
|
||||||
disabled>
|
disabled>
|
||||||
<span class="fa fa-image"></span>
|
<span class="fa fa-image"></span>
|
||||||
{% trans "pretix Logo" %}
|
{% trans "pretix Logo" %}
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-default btn-block" id="editor-add-image" disabled
|
<button class="btn btn-default btn-block" id="editor-add-image" disabled>
|
||||||
data-toggle="tooltip" title="{% trans "You can use this to add user-uploaded pictures from questions or pictures generated by plugins. If you want to embed a logo or other images, use a custom background instead." %}">
|
|
||||||
<span class="fa fa-image"></span>
|
<span class="fa fa-image"></span>
|
||||||
{% trans "Dynamic image" %}
|
{% trans "Dynamic image" %}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
import mimetypes
|
import mimetypes
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from decimal import Decimal
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@@ -39,8 +38,7 @@ from django.utils.crypto import get_random_string
|
|||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
from PyPDF2 import PdfFileReader, PdfFileWriter
|
from PyPDF2 import PdfFileWriter
|
||||||
from PyPDF2.utils import PdfReadError
|
|
||||||
from reportlab.lib.units import mm
|
from reportlab.lib.units import mm
|
||||||
|
|
||||||
from pretix.base.i18n import language
|
from pretix.base.i18n import language
|
||||||
@@ -84,15 +82,15 @@ class BaseEditorView(EventPermissionRequiredMixin, TemplateView):
|
|||||||
return None, f
|
return None, f
|
||||||
|
|
||||||
def _get_preview_position(self):
|
def _get_preview_position(self):
|
||||||
item = self.request.event.items.create(name=_("Sample product"), default_price=Decimal('42.23'),
|
item = self.request.event.items.create(name=_("Sample product"), default_price=42.23,
|
||||||
description=_("Sample product description"))
|
description=_("Sample product description"))
|
||||||
item2 = self.request.event.items.create(name=_("Sample workshop"), default_price=Decimal('23.40'))
|
item2 = self.request.event.items.create(name=_("Sample workshop"), default_price=23.40)
|
||||||
|
|
||||||
from pretix.base.models import Order
|
from pretix.base.models import Order
|
||||||
order = self.request.event.orders.create(status=Order.STATUS_PENDING, datetime=now(),
|
order = self.request.event.orders.create(status=Order.STATUS_PENDING, datetime=now(),
|
||||||
email='sample@pretix.eu',
|
email='sample@pretix.eu',
|
||||||
locale=self.request.event.settings.locale,
|
locale=self.request.event.settings.locale,
|
||||||
expires=now(), code="PREVIEW1234", total=Decimal('119.00'))
|
expires=now(), code="PREVIEW1234", total=119)
|
||||||
|
|
||||||
scheme = PERSON_NAME_SCHEMES[self.request.event.settings.name_scheme]
|
scheme = PERSON_NAME_SCHEMES[self.request.event.settings.name_scheme]
|
||||||
sample = {k: str(v) for k, v in scheme['sample'].items()}
|
sample = {k: str(v) for k, v in scheme['sample'].items()}
|
||||||
@@ -193,17 +191,6 @@ class BaseEditorView(EventPermissionRequiredMixin, TemplateView):
|
|||||||
c.file = fileobj
|
c.file = fileobj
|
||||||
c.save()
|
c.save()
|
||||||
c.refresh_from_db()
|
c.refresh_from_db()
|
||||||
|
|
||||||
try:
|
|
||||||
bg_bytes = c.file.read()
|
|
||||||
PdfFileReader(BytesIO(bg_bytes), strict=False)
|
|
||||||
except PdfReadError as e:
|
|
||||||
return JsonResponse({
|
|
||||||
"status": "error",
|
|
||||||
"error": _('Unfortunately, we were unable to process this PDF file ({reason}).').format(
|
|
||||||
reason=str(e)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
return JsonResponse({
|
return JsonResponse({
|
||||||
"status": "ok",
|
"status": "ok",
|
||||||
"id": c.id,
|
"id": c.id,
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ def render_pdf(event, positions, opt):
|
|||||||
offsety = opt['margins'][2] + (opt['rows'] - 1 - i // opt['cols']) * opt['offsets'][1]
|
offsety = opt['margins'][2] + (opt['rows'] - 1 - i // opt['cols']) * opt['offsets'][1]
|
||||||
p.translate(offsetx, offsety)
|
p.translate(offsetx, offsety)
|
||||||
with language(op.order.locale, op.order.event.settings.region):
|
with language(op.order.locale, op.order.event.settings.region):
|
||||||
r.draw_page(p, op.order, op, show_page=False, only_page=1)
|
r.draw_page(p, op.order, op, show_page=False)
|
||||||
p.translate(-offsetx, -offsety)
|
p.translate(-offsetx, -offsety)
|
||||||
|
|
||||||
if opt['pagesize']:
|
if opt['pagesize']:
|
||||||
|
|||||||
@@ -66,11 +66,9 @@ fabric.Barcodearea = fabric.util.createClass(fabric.Rect, {
|
|||||||
ctx.font = '16px Helvetica';
|
ctx.font = '16px Helvetica';
|
||||||
ctx.fillStyle = '#fff';
|
ctx.fillStyle = '#fff';
|
||||||
if (this.content === "pseudonymization_id") {
|
if (this.content === "pseudonymization_id") {
|
||||||
ctx.fillText(this.content, -this.width / 2, -this.height / 2 + 20);
|
ctx.fillText(gettext('Lead Scan QR'), -this.width / 2, -this.height / 2 + 20);
|
||||||
} else if (!this.content || this.content === "secret") {
|
|
||||||
ctx.fillText(gettext('Check-in QR'), -this.width / 2, -this.height / 2 + 20);
|
|
||||||
} else {
|
} else {
|
||||||
ctx.fillText(this.content, -this.width / 2, -this.height / 2 + 20);
|
ctx.fillText(gettext('Check-in QR'), -this.width / 2, -this.height / 2 + 20);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -104,15 +102,11 @@ var editor = {
|
|||||||
objects: [],
|
objects: [],
|
||||||
history: [],
|
history: [],
|
||||||
clipboard: [],
|
clipboard: [],
|
||||||
pdf: null,
|
|
||||||
pdf_page: null,
|
pdf_page: null,
|
||||||
pdf_page_number: 1,
|
|
||||||
pdf_page_count: 1,
|
|
||||||
pdf_scale: 1,
|
pdf_scale: 1,
|
||||||
pdf_viewport: null,
|
pdf_viewport: null,
|
||||||
_history_pos: 0,
|
_history_pos: 0,
|
||||||
_history_modification_in_progress: false,
|
_history_modification_in_progress: false,
|
||||||
_other_page_objects: [],
|
|
||||||
dirty: false,
|
dirty: false,
|
||||||
pdf_url: null,
|
pdf_url: null,
|
||||||
uploaded_file_id: null,
|
uploaded_file_id: null,
|
||||||
@@ -136,7 +130,7 @@ var editor = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
dump: function (objs) {
|
dump: function (objs) {
|
||||||
var d = !objs ? JSON.parse(JSON.stringify(editor._other_page_objects)) : [];
|
var d = [];
|
||||||
objs = objs || editor.fabric.getObjects();
|
objs = objs || editor.fabric.getObjects();
|
||||||
|
|
||||||
for (var i in objs) {
|
for (var i in objs) {
|
||||||
@@ -155,7 +149,6 @@ var editor = {
|
|||||||
}
|
}
|
||||||
d.push({
|
d.push({
|
||||||
type: "textarea",
|
type: "textarea",
|
||||||
page: editor.pdf_page_number,
|
|
||||||
locale: $("#pdf-info-locale").val(),
|
locale: $("#pdf-info-locale").val(),
|
||||||
left: editor._px2mm(left).toFixed(2),
|
left: editor._px2mm(left).toFixed(2),
|
||||||
bottom: editor._px2mm(bottom).toFixed(2),
|
bottom: editor._px2mm(bottom).toFixed(2),
|
||||||
@@ -169,14 +162,12 @@ var editor = {
|
|||||||
downward: o.downward || false,
|
downward: o.downward || false,
|
||||||
content: o.content,
|
content: o.content,
|
||||||
text: o.text,
|
text: o.text,
|
||||||
text_i18n: o.text_i18n || {},
|
|
||||||
rotation: o.angle,
|
rotation: o.angle,
|
||||||
align: o.textAlign,
|
align: o.textAlign,
|
||||||
});
|
});
|
||||||
} else if (o.type === "imagearea") {
|
} else if (o.type === "imagearea") {
|
||||||
d.push({
|
d.push({
|
||||||
type: "imagearea",
|
type: "imagearea",
|
||||||
page: editor.pdf_page_number,
|
|
||||||
left: editor._px2mm(left).toFixed(2),
|
left: editor._px2mm(left).toFixed(2),
|
||||||
bottom: editor._px2mm(editor.pdf_viewport.height - o.height * o.scaleY - top).toFixed(2),
|
bottom: editor._px2mm(editor.pdf_viewport.height - o.height * o.scaleY - top).toFixed(2),
|
||||||
height: editor._px2mm(o.height * o.scaleY).toFixed(2),
|
height: editor._px2mm(o.height * o.scaleY).toFixed(2),
|
||||||
@@ -186,18 +177,15 @@ var editor = {
|
|||||||
} else if (o.type === "barcodearea") {
|
} else if (o.type === "barcodearea") {
|
||||||
d.push({
|
d.push({
|
||||||
type: "barcodearea",
|
type: "barcodearea",
|
||||||
page: editor.pdf_page_number,
|
|
||||||
left: editor._px2mm(left).toFixed(2),
|
left: editor._px2mm(left).toFixed(2),
|
||||||
bottom: editor._px2mm(editor.pdf_viewport.height - o.height * o.scaleY - top).toFixed(2),
|
bottom: editor._px2mm(editor.pdf_viewport.height - o.height * o.scaleY - top).toFixed(2),
|
||||||
size: editor._px2mm(o.height * o.scaleY).toFixed(2),
|
size: editor._px2mm(o.height * o.scaleY).toFixed(2),
|
||||||
content: o.content,
|
content: o.content,
|
||||||
text: o.text,
|
|
||||||
nowhitespace: o.nowhitespace || false,
|
nowhitespace: o.nowhitespace || false,
|
||||||
});
|
});
|
||||||
} else if (o.type === "poweredby") {
|
} else if (o.type === "poweredby") {
|
||||||
d.push({
|
d.push({
|
||||||
type: "poweredby",
|
type: "poweredby",
|
||||||
page: editor.pdf_page_number,
|
|
||||||
left: editor._px2mm(left).toFixed(2),
|
left: editor._px2mm(left).toFixed(2),
|
||||||
bottom: editor._px2mm(editor.pdf_viewport.height - o.height * o.scaleY - top).toFixed(2),
|
bottom: editor._px2mm(editor.pdf_viewport.height - o.height * o.scaleY - top).toFixed(2),
|
||||||
size: editor._px2mm(o.height * o.scaleY).toFixed(2),
|
size: editor._px2mm(o.height * o.scaleY).toFixed(2),
|
||||||
@@ -209,11 +197,6 @@ var editor = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_add_from_data: function (d) {
|
_add_from_data: function (d) {
|
||||||
var targetPage = d.page || 1;
|
|
||||||
if (targetPage !== editor.pdf_page_number) {
|
|
||||||
editor._other_page_objects.push(d);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (d.type === "barcodearea") {
|
if (d.type === "barcodearea") {
|
||||||
o = editor._add_qrcode();
|
o = editor._add_qrcode();
|
||||||
o.content = d.content;
|
o.content = d.content;
|
||||||
@@ -247,9 +230,6 @@ var editor = {
|
|||||||
}
|
}
|
||||||
if (d.content === "other") {
|
if (d.content === "other") {
|
||||||
o.setText(d.text);
|
o.setText(d.text);
|
||||||
} else if (d.content === "other_i18n") {
|
|
||||||
o.text_i18n = d.text_i18n
|
|
||||||
o.setText(d.text_i18n[Object.keys(d.text_i18n)[0]]);
|
|
||||||
} else {
|
} else {
|
||||||
o.setText(editor._get_text_sample(d.content));
|
o.setText(editor._get_text_sample(d.content));
|
||||||
}
|
}
|
||||||
@@ -271,7 +251,6 @@ var editor = {
|
|||||||
|
|
||||||
load: function(data) {
|
load: function(data) {
|
||||||
editor.fabric.clear();
|
editor.fabric.clear();
|
||||||
editor._other_page_objects = [];
|
|
||||||
for (var i in data) {
|
for (var i in data) {
|
||||||
var d = data[i], o;
|
var d = data[i], o;
|
||||||
editor._add_from_data(d);
|
editor._add_from_data(d);
|
||||||
@@ -289,71 +268,6 @@ var editor = {
|
|||||||
return $('#toolbox-content option[value='+key+']').attr('data-sample') || '';
|
return $('#toolbox-content option[value='+key+']').attr('data-sample') || '';
|
||||||
},
|
},
|
||||||
|
|
||||||
_load_page: function (page_number, dump) {
|
|
||||||
var previous_dump = editor._fabric_loaded ? editor.dump() : [];
|
|
||||||
|
|
||||||
// Fetch the required page
|
|
||||||
editor.pdf.getPage(page_number).then(function (page) {
|
|
||||||
console.log('Page loaded');
|
|
||||||
var canvas = document.getElementById('pdf-canvas');
|
|
||||||
|
|
||||||
var scale = editor.$cva.width() / page.getViewport(1.0).width;
|
|
||||||
var viewport = page.getViewport(scale);
|
|
||||||
|
|
||||||
// Prepare canvas using PDF page dimensions
|
|
||||||
var context = canvas.getContext('2d');
|
|
||||||
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
||||||
canvas.height = viewport.height;
|
|
||||||
canvas.width = viewport.width;
|
|
||||||
|
|
||||||
editor.pdf_page = page;
|
|
||||||
editor.pdf_scale = scale;
|
|
||||||
editor.pdf_viewport = viewport;
|
|
||||||
|
|
||||||
// Render PDF page into canvas context
|
|
||||||
var renderContext = {
|
|
||||||
canvasContext: context,
|
|
||||||
viewport: viewport
|
|
||||||
};
|
|
||||||
var renderTask = page.render(renderContext);
|
|
||||||
renderTask.then(function () {
|
|
||||||
editor.pdf_page_number = page_number
|
|
||||||
editor._init_page_nav();
|
|
||||||
|
|
||||||
console.log('Page rendered');
|
|
||||||
if (dump || !editor._fabric_loaded) {
|
|
||||||
editor._init_fabric(dump);
|
|
||||||
} else {
|
|
||||||
editor.load(previous_dump);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_init_page_nav: function () {
|
|
||||||
if (editor.pdf_page_count === 1) {
|
|
||||||
$("#page_nav").hide();
|
|
||||||
} else {
|
|
||||||
$("#page_nav").html("");
|
|
||||||
for (i = 1; i <= editor.pdf_page_count; i++) {
|
|
||||||
var $li = $("<li>").addClass("nav-item");
|
|
||||||
var $a = $("<a>").text(i).attr("href", "#").attr("data-page", i).appendTo($li);
|
|
||||||
if (i === editor.pdf_page_number) {
|
|
||||||
$li.addClass("active")
|
|
||||||
}
|
|
||||||
$("#page_nav").append($li)
|
|
||||||
$a.on("click", function (event) {
|
|
||||||
console.log("switch to page", $(this).attr("data-page"));
|
|
||||||
editor.fabric.deactivateAll();
|
|
||||||
editor._load_page(parseInt($(this).attr("data-page")));
|
|
||||||
event.preventDefault();
|
|
||||||
return true;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
$("#page_nav").show();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_load_pdf: function (dump) {
|
_load_pdf: function (dump) {
|
||||||
// TODO: Loading indicators
|
// TODO: Loading indicators
|
||||||
var url = editor.pdf_url;
|
var url = editor.pdf_url;
|
||||||
@@ -365,13 +279,36 @@ var editor = {
|
|||||||
loadingTask.promise.then(function (pdf) {
|
loadingTask.promise.then(function (pdf) {
|
||||||
console.log('PDF loaded');
|
console.log('PDF loaded');
|
||||||
|
|
||||||
editor.pdf = pdf;
|
// Fetch the first page
|
||||||
editor.pdf_page_count = pdf.numPages;
|
var pageNumber = 1;
|
||||||
if (editor.pdf_page_count > 10) {
|
pdf.getPage(pageNumber).then(function (page) {
|
||||||
alert('Please do not upload files with more than 10 pages for performance reasons.')
|
console.log('Page loaded');
|
||||||
}
|
var canvas = document.getElementById('pdf-canvas');
|
||||||
editor._init_page_nav();
|
|
||||||
editor._load_page(1, dump);
|
var scale = editor.$cva.width() / page.getViewport(1.0).width;
|
||||||
|
var viewport = page.getViewport(scale);
|
||||||
|
|
||||||
|
// Prepare canvas using PDF page dimensions
|
||||||
|
var context = canvas.getContext('2d');
|
||||||
|
context.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
canvas.height = viewport.height;
|
||||||
|
canvas.width = viewport.width;
|
||||||
|
|
||||||
|
editor.pdf_page = page;
|
||||||
|
editor.pdf_scale = scale;
|
||||||
|
editor.pdf_viewport = viewport;
|
||||||
|
|
||||||
|
// Render PDF page into canvas context
|
||||||
|
var renderContext = {
|
||||||
|
canvasContext: context,
|
||||||
|
viewport: viewport
|
||||||
|
};
|
||||||
|
var renderTask = page.render(renderContext);
|
||||||
|
renderTask.then(function () {
|
||||||
|
console.log('Page rendered');
|
||||||
|
editor._init_fabric(dump);
|
||||||
|
});
|
||||||
|
});
|
||||||
}, function (reason) {
|
}, function (reason) {
|
||||||
var msg = gettext('The PDF background file could not be loaded for the following reason:');
|
var msg = gettext('The PDF background file could not be loaded for the following reason:');
|
||||||
editor._error(msg + ' ' + reason);
|
editor._error(msg + ' ' + reason);
|
||||||
@@ -395,7 +332,6 @@ var editor = {
|
|||||||
editor._update_toolbox();
|
editor._update_toolbox();
|
||||||
|
|
||||||
$("#toolbox-content-other").hide();
|
$("#toolbox-content-other").hide();
|
||||||
$("#toolbox-content-other-i18n").hide();
|
|
||||||
$(".add-buttons button").prop('disabled', false);
|
$(".add-buttons button").prop('disabled', false);
|
||||||
|
|
||||||
if (dump) {
|
if (dump) {
|
||||||
@@ -486,23 +422,14 @@ var editor = {
|
|||||||
$("#toolbox").find("button[data-action=right]").toggleClass('active', o.textAlign === 'right');
|
$("#toolbox").find("button[data-action=right]").toggleClass('active', o.textAlign === 'right');
|
||||||
$("#toolbox-textwidth").val(editor._px2mm(o.width).toFixed(2));
|
$("#toolbox-textwidth").val(editor._px2mm(o.width).toFixed(2));
|
||||||
$("#toolbox-textrotation").val((o.angle || 0.0).toFixed(1));
|
$("#toolbox-textrotation").val((o.angle || 0.0).toFixed(1));
|
||||||
}
|
if (o.type === "textarea") {
|
||||||
|
$("#toolbox-content").val(o.content);
|
||||||
if (o.type === "textarea" || o.type === "barcodearea") {
|
$("#toolbox-content-other").toggle($("#toolbox-content").val() === "other");
|
||||||
if (!o.content && o.type == "barcodearea") {
|
if (o.content === "other") {
|
||||||
o.content = "secret";
|
$("#toolbox-content-other").val(o.text);
|
||||||
}
|
} else {
|
||||||
$("#toolbox-content").val(o.content);
|
$("#toolbox-content-other").val("");
|
||||||
$("#toolbox-content-other").toggle($("#toolbox-content").val() === "other");
|
}
|
||||||
$("#toolbox-content-other-i18n").toggle($("#toolbox-content").val() === "other_i18n");
|
|
||||||
if (o.content === "other") {
|
|
||||||
$("#toolbox-content-other").val(o.text);
|
|
||||||
} else if (o.content === "other_i18n") {
|
|
||||||
$("#toolbox-content-other-i18n textarea").each(function () {
|
|
||||||
$(this).val(o.text_i18n[$(this).attr("lang")] || '');
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$("#toolbox-content-other").val("");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -534,20 +461,6 @@ var editor = {
|
|||||||
o.setScaleY(1);
|
o.setScaleY(1);
|
||||||
o.set('top', new_top)
|
o.set('top', new_top)
|
||||||
o.nowhitespace = $("#toolbox-qrwhitespace").prop("checked") || false;
|
o.nowhitespace = $("#toolbox-qrwhitespace").prop("checked") || false;
|
||||||
|
|
||||||
$("#toolbox-content-other").toggle($("#toolbox-content").val() === "other");
|
|
||||||
$("#toolbox-content-other-i18n").toggle($("#toolbox-content").val() === "other_i18n");
|
|
||||||
o.content = $("#toolbox-content").val();
|
|
||||||
if ($("#toolbox-content").val() === "other") {
|
|
||||||
o.text = $("#toolbox-content-other").val();
|
|
||||||
} else if ($("#toolbox-content").val() === "other_i18n") {
|
|
||||||
o.text_i18n = {}
|
|
||||||
$("#toolbox-content-other-i18n textarea").each(function () {
|
|
||||||
o.text_i18n[$(this).attr("lang")] = $(this).val();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
o.text = editor._get_text_sample($("#toolbox-content").val());
|
|
||||||
}
|
|
||||||
} else if (o.type === "imagearea") {
|
} else if (o.type === "imagearea") {
|
||||||
var new_w = editor._mm2px($("#toolbox-width").val());
|
var new_w = editor._mm2px($("#toolbox-width").val());
|
||||||
var new_h = editor._mm2px($("#toolbox-height").val());
|
var new_h = editor._mm2px($("#toolbox-height").val());
|
||||||
@@ -590,16 +503,9 @@ var editor = {
|
|||||||
o.downward = $("#toolbox").find("button[data-action=downward]").is('.active');
|
o.downward = $("#toolbox").find("button[data-action=downward]").is('.active');
|
||||||
o.rotate(parseFloat($("#toolbox-textrotation").val()));
|
o.rotate(parseFloat($("#toolbox-textrotation").val()));
|
||||||
$("#toolbox-content-other").toggle($("#toolbox-content").val() === "other");
|
$("#toolbox-content-other").toggle($("#toolbox-content").val() === "other");
|
||||||
$("#toolbox-content-other-i18n").toggle($("#toolbox-content").val() === "other_i18n");
|
|
||||||
o.content = $("#toolbox-content").val();
|
o.content = $("#toolbox-content").val();
|
||||||
if ($("#toolbox-content").val() === "other") {
|
if ($("#toolbox-content").val() === "other") {
|
||||||
o.setText($("#toolbox-content-other").val());
|
o.setText($("#toolbox-content-other").val());
|
||||||
} else if ($("#toolbox-content").val() === "other_i18n") {
|
|
||||||
o.text_i18n = {}
|
|
||||||
$("#toolbox-content-other-i18n textarea").each(function () {
|
|
||||||
o.text_i18n[$(this).attr("lang")] = $(this).val();
|
|
||||||
});
|
|
||||||
o.setText($("#toolbox-content-other-i18n textarea").first().val());
|
|
||||||
} else {
|
} else {
|
||||||
o.setText(editor._get_text_sample($("#toolbox-content").val()));
|
o.setText(editor._get_text_sample($("#toolbox-content").val()));
|
||||||
}
|
}
|
||||||
@@ -712,7 +618,6 @@ var editor = {
|
|||||||
lockUniScaling: true,
|
lockUniScaling: true,
|
||||||
fill: '#666',
|
fill: '#666',
|
||||||
content: $(this).attr("data-content"),
|
content: $(this).attr("data-content"),
|
||||||
text: '',
|
|
||||||
nowhitespace: true,
|
nowhitespace: true,
|
||||||
});
|
});
|
||||||
rect.setControlsVisibility({'mtr': false});
|
rect.setControlsVisibility({'mtr': false});
|
||||||
@@ -759,7 +664,6 @@ var editor = {
|
|||||||
editor._history_modification_in_progress = true;
|
editor._history_modification_in_progress = true;
|
||||||
var objs = [];
|
var objs = [];
|
||||||
for (var i in editor.clipboard) {
|
for (var i in editor.clipboard) {
|
||||||
editor.clipboard[i].page = editor.pdf_page_number;
|
|
||||||
objs.push(editor._add_from_data(editor.clipboard[i]));
|
objs.push(editor._add_from_data(editor.clipboard[i]));
|
||||||
}
|
}
|
||||||
editor.fabric.discardActiveObject();
|
editor.fabric.discardActiveObject();
|
||||||
@@ -825,11 +729,6 @@ var editor = {
|
|||||||
case 46: /* Delete */
|
case 46: /* Delete */
|
||||||
editor._delete();
|
editor._delete();
|
||||||
break;
|
break;
|
||||||
case 65: /* A */
|
|
||||||
if (e.ctrlKey) {
|
|
||||||
editor._selectAll();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 89: /* Y */
|
case 89: /* Y */
|
||||||
if (e.ctrlKey) {
|
if (e.ctrlKey) {
|
||||||
editor._redo();
|
editor._redo();
|
||||||
@@ -876,15 +775,6 @@ var editor = {
|
|||||||
editor.dirty = true;
|
editor.dirty = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
_selectAll: function () {
|
|
||||||
var group = new fabric.Group(editor.fabric.getObjects(), {
|
|
||||||
originX: 'center',
|
|
||||||
originY: 'center',
|
|
||||||
});
|
|
||||||
group.setCoords();
|
|
||||||
editor.fabric.setActiveGroup(group);
|
|
||||||
},
|
|
||||||
|
|
||||||
_undo: function undo() {
|
_undo: function undo() {
|
||||||
if (editor._history_pos < editor.history.length - 1) {
|
if (editor._history_pos < editor.history.length - 1) {
|
||||||
editor._history_modification_in_progress = true;
|
editor._history_modification_in_progress = true;
|
||||||
@@ -937,7 +827,6 @@ var editor = {
|
|||||||
d = editor.dump();
|
d = editor.dump();
|
||||||
editor.fabric.dispose();
|
editor.fabric.dispose();
|
||||||
editor._load_pdf(d);
|
editor._load_pdf(d);
|
||||||
$(".background-download-button").attr("href", url);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_source_show: function () {
|
_source_show: function () {
|
||||||
@@ -984,7 +873,7 @@ var editor = {
|
|||||||
editor.$fcv = $("#fabric-canvas");
|
editor.$fcv = $("#fabric-canvas");
|
||||||
editor.$cva = $("#editor-canvas-area");
|
editor.$cva = $("#editor-canvas-area");
|
||||||
editor._load_pdf();
|
editor._load_pdf();
|
||||||
$("#editor-add-qrcode, #editor-add-qrcode-lead, #editor-add-qrcode-other").click(editor._add_qrcode);
|
$("#editor-add-qrcode, #editor-add-qrcode-lead").click(editor._add_qrcode);
|
||||||
$("#editor-add-image").click(editor._add_imagearea);
|
$("#editor-add-image").click(editor._add_imagearea);
|
||||||
$("#editor-add-text").click(editor._add_text);
|
$("#editor-add-text").click(editor._add_text);
|
||||||
$("#editor-add-poweredby").click(function() {editor._add_poweredby("dark")});
|
$("#editor-add-poweredby").click(function() {editor._add_poweredby("dark")});
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ body {
|
|||||||
}
|
}
|
||||||
#toolbox[data-type] .position,
|
#toolbox[data-type] .position,
|
||||||
#toolbox[data-type=barcodearea] .squaresize,
|
#toolbox[data-type=barcodearea] .squaresize,
|
||||||
#toolbox[data-type=barcodearea] .textcontent,
|
|
||||||
#toolbox[data-type=imagearea] .rectsize,
|
#toolbox[data-type=imagearea] .rectsize,
|
||||||
#toolbox[data-type=imagearea] .imagecontent,
|
#toolbox[data-type=imagearea] .imagecontent,
|
||||||
#toolbox[data-type=poweredby] .poweredby,
|
#toolbox[data-type=poweredby] .poweredby,
|
||||||
@@ -70,10 +69,3 @@ body {
|
|||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
.panel-pdf-editor .panel-body {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
.panel-pdf-editor .panel-body .nav-pills {
|
|
||||||
padding: 15px;
|
|
||||||
background: #eee;
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user