stash
This commit is contained in:
parent
4787acd8eb
commit
67c7415c3b
6 changed files with 691 additions and 407 deletions
|
|
@ -12,6 +12,40 @@
|
|||
alternatives below.
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-lg-8">
|
||||
<div class="card h-100">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Label content</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row g-3">
|
||||
<div :class="v === 'value' ? 'col-12' : 'col-md-6'" v-for="v in baseVars" :key="v">
|
||||
<label class="form-label">{{ varLabel(v) }}</label>
|
||||
<textarea v-if="v === 'value'" class="form-control" rows="3"
|
||||
v-model="varValues[v]"
|
||||
placeholder="https://example.com/…"></textarea>
|
||||
<input v-else type="text" class="form-control" v-model="varValues[v]">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Calculated</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div v-for="v in derivedVars" :key="v" class="mb-2">
|
||||
<div class="small text-muted">{{ varLabel(v) }}</div>
|
||||
<div class="text-break">{{ fields[v] || "—" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="!usbSupported" class="row">
|
||||
<div class="col-lg-7">
|
||||
<div class="card">
|
||||
|
|
@ -19,13 +53,7 @@
|
|||
<h5 class="card-title mb-0">Label preview</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">QR code content</label>
|
||||
<input type="text" class="form-control" v-model="value"
|
||||
placeholder="https://example.com/…" autofocus>
|
||||
</div>
|
||||
|
||||
<div class="label-preview mb-3" v-show="selectedContent.qr || selectedContent.text">
|
||||
<div class="label-preview mb-3" v-show="selectedContent">
|
||||
<canvas ref="fallbackCanvas"></canvas>
|
||||
</div>
|
||||
|
||||
|
|
@ -67,13 +95,7 @@
|
|||
Connect a printer to preview and print a label.
|
||||
</p>
|
||||
<template v-else>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">QR code content</label>
|
||||
<input type="text" class="form-control" v-model="value"
|
||||
placeholder="https://example.com/…" autofocus>
|
||||
</div>
|
||||
|
||||
<div class="label-preview mb-3" v-show="selectedContent.qr || selectedContent.text">
|
||||
<div class="label-preview mb-3" v-show="selectedContent">
|
||||
<canvas ref="labelCanvas"></canvas>
|
||||
</div>
|
||||
|
||||
|
|
@ -149,8 +171,8 @@ import BaseLayout from "@/components/BaseLayout.vue";
|
|||
import LabelLayoutPreview from "@/components/LabelLayoutPreview.vue";
|
||||
|
||||
import {MultiPrinterBlob, canvasToBitmap, bitmapToCanvas} from "../../vendor/weblabel.js";
|
||||
import {buildLabelContent, buildLabelFields} from "@/label-content.js";
|
||||
import {LABEL_TEMPLATES, tapeFromStatus, drawLabel, drawFallbackLabel, templateContent} from "@/label-drawing.js";
|
||||
import {tapeFromStatus, drawLabel, drawFallbackLabel, buildLabelContent, buildLabelFields} from "@/label.js";
|
||||
import {LABEL_TEMPLATES, BASE_VARS, DERIVED_VARS, withDerivedVars, templateContent} from "@/label-layouts.js";
|
||||
|
||||
// Served verbatim from public/vendor/ rather than bundled: libweblabel.js's
|
||||
// own emscripten glue resolves its .wasm sibling relative to *its own*
|
||||
|
|
@ -189,7 +211,22 @@ export default {
|
|||
tape: null,
|
||||
labelBitmap: null,
|
||||
|
||||
value: buildLabelContent(this.prefill),
|
||||
// One input per *base* template variable (see label-layouts.js's BASE_VARS) - the
|
||||
// derived ones (itemUrl, itemHandle) are format strings calculated from these, not
|
||||
// typed directly, so they're only ever shown (see the `fields` computed below), never
|
||||
// stored here. Prefilled from the ?kind=…&… query params where
|
||||
// buildLabelContent/buildLabelFields have a value for them, editable from there so a
|
||||
// template needing e.g. userHandle isn't stuck depending on a prefill that never
|
||||
// arrives.
|
||||
varValues: {
|
||||
...Object.fromEntries(BASE_VARS.map(v => [v, ""])),
|
||||
value: buildLabelContent(this.prefill),
|
||||
// Defaults to wherever this page itself is being served from - editable since any
|
||||
// frontend can resolve any handle (see label-layouts.js's DERIVED_VARS.itemUrl),
|
||||
// so a label doesn't have to point back at this particular one.
|
||||
webdomain: window.location.origin,
|
||||
...buildLabelFields(this.prefill),
|
||||
},
|
||||
copies: 1,
|
||||
selectedTemplate: LABEL_TEMPLATES[0].id,
|
||||
|
||||
|
|
@ -200,11 +237,30 @@ export default {
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
// Named content fields the field-specific templates draw from, plus the free-text
|
||||
// `value` field the generic qr/qr-text/text templates use. A field this doesn't have
|
||||
// (rather than one that's merely empty) is what LabelLayoutPreview.vue greys out.
|
||||
// The base variables the "Label content" form renders an input for, and the derived ones
|
||||
// it instead calculates and lists read-only beside that form - plain passthroughs, but
|
||||
// keep the template from importing label-layouts.js just for these.
|
||||
baseVars() {
|
||||
return BASE_VARS;
|
||||
},
|
||||
derivedVars() {
|
||||
return Object.keys(DERIVED_VARS);
|
||||
},
|
||||
// Named content fields the templates draw from: the form's own base vars, plus every
|
||||
// DERIVED_VARS format string calculated live from those - so typing a userHandle and
|
||||
// itemId (whether by hand or via prefill) recalculates itemUrl/itemHandle the same way
|
||||
// either way. A blank/uncalculated value is dropped rather than passed through as an
|
||||
// empty string, so it reads as *absent* to templateIsAvailable/templateContent the same
|
||||
// way a prefill that never supplied it would - that's what LabelLayoutPreview.vue greys a
|
||||
// template's thumbnail out on.
|
||||
fields() {
|
||||
return {value: this.value, ...buildLabelFields(this.prefill)};
|
||||
const base = {};
|
||||
for (const v of BASE_VARS) {
|
||||
if (this.varValues[v]) {
|
||||
base[v] = this.varValues[v];
|
||||
}
|
||||
}
|
||||
return withDerivedVars(base);
|
||||
},
|
||||
currentTemplate() {
|
||||
return LABEL_TEMPLATES.find(t => t.id === this.selectedTemplate) || LABEL_TEMPLATES[0];
|
||||
|
|
@ -232,12 +288,15 @@ export default {
|
|||
},
|
||||
},
|
||||
watch: {
|
||||
value() {
|
||||
if (this.usbSupported) {
|
||||
this.redraw();
|
||||
} else {
|
||||
this.redrawFallback();
|
||||
}
|
||||
varValues: {
|
||||
handler() {
|
||||
if (this.usbSupported) {
|
||||
this.redraw();
|
||||
} else {
|
||||
this.redrawFallback();
|
||||
}
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
selectedTemplate() {
|
||||
if (this.usbSupported) {
|
||||
|
|
@ -258,6 +317,13 @@ export default {
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
// Turns a camelCase variable name (see label-layouts.js's KNOWN_VARS) into a form label,
|
||||
// e.g. "itemHandle" -> "Item Handle" - so adding a new template variable doesn't also
|
||||
// require hand-writing a label for it here.
|
||||
varLabel(v) {
|
||||
return v.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/^./, c => c.toUpperCase());
|
||||
},
|
||||
|
||||
async guard(fn) {
|
||||
this.error = null;
|
||||
this.busy = true;
|
||||
|
|
@ -326,7 +392,7 @@ export default {
|
|||
redraw() {
|
||||
this.labelBitmap = null;
|
||||
const content = this.selectedContent;
|
||||
if (!this.tape || (!content.qr && !content.text)) {
|
||||
if (!this.tape || !content) {
|
||||
return;
|
||||
}
|
||||
const canvas = this.$refs.labelCanvas;
|
||||
|
|
@ -350,7 +416,7 @@ export default {
|
|||
redrawFallback() {
|
||||
this.fallbackReady = false;
|
||||
const content = this.selectedContent;
|
||||
if (!content.qr && !content.text) {
|
||||
if (!content) {
|
||||
return;
|
||||
}
|
||||
const canvas = this.$refs.fallbackCanvas;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue