Files
lego-instructions-manager/app/templates/admin/labels/dymo.html
T

268 lines
13 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}Dymo Label Sheets - Admin{% endblock %}
{% block extra_css %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/labels-bricklink.css') }}">
{% endblock %}
{% block content %}
<div class="bl">
{% set section = 'labels' %}
{% set bar_sub = 'Dymo LabelWriter die-cut stock' %}
{% set crumbs = [{'name': 'My Labels', 'url': url_for('labels.index')}, {'name': 'Dymo sheets'}] %}
{% include 'admin/labels/_nav.html' %}
<form method="POST" action="{{ url_for('dymo.index') }}" id="dymoForm">
<input type="hidden" name="ids" value="{{ ids }}">
{# Same hidden marker as the tape page: it is how an unticked checkbox is
told apart from a page opened with no options at all. #}
<input type="hidden" name="_opts" value="1">
<input type="hidden" name="groups" value="{{ request.values.get('groups', '') }}">
<div class="row g-2 mt-0">
<div class="col-lg-4">
<div class="bl-panel">
<div class="bl-panel-head"><span>Label stock</span></div>
<div class="bl-panel-body">
<label class="fld">Loaded in the LabelWriter</label>
<select name="stock" class="w-100 mb-2" id="stockSelect">
{% for key, preset in stocks.items() %}
<option value="{{ key }}" {% if key == sheet.stock %}selected{% endif %}>{{ preset.name }}</option>
{% endfor %}
</select>
<div class="k mb-2" style="text-transform:none;">{{ stock.note }}</div>
<label class="fld">Labels per sticker</label>
<select name="layout" class="w-100 mb-2" id="layoutSelect">
{% for key, text in layouts %}
<option value="{{ key }}" {% if key == sheet.layout %}selected{% endif %}>{{ text }}</option>
{% endfor %}
</select>
<div class="k mb-2" style="text-transform:none;">
{{ stock.width_mm }} &times; {{ stock.height_mm }}mm fits
<strong>{{ per_sheet }}</strong> standard 40 &times; 15mm labels
({{ grid }}). A two-part drawer label is taller, so a mixed
run fits fewer.
</div>
<div class="row g-2">
<div class="col-6">
<label class="fld">Margin (mm)</label>
<input type="number" name="margin_mm" step="0.5" min="0" max="10"
class="w-100" value="{{ sheet.margin_mm }}">
</div>
<div class="col-6">
<label class="fld">Gap (mm)</label>
<input type="number" name="gap_mm" step="0.5" min="0" max="10"
class="w-100" value="{{ sheet.gap_mm }}">
</div>
<div class="col-6">
<label class="fld">Skip slots</label>
<input type="number" name="start_at" min="0" max="50"
class="w-100" value="{{ sheet.start_at }}">
</div>
<div class="col-6">
<label class="fld">Copies each</label>
<input type="number" name="copies" min="1" max="99"
class="w-100" value="{{ options.copies }}">
</div>
</div>
<hr class="my-2">
<label class="d-flex align-items-center gap-2" style="font-size:12px;">
<input type="checkbox" name="cut_guides" value="1"
{% if sheet.cut_guides %}checked{% endif %}>
Dashed cut guides
</label>
<label class="d-flex align-items-center gap-2" style="font-size:12px;">
<input type="checkbox" name="centre" value="1"
{% if sheet.centre %}checked{% endif %}>
Centre on the sticker
</label>
<label class="d-flex align-items-center gap-2" style="font-size:12px;">
<input type="checkbox" name="monochrome" value="1"
{% if sheet.monochrome %}checked{% endif %}>
Monochrome (thermal)
</label>
<div class="k mt-1" style="text-transform:none;">
A LabelWriter is direct thermal: black dots on white, no
colour and no greys of its own. Converting here means the
preview shows what will actually come out.
</div>
</div>
</div>
<div class="bl-panel">
<div class="bl-panel-head"><span>The labels themselves</span></div>
<div class="bl-panel-body">
<label class="fld">Size</label>
<select name="size_mode" class="w-100 mb-2" id="sizeSelect">
{% for key, text in size_modes %}
<option value="{{ key }}" {% if key == options.size_mode %}selected{% endif %}>{{ text }}</option>
{% endfor %}
</select>
<label class="d-flex align-items-center gap-2 mb-2" style="font-size:12px;">
<input type="checkbox" name="group_drawers" value="1"
{% if options.group_drawers %}checked{% endif %}>
Combine parts that share a drawer
</label>
<div class="row g-2">
<div class="col-6">
<label class="fld">Text size
<span class="num" id="fontOut">{{ '%.2f'|format(options.font_scale) }}&times;</span>
</label>
<input type="number" name="font_scale" step="0.05" min="0.5" max="2"
class="w-100" value="{{ options.font_scale }}" id="fontNum">
</div>
<div class="col-6">
<label class="fld">Image width %</label>
<input type="number" name="image_percent" min="0" max="60"
class="w-100" value="{{ options.image_percent }}">
</div>
<div class="col-12">
<input type="range" min="0.5" max="2" step="0.05" class="w-100"
value="{{ options.font_scale }}" id="fontRange">
<div class="d-flex gap-1 flex-wrap">
{% for preset, text in [(1.0, 'Normal'), (1.4, 'Large'), (2.0, 'Largest')] %}
<button type="button" class="bl-btn bl-btn-sm font-preset"
data-scale="{{ preset }}">{{ text }}</button>
{% endfor %}
</div>
<div class="k mt-1" style="text-transform:none;">
The name is sized first and the image gives way to it. The
whole name always prints, so once it spans the 40mm label
turning this up changes nothing &mdash; most names hit that by
about 1.4&times;. Untick <em>Part image</em> to give the text
the whole width.
</div>
</div>
<div class="col-6">
<label class="fld">Padding (mm)</label>
<input type="number" name="padding_mm" step="0.1" min="0" max="10"
class="w-100" value="{{ options.padding_mm }}">
</div>
<div class="col-6">
<label class="fld">Align</label>
<select name="align" class="w-100">
<option value="left" {% if options.align == 'left' %}selected{% endif %}>Left</option>
<option value="center" {% if options.align == 'center' %}selected{% endif %}>Centre</option>
</select>
</div>
</div>
</div>
</div>
<div class="bl-panel">
<div class="bl-panel-head"><span>Show on label</span></div>
<div class="bl-panel-body">
{% for value, text in field_options %}
<label class="d-flex align-items-center gap-2" style="font-size:12px;">
<input type="checkbox" name="fields" value="{{ value }}"
{% if value in options.fields %}checked{% endif %}> {{ text }}
</label>
{% endfor %}
</div>
</div>
</div>
<div class="col-lg-8">
<div class="bl-panel">
<div class="bl-panel-head"><span>Print</span></div>
<div class="bl-panel-body">
<div class="d-flex gap-2 flex-wrap align-items-center">
<button type="submit" formaction="{{ url_for('dymo.download_pdf') }}"
class="bl-btn bl-btn-go">
<i class="bi bi-file-pdf"></i>
Download PDF &mdash; {{ pages|length }} sticker{{ '' if pages|length == 1 else 's' }}
</button>
<button type="submit" class="bl-btn">Refresh preview</button>
<a href="{{ url_for('tape.index', ids=ids) }}" class="bl-btn">
<i class="bi bi-upc"></i> Tape instead
</a>
</div>
<div class="k mt-2" style="text-transform:none;">
Each PDF page is exactly {{ stock.width_mm }} &times; {{ stock.height_mm }}mm,
so print it with the Dymo driver set to this label and
<strong>scale 100% / Actual size</strong> &mdash; not "Fit to page",
which shrinks everything by a few percent and spoils the 40mm width.
The LabelWriter 4XL is USB, so LIM can't print to it over the
network the way it does the tape printer.
</div>
</div>
</div>
<div class="bl-panel">
<div class="bl-panel-head">
<span>Preview &mdash; {{ pages|length }} sticker{{ '' if pages|length == 1 else 's' }}
from {{ plan|length }} label{{ '' if plan|length == 1 else 's' }}</span>
<span class="num">{{ stock.width_mm }} &times; {{ stock.height_mm }}mm</span>
</div>
<div class="bl-panel-body">
{% if not options.fields %}
<div class="mb-2"><span class="bl-tag warn">Nothing selected</span>
Every field is unticked, so the labels will print blank.</div>
{% endif %}
{% for page in pages[:6] %}
<div class="mb-3">
<div class="k mb-1" style="text-transform:none;">
Sticker {{ loop.index }} of {{ pages|length }} &middot;
{{ page | rejectattr('blank') | list | length }} label{{ '' if page|length == 1 else 's' }}
</div>
<img style="border:1px solid #c9d3dd;background:#fff;max-width:100%;"
alt="Dymo sticker {{ loop.index }}"
src="{{ url_for('dymo.preview', page=loop.index, **query) }}">
</div>
{% endfor %}
{% if pages|length > 6 %}
<div class="k" style="text-transform:none;">
Showing the first 6 of {{ pages|length }}. All of them are in the PDF.
</div>
{% endif %}
<div class="k mt-2" style="text-transform:none;">
300 dpi, the LabelWriter's native resolution. Drawn by the same
code as the tape labels, so a drawer label is the same
{{ '%.0f'|format(40) }} &times; 15mm sticker whichever printer makes it.
Cut along the dashed lines.
</div>
</div>
</div>
</div>
</div>
</form>
</div>
{% endblock %}
{% block extra_js %}
<script>
// Changing the stock, the grid or the label size re-renders the sheet.
['stockSelect', 'layoutSelect', 'sizeSelect'].forEach(id => {
document.getElementById(id)?.addEventListener('change',
() => document.getElementById('dymoForm').submit());
});
// Text size: slider, box and presets all drive the one value.
(function () {
const num = document.getElementById('fontNum');
const range = document.getElementById('fontRange');
const out = document.getElementById('fontOut');
if (!num || !range) { return; }
const show = v => { if (out) { out.textContent = Number(v).toFixed(2) + '×'; } };
num.addEventListener('input', () => { range.value = num.value; show(num.value); });
range.addEventListener('input', () => { num.value = range.value; show(range.value); });
range.addEventListener('change', () => document.getElementById('dymoForm').submit());
document.querySelectorAll('.font-preset').forEach(btn => {
btn.addEventListener('click', () => {
num.value = range.value = btn.dataset.scale;
show(btn.dataset.scale);
document.getElementById('dymoForm').submit();
});
});
})();
</script>
{% endblock %}