1
0
mirror of https://github.com/MultiMote/niimblue synced 2026-01-19 19:37:11 +03:00

Add ZPL import via Labelary API

This commit is contained in:
MultiMote
2024-09-03 15:42:03 +03:00
parent fd4e525f4e
commit 16fd97d150
3 changed files with 86 additions and 3 deletions

View File

@@ -17,6 +17,7 @@
import BarcodeParamsPanel from "./BarcodeParamsControls.svelte";
import Dropdown from "bootstrap/js/dist/dropdown";
import { FileUtils } from "../utils/file_utils";
import ZplImportButton from "./ZplImportButton.svelte";
let htmlCanvas: HTMLCanvasElement;
let fabricCanvas: fabric.Canvas;
@@ -110,6 +111,25 @@
);
};
const zplImageReady = (img: Blob) => {
const reader = new FileReader();
reader.readAsDataURL(img);
reader.onload = (readerEvt: ProgressEvent<FileReader>) => {
if (readerEvt?.target?.result) {
fabric.Image.fromURL(readerEvt.target.result as string, (img: fabric.Image) => {
img.set({ left: 0, top: 0, snapAngle: 10 });
img.scaleToHeight(labelProps.size.width - 1).scaleToHeight(labelProps.size.height - 1);
fabricCanvas.add(img);
});
}
};
reader.onerror = (readerEvt: ProgressEvent<FileReader>) => {
console.error(readerEvt);
};
};
const onObjectPicked = (objectType: OjectType) => {
ImageEditorUtils.addObject(fabricCanvas, objectType);
};
@@ -245,9 +265,13 @@
<div class="btn-group btn-group-sm" role="group">
<button class="btn btn-secondary btn-sm" on:click={onLoadClicked}><FaIcon icon="folder-open" /></button>
<button class="btn btn-secondary dropdown-toggle px-1" data-bs-toggle="dropdown"> </button>
<button class="btn btn-secondary dropdown-toggle px-1" data-bs-toggle="dropdown" data-bs-auto-close="outside">
</button>
<div class="dropdown-menu px-2">
<button class="btn btn-secondary btn-sm" on:click={onImportClicked}>Import JSON</button>
<div class="d-flex gap-1 flex-wrap">
<button class="btn btn-secondary btn-sm" on:click={onImportClicked}>Import JSON</button>
<ZplImportButton {labelProps} onImageReady={zplImageReady} />
</div>
</div>
</div>

View File

@@ -0,0 +1,54 @@
<script lang="ts">
import type { LabelProps } from "../types";
import { FileUtils } from "../utils/file_utils";
import FaIcon from "./FaIcon.svelte";
export let labelProps: LabelProps;
export let onImageReady: (img: Blob) => void;
let state: "idle" | "processing" | "error" = "idle";
const onImportClicked = async () => {
const mmToInchCoeff = 25.4;
const dpmm = 8; // todo: may vary, make it configurable
const widthInches = labelProps.size.width / dpmm / mmToInchCoeff;
const heightInches = labelProps.size.height / dpmm / mmToInchCoeff;
const contents = await FileUtils.pickAndReadTextFile("zpl");
state = "processing";
try {
const response = await fetch(
`http://api.labelary.com/v1/printers/${dpmm}dpmm/labels/${widthInches}x${heightInches}/0/`,
{
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "image/png",
"X-Quality": "bitonal",
},
body: contents,
}
);
if (response.ok) {
const img = await response.blob();
onImageReady(img);
state = "idle";
} else {
state = "error";
}
} catch (e) {
state = "error";
console.error(e);
}
};
</script>
<button class="btn btn-secondary btn-sm" on:click={onImportClicked}
>Import ZPL
{#if state === "processing"}
<FaIcon icon="sync" params={{ classes: ["fa-spin"] }}></FaIcon>
{:else if state === "error"}
<FaIcon icon="warning" params={{ classes: ["text-warning"] }}></FaIcon>
{/if}
</button>

View File

@@ -18,7 +18,12 @@ export class FileUtils {
URL.revokeObjectURL(link.href);
}
/** Open file picker and return file contents */
/**
* Open file picker and return file contents
*
* fixme: never ends if dialog closed
*
* */
public static async pickAndReadTextFile(acceptExtension: string): Promise<string> {
return new Promise((resolve, reject) => {
const input: HTMLInputElement = document.createElement("input");