mirror of
https://github.com/sysadminsmedia/homebox.git
synced 2025-12-24 06:28:34 +01:00
add label generation api (#498)
* add label generation api * show location name on labels * add label scan page * dispose of code reader when navigating away from scan page * save label to png * implement code suggestions * fix label padding and margin * update swagger docs * add print from browser dialog Co-authored-by: fidoriel <49869342+fidoriel@users.noreply.github.com> * increase label description font weight * update documentation label file suffix * fix scanner components import * fix linting issues --------- Co-authored-by: fidoriel <49869342+fidoriel@users.noreply.github.com>
This commit is contained in:
125
frontend/components/global/LabelMaker.vue
Normal file
125
frontend/components/global/LabelMaker.vue
Normal file
@@ -0,0 +1,125 @@
|
||||
<script setup lang="ts">
|
||||
import { route } from "../../lib/api/base";
|
||||
import MdiPrinterPos from "~icons/mdi/printer-pos";
|
||||
import MdiFileDownload from "~icons/mdi/file-download";
|
||||
|
||||
const props = defineProps<{
|
||||
type: string;
|
||||
id: string;
|
||||
}>();
|
||||
|
||||
const pubApi = usePublicApi();
|
||||
const toast = useNotifier();
|
||||
|
||||
const { data: status } = useAsyncData(async () => {
|
||||
const { data, error } = await pubApi.status();
|
||||
if (error) {
|
||||
toast.error("Failed to load status");
|
||||
return;
|
||||
}
|
||||
|
||||
return data;
|
||||
});
|
||||
|
||||
const printModal = ref(false);
|
||||
const serverPrinting = ref(false);
|
||||
|
||||
function openPrint() {
|
||||
printModal.value = true;
|
||||
}
|
||||
|
||||
function browserPrint() {
|
||||
const printWindow = window.open(getLabelUrl(false), "popup=true");
|
||||
|
||||
if (printWindow !== null) {
|
||||
printWindow.onload = () => {
|
||||
printWindow.print();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function serverPrint() {
|
||||
serverPrinting.value = true;
|
||||
try {
|
||||
await fetch(getLabelUrl(true));
|
||||
} catch (err) {
|
||||
console.error("Failed to print labels:", err);
|
||||
serverPrinting.value = false;
|
||||
toast.error("Failed to print label");
|
||||
return;
|
||||
}
|
||||
|
||||
toast.success("Label printed");
|
||||
printModal.value = false;
|
||||
serverPrinting.value = false;
|
||||
}
|
||||
|
||||
function downloadLabel() {
|
||||
const link = document.createElement("a");
|
||||
link.download = `label-${props.id}.png`;
|
||||
link.href = getLabelUrl(false);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
|
||||
function getLabelUrl(print: boolean): string {
|
||||
const params = { print };
|
||||
|
||||
if (props.type === "item") {
|
||||
return route(`/labelmaker/item/${props.id}`, params);
|
||||
} else if (props.type === "location") {
|
||||
return route(`/labelmaker/location/${props.id}`, params);
|
||||
} else if (props.type === "asset") {
|
||||
return route(`/labelmaker/asset/${props.id}`, params);
|
||||
} else {
|
||||
throw new Error(`Unexpected labelmaker type ${props.type}`);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<BaseModal v-model="printModal">
|
||||
<template #title>{{ $t("components.global.label_maker.print") }}</template>
|
||||
<p>
|
||||
{{ $t("components.global.label_maker.confirm_description") }}
|
||||
</p>
|
||||
<img :src="getLabelUrl(false)" />
|
||||
<div class="modal-action">
|
||||
<BaseButton
|
||||
v-if="status?.labelPrinting || false"
|
||||
type="submit"
|
||||
:loading="serverPrinting"
|
||||
@click="serverPrint"
|
||||
>{{ $t("components.global.label_maker.server_print") }}</BaseButton
|
||||
>
|
||||
<BaseButton type="submit" @click="browserPrint">{{
|
||||
$t("components.global.label_maker.browser_print")
|
||||
}}</BaseButton>
|
||||
</div>
|
||||
</BaseModal>
|
||||
|
||||
<div class="dropdown dropdown-left">
|
||||
<slot>
|
||||
<label tabindex="0" class="btn btn-sm">
|
||||
{{ $t("components.global.label_maker.titles") }}
|
||||
</label>
|
||||
</slot>
|
||||
<ul class="dropdown-content menu compact rounded-box w-52 bg-base-100 shadow-lg">
|
||||
<li>
|
||||
<button @click="openPrint">
|
||||
<MdiPrinterPos name="mdi-printer-pos" class="mr-2" />
|
||||
{{ $t("components.global.label_maker.print") }}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button @click="downloadLabel">
|
||||
<MdiFileDownload name="mdi-file-download" class="mr-2" />
|
||||
{{ $t("components.global.label_maker.download") }}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user