tantee-nuxt-commons 0.0.167 → 0.0.169
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.json +1 -1
- package/dist/runtime/components/Alert.vue +1 -0
- package/dist/runtime/components/form/ActionPad.vue +1 -1
- package/dist/runtime/components/form/Dialog.vue +1 -1
- package/dist/runtime/components/form/EditPad.vue +1 -1
- package/dist/runtime/components/form/File.vue +126 -189
- package/dist/runtime/components/form/Iterator.vue +0 -2
- package/dist/runtime/components/form/Pad.vue +71 -2
- package/dist/runtime/components/form/SignPad.vue +139 -131
- package/dist/runtime/components/form/images/Field.vue +165 -185
- package/dist/runtime/components/label/DateCount.vue +117 -13
- package/dist/runtime/components/pdf/View.vue +42 -32
- package/dist/runtime/composables/document/templateFormTable.js +4 -1
- package/package.json +1 -1
- package/dist/runtime/composables/assetFile.d.ts +0 -31
- package/dist/runtime/composables/assetFile.js +0 -134
|
@@ -15,12 +15,12 @@ interface Props extends /* @vue-ignore */ InstanceType<typeof PDF['$props']> {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
const props = withDefaults(defineProps<Props>(), {
|
|
18
|
-
base64String:
|
|
19
|
-
title:
|
|
20
|
-
fileName:
|
|
18
|
+
base64String: '',
|
|
19
|
+
title: '',
|
|
20
|
+
fileName: '',
|
|
21
21
|
disabled: false,
|
|
22
22
|
isPrint: false,
|
|
23
|
-
showBackToTopBtn: false
|
|
23
|
+
showBackToTopBtn: false,
|
|
24
24
|
})
|
|
25
25
|
|
|
26
26
|
const emit = defineEmits(['closeDialog'])
|
|
@@ -33,25 +33,34 @@ const generateUniqueId = (): string => {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
const downloadPdf = (): void => {
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
try {
|
|
37
|
+
if (!props.base64String) alert?.addAlert({ message: 'No Base64 provided', alertType: 'error' })
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
byteArray
|
|
41
|
-
}
|
|
39
|
+
const byteString = atob(props.base64String || '')
|
|
40
|
+
const byteArray = new Uint8Array(byteString.length)
|
|
42
41
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
42
|
+
for (let i = 0; i < byteString.length; i++) {
|
|
43
|
+
byteArray[i] = byteString.charCodeAt(i)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const blob = new Blob([byteArray], { type: 'application/pdf' })
|
|
47
|
+
const link = URL.createObjectURL(blob)
|
|
48
|
+
const anchorElement = document.createElement('a')
|
|
49
|
+
anchorElement.style.display = 'none'
|
|
50
|
+
anchorElement.href = link
|
|
51
|
+
anchorElement.download = `${generateUniqueId()}.pdf`
|
|
52
|
+
|
|
53
|
+
document.body.appendChild(anchorElement)
|
|
54
|
+
anchorElement.click()
|
|
55
|
+
URL.revokeObjectURL(link)
|
|
56
|
+
document.body.removeChild(anchorElement)
|
|
57
|
+
base64.value = ''
|
|
58
|
+
|
|
59
|
+
alert?.addAlert({ message: 'Download success', alertType: 'success' })
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
alert?.addAlert({ message: `Download unsuccess : ${error}`, alertType: 'error' })
|
|
63
|
+
}
|
|
55
64
|
}
|
|
56
65
|
|
|
57
66
|
const printPdf = () => {
|
|
@@ -60,7 +69,7 @@ const printPdf = () => {
|
|
|
60
69
|
type: 'pdf',
|
|
61
70
|
base64: true,
|
|
62
71
|
onPrintDialogClose: endLoadPdf,
|
|
63
|
-
onError: (error
|
|
72
|
+
onError: (error) => {
|
|
64
73
|
alert?.addAlert({ message: error, alertType: 'error' })
|
|
65
74
|
},
|
|
66
75
|
})
|
|
@@ -73,18 +82,19 @@ const endLoadPdf = () => {
|
|
|
73
82
|
}
|
|
74
83
|
|
|
75
84
|
const isMobile = () => {
|
|
76
|
-
return /Android|Mobi|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Macintosh/i.test(navigator.userAgent)
|
|
85
|
+
return /Android|Mobi|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Macintosh/i.test(navigator.userAgent)
|
|
77
86
|
}
|
|
78
87
|
|
|
79
88
|
const checkMobileAndPrint = computed(() => {
|
|
80
|
-
return !isMobile() && props.isPrint
|
|
81
|
-
})
|
|
89
|
+
return !isMobile() && props.isPrint
|
|
90
|
+
})
|
|
82
91
|
|
|
83
92
|
const setWidthPdf = computed(() => {
|
|
84
93
|
if (isMobile()) {
|
|
85
|
-
return
|
|
86
|
-
}
|
|
87
|
-
|
|
94
|
+
return '100%'
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
return '100dvh'
|
|
88
98
|
}
|
|
89
99
|
})
|
|
90
100
|
</script>
|
|
@@ -114,10 +124,10 @@ const setWidthPdf = computed(() => {
|
|
|
114
124
|
</v-toolbar>
|
|
115
125
|
<v-card-text class="justify-center h-screen">
|
|
116
126
|
<PDF
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
127
|
+
v-bind="$attrs"
|
|
128
|
+
:pdf-width="setWidthPdf"
|
|
129
|
+
:src="base64"
|
|
130
|
+
:show-back-to-top-btn="props.showBackToTopBtn"
|
|
121
131
|
/>
|
|
122
132
|
</v-card-text>
|
|
123
133
|
</v-card>
|
|
@@ -34,13 +34,16 @@ function guessWidth(width) {
|
|
|
34
34
|
export function processTemplateFormTable(item, parentTemplates, dataVariable) {
|
|
35
35
|
let tableOptions = Object.assign({ title: item.inputLabel || "", formTemplate: "" }, item.inputOptions);
|
|
36
36
|
let tableHeader = tableOptions.headers || [];
|
|
37
|
-
if (!tableHeader.some((h) => h.key === "action")) tableHeader.push({ title: "Action", key: "action", width: "100px" });
|
|
38
37
|
let tableItemTemplate = "";
|
|
39
38
|
tableHeader.forEach((h) => {
|
|
40
39
|
if (h.template) {
|
|
41
40
|
tableItemTemplate += `\r
|
|
42
41
|
<template #item.${h.key}="props">${h.template}</template>`;
|
|
42
|
+
} else {
|
|
43
|
+
tableItemTemplate += `\r
|
|
44
|
+
<template #item.${h.key}="props">{{autoSanitizedDisplay(props.item.${h.key})}}</template>`;
|
|
43
45
|
}
|
|
44
46
|
});
|
|
47
|
+
if (!tableHeader.some((h) => h.key === "action")) tableHeader.push({ title: "Action", key: "action", width: "100px" });
|
|
45
48
|
return processDefaultTemplate(item, `<template #form="{data,rules}">${useDocumentTemplate(tableOptions.formTemplate)}</template>${tableItemTemplate}`, `title="${tableOptions.title}" :headers='${escapeObjectForInlineBinding(tableHeader)}'`, void 0, dataVariable);
|
|
46
49
|
}
|
package/package.json
CHANGED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/** Core format you wanted to standardize around */
|
|
2
|
-
export interface Base64String {
|
|
3
|
-
base64String?: string;
|
|
4
|
-
}
|
|
5
|
-
export interface Base64Asset extends Base64String {
|
|
6
|
-
id?: number;
|
|
7
|
-
}
|
|
8
|
-
export interface Base64File extends Base64Asset {
|
|
9
|
-
/** Display or server filename; when converting from a File, we use File.name */
|
|
10
|
-
fileName: string;
|
|
11
|
-
originalFileName?: string;
|
|
12
|
-
/** Parsed or inferred MIME type */
|
|
13
|
-
fileType?: string;
|
|
14
|
-
}
|
|
15
|
-
export interface Base64Image {
|
|
16
|
-
imageData: Base64Asset;
|
|
17
|
-
imageTitle?: string;
|
|
18
|
-
imageProps?: Record<string, unknown>;
|
|
19
|
-
}
|
|
20
|
-
/** Ensure we have a well-formed data URL; if raw base64 is provided, wrap it */
|
|
21
|
-
declare function ensureDataUrl(base64Data: string, contentType?: string): string;
|
|
22
|
-
export declare const useAssetFile: () => {
|
|
23
|
-
hydrateAssetFile: <T extends Base64Asset>(assetFile: T) => Promise<T>;
|
|
24
|
-
base64ToFile: (base64Data: string, filename: string, defaultContentType?: string) => File | undefined;
|
|
25
|
-
fileToBase64: (file: File, maxFileSizeMB?: number) => Promise<Base64File>;
|
|
26
|
-
fileToBase64String: (file: File, maxFileSizeMB?: number) => Promise<Base64String>;
|
|
27
|
-
downloadBase64File: (base64Data: string, filename: string) => void;
|
|
28
|
-
downloadAsset: (input: string | Base64File | Base64Asset, filename?: string, defaultContentType?: string) => void;
|
|
29
|
-
ensureDataUrl: typeof ensureDataUrl;
|
|
30
|
-
};
|
|
31
|
-
export {};
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import { useGraphQlOperation } from "./graphqlOperation.js";
|
|
2
|
-
const DATA_URL_RE = /^data:([^;]+);base64,(.+)$/i;
|
|
3
|
-
function parseDataUrl(input) {
|
|
4
|
-
const match = input.match(DATA_URL_RE);
|
|
5
|
-
if (!match) return null;
|
|
6
|
-
const [, contentType, payload] = match;
|
|
7
|
-
return { contentType, payload };
|
|
8
|
-
}
|
|
9
|
-
function base64ToBytes(base64Payload) {
|
|
10
|
-
const normalized = base64Payload.replace(/-/g, "+").replace(/_/g, "/");
|
|
11
|
-
const binaryStr = atob(normalized);
|
|
12
|
-
const len = binaryStr.length;
|
|
13
|
-
const bytes = new Uint8Array(len);
|
|
14
|
-
const CHUNK = 32768;
|
|
15
|
-
for (let i = 0; i < len; i += CHUNK) {
|
|
16
|
-
const end = Math.min(i + CHUNK, len);
|
|
17
|
-
for (let j = i; j < end; j++) {
|
|
18
|
-
bytes[j] = binaryStr.charCodeAt(j);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return bytes;
|
|
22
|
-
}
|
|
23
|
-
function bytesToFile(bytes, filename, contentType) {
|
|
24
|
-
try {
|
|
25
|
-
return new File([bytes], filename, { type: contentType });
|
|
26
|
-
} catch {
|
|
27
|
-
return new Blob([bytes], { type: contentType });
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
function ensureDataUrl(base64Data, contentType = "application/octet-stream") {
|
|
31
|
-
if (DATA_URL_RE.test(base64Data)) return base64Data;
|
|
32
|
-
return `data:${contentType};base64,${base64Data}`;
|
|
33
|
-
}
|
|
34
|
-
function extensionFromMime(mime) {
|
|
35
|
-
const map = {
|
|
36
|
-
"image/png": "png",
|
|
37
|
-
"image/jpeg": "jpg",
|
|
38
|
-
"image/jpg": "jpg",
|
|
39
|
-
"image/gif": "gif",
|
|
40
|
-
"image/webp": "webp",
|
|
41
|
-
"application/pdf": "pdf",
|
|
42
|
-
"text/plain": "txt"
|
|
43
|
-
};
|
|
44
|
-
return map[mime];
|
|
45
|
-
}
|
|
46
|
-
export const useAssetFile = () => {
|
|
47
|
-
async function hydrateAssetFile(assetFile) {
|
|
48
|
-
if (!assetFile?.base64String && assetFile?.id != null) {
|
|
49
|
-
const result = await useGraphQlOperation(
|
|
50
|
-
"Query",
|
|
51
|
-
"assetFileById",
|
|
52
|
-
["id", "base64String"],
|
|
53
|
-
{ id: assetFile.id },
|
|
54
|
-
false
|
|
55
|
-
);
|
|
56
|
-
if (result?.base64String) assetFile.base64String = result.base64String;
|
|
57
|
-
}
|
|
58
|
-
return assetFile;
|
|
59
|
-
}
|
|
60
|
-
function base64ToFile(base64Data, filename, defaultContentType = "application/octet-stream") {
|
|
61
|
-
try {
|
|
62
|
-
const parsed = parseDataUrl(base64Data);
|
|
63
|
-
const contentType = parsed?.contentType ?? defaultContentType;
|
|
64
|
-
const payload = parsed?.payload ?? base64Data;
|
|
65
|
-
const bytes = base64ToBytes(payload);
|
|
66
|
-
return bytesToFile(bytes, filename, contentType);
|
|
67
|
-
} catch (error) {
|
|
68
|
-
console.error("Invalid base64 data", error);
|
|
69
|
-
return void 0;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
function fileToBase64(file, maxFileSizeMB = 5) {
|
|
73
|
-
const maxSize = maxFileSizeMB * 1048576;
|
|
74
|
-
return new Promise((resolve, reject) => {
|
|
75
|
-
if (file.size > maxSize) {
|
|
76
|
-
reject(`File (${file.name}) size exceeds the ${maxFileSizeMB} MB limit.`);
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
const reader = new FileReader();
|
|
80
|
-
reader.onload = (event) => {
|
|
81
|
-
const dataUrl = event.target?.result;
|
|
82
|
-
resolve({
|
|
83
|
-
fileName: file.name,
|
|
84
|
-
originalFileName: file.name,
|
|
85
|
-
base64String: dataUrl,
|
|
86
|
-
fileType: file.type || parseDataUrl(dataUrl)?.contentType
|
|
87
|
-
});
|
|
88
|
-
};
|
|
89
|
-
reader.onerror = reject;
|
|
90
|
-
reader.readAsDataURL(file);
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
async function fileToBase64String(file, maxFileSizeMB = 5) {
|
|
94
|
-
const res = await fileToBase64(file, maxFileSizeMB);
|
|
95
|
-
return { base64String: res.base64String };
|
|
96
|
-
}
|
|
97
|
-
function downloadBase64File(base64Data, filename) {
|
|
98
|
-
const file = base64ToFile(base64Data, filename);
|
|
99
|
-
if (!file) return;
|
|
100
|
-
const url = URL.createObjectURL(file);
|
|
101
|
-
const link = document.createElement("a");
|
|
102
|
-
link.href = url;
|
|
103
|
-
link.download = filename;
|
|
104
|
-
document.body.appendChild(link);
|
|
105
|
-
link.click();
|
|
106
|
-
document.body.removeChild(link);
|
|
107
|
-
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
108
|
-
}
|
|
109
|
-
function downloadAsset(input, filename, defaultContentType = "application/octet-stream") {
|
|
110
|
-
let base64 = typeof input === "string" ? input : input.base64String;
|
|
111
|
-
if (!base64) return;
|
|
112
|
-
if (!filename) {
|
|
113
|
-
const parsed2 = parseDataUrl(base64);
|
|
114
|
-
const ext = parsed2 ? extensionFromMime(parsed2.contentType) : void 0;
|
|
115
|
-
filename = typeof input !== "string" && input.fileName || `download${ext ? "." + ext : ""}`;
|
|
116
|
-
}
|
|
117
|
-
const parsed = parseDataUrl(base64);
|
|
118
|
-
if (!parsed) {
|
|
119
|
-
base64 = ensureDataUrl(base64, defaultContentType);
|
|
120
|
-
}
|
|
121
|
-
downloadBase64File(base64, filename);
|
|
122
|
-
}
|
|
123
|
-
return {
|
|
124
|
-
// core
|
|
125
|
-
hydrateAssetFile,
|
|
126
|
-
base64ToFile,
|
|
127
|
-
fileToBase64,
|
|
128
|
-
fileToBase64String,
|
|
129
|
-
downloadBase64File,
|
|
130
|
-
downloadAsset,
|
|
131
|
-
// helpers (exported in case you want them elsewhere)
|
|
132
|
-
ensureDataUrl
|
|
133
|
-
};
|
|
134
|
-
};
|