From de551f740d6530757a45690683f28b29abcaa29e Mon Sep 17 00:00:00 2001 From: Muhammed Mustafa Date: Tue, 7 Nov 2023 10:42:15 +0000 Subject: [PATCH 01/16] feat: Added barcode download btn --- .../virtual-cell/barcode/Barcode.vue | 7 +- .../virtual-cell/barcode/JsBarcodeWrapper.vue | 108 ++++++++++++++++-- packages/nc-gui/lang/en.json | 1 + 3 files changed, 103 insertions(+), 13 deletions(-) diff --git a/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue b/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue index 502a8076d9..2289d84c69 100644 --- a/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue +++ b/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue @@ -46,7 +46,12 @@ const rowHeight = inject(RowHeightInj, ref(undefined)) :footer="null" @ok="handleModalOkClick" > - +
() +const barcodeSvgRef = ref() const errorForCurrentInput = ref(false) const generate = () => { @@ -34,6 +35,79 @@ const generate = () => { } } +function copyStylesInline(destinationNode: any, sourceNode: any) { + const containerElements = ['svg', 'g'] + for (let cd = 0; cd < destinationNode.childNodes.length; cd++) { + const child = destinationNode.childNodes[cd] + if (containerElements.includes(child.tagName)) { + copyStylesInline(child, sourceNode.childNodes[cd]) + continue + } + + const style = sourceNode.childNodes[cd].currentStyle || window.getComputedStyle(sourceNode.childNodes[cd]) + if (style === 'undefined' || style == null) continue + for (let st = 0; st < style.length; st++) { + child.style.setProperty(style[st], style.getPropertyValue(style[st])) + } + } +} + +function triggerDownload(imgURI: string, fileName: string) { + const evt = new MouseEvent('click', { + view: window, + bubbles: false, + cancelable: true, + }) + const a = document.createElement('a') + a.setAttribute('download', fileName) + a.setAttribute('href', imgURI) + a.setAttribute('target', '_blank') + a.dispatchEvent(evt) +} + +function _downloadSvg(svg: SVGGraphicsElement, fileName: string) { + const copy = svg.cloneNode(true) + + copyStylesInline(copy, svg) + + const canvas = document.createElement('canvas') + const bbox = svg.getBBox() + canvas.width = bbox.width + canvas.height = bbox.height + + const ctx = canvas.getContext('2d')! + ctx.clearRect(0, 0, bbox.width, bbox.height) + + const data = new XMLSerializer().serializeToString(copy) + const DOMURL = window.URL || window.webkitURL || window + const img = new Image() + const svgBlob = new Blob([data], { type: 'image/svg+xml;charset=utf-8' }) + const url = DOMURL.createObjectURL(svgBlob) + + img.onload = function () { + ctx.drawImage(img, 0, 0) + DOMURL.revokeObjectURL(url) + if (typeof navigator !== 'undefined' && navigator.msSaveOrOpenBlob) { + const blob = canvas.msToBlob() + navigator.msSaveOrOpenBlob(blob, fileName) + } else { + const imgURI = canvas.toDataURL('image/png').replace('image/png', 'image/octet-stream') + triggerDownload(imgURI, fileName) + } + console.log(canvas) + + // TODO: Somehow canvas dom element is getting deleted + // document.removeChild(canvas) + } + img.src = url +} + +const downloadSvg = () => { + if (!barcodeSvgRef.value) return + + _downloadSvg(barcodeSvgRef.value, `${props.barcodeValue}.png`) +} + const onBarcodeClick = (ev: MouseEvent) => { if (isGallery.value) return ev.stopPropagation() @@ -45,15 +119,25 @@ onMounted(generate) diff --git a/packages/nc-gui/lang/en.json b/packages/nc-gui/lang/en.json index 3eb2933c86..09d44d2da6 100644 --- a/packages/nc-gui/lang/en.json +++ b/packages/nc-gui/lang/en.json @@ -444,6 +444,7 @@ "inUI": "in UI Dashboard", "projectSettings": "Base Settings", "clickToHide": "Click to hide", + "clickToDownload": "Click to download", "forRole": "for role", "searchUsers": "Search Users", "superAdmin": "Super Admin", From 851d8492e71943483c021b51598ae8d16c90da91 Mon Sep 17 00:00:00 2001 From: Muhammed Mustafa Date: Tue, 7 Nov 2023 10:42:15 +0000 Subject: [PATCH 02/16] fix: Hide barcode box when there is too many char error --- packages/nc-gui/components/virtual-cell/barcode/Barcode.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue b/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue index 2289d84c69..2c27509ecf 100644 --- a/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue +++ b/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue @@ -54,6 +54,7 @@ const rowHeight = inject(RowHeightInj, ref(undefined)) />
import JsBarcode from 'jsbarcode' import { IsGalleryInj, onMounted } from '#imports' +import { downloadSvg as _downloadSvg } from '~/utils/svgToPng' const props = defineProps({ barcodeValue: { type: String, required: true }, @@ -35,73 +36,6 @@ const generate = () => { } } -function copyStylesInline(destinationNode: any, sourceNode: any) { - const containerElements = ['svg', 'g'] - for (let cd = 0; cd < destinationNode.childNodes.length; cd++) { - const child = destinationNode.childNodes[cd] - if (containerElements.includes(child.tagName)) { - copyStylesInline(child, sourceNode.childNodes[cd]) - continue - } - - const style = sourceNode.childNodes[cd].currentStyle || window.getComputedStyle(sourceNode.childNodes[cd]) - if (style === 'undefined' || style == null) continue - for (let st = 0; st < style.length; st++) { - child.style.setProperty(style[st], style.getPropertyValue(style[st])) - } - } -} - -function triggerDownload(imgURI: string, fileName: string) { - const evt = new MouseEvent('click', { - view: window, - bubbles: false, - cancelable: true, - }) - const a = document.createElement('a') - a.setAttribute('download', fileName) - a.setAttribute('href', imgURI) - a.setAttribute('target', '_blank') - a.dispatchEvent(evt) -} - -function _downloadSvg(svg: SVGGraphicsElement, fileName: string) { - const copy = svg.cloneNode(true) - - copyStylesInline(copy, svg) - - const canvas = document.createElement('canvas') - const bbox = svg.getBBox() - canvas.width = bbox.width - canvas.height = bbox.height - - const ctx = canvas.getContext('2d')! - ctx.clearRect(0, 0, bbox.width, bbox.height) - - const data = new XMLSerializer().serializeToString(copy) - const DOMURL = window.URL || window.webkitURL || window - const img = new Image() - const svgBlob = new Blob([data], { type: 'image/svg+xml;charset=utf-8' }) - const url = DOMURL.createObjectURL(svgBlob) - - img.onload = function () { - ctx.drawImage(img, 0, 0) - DOMURL.revokeObjectURL(url) - if (typeof navigator !== 'undefined' && navigator.msSaveOrOpenBlob) { - const blob = canvas.msToBlob() - navigator.msSaveOrOpenBlob(blob, fileName) - } else { - const imgURI = canvas.toDataURL('image/png').replace('image/png', 'image/octet-stream') - triggerDownload(imgURI, fileName) - } - console.log(canvas) - - // TODO: Somehow canvas dom element is getting deleted - // document.removeChild(canvas) - } - img.src = url -} - const downloadSvg = () => { if (!barcodeSvgRef.value) return diff --git a/packages/nc-gui/utils/svgToPng.ts b/packages/nc-gui/utils/svgToPng.ts new file mode 100644 index 0000000000..a98a1c2862 --- /dev/null +++ b/packages/nc-gui/utils/svgToPng.ts @@ -0,0 +1,68 @@ +function copyStylesInline(destinationNode: any, sourceNode: any) { + const containerElements = ['svg', 'g'] + for (let cd = 0; cd < destinationNode.childNodes.length; cd++) { + const child = destinationNode.childNodes[cd] + if (containerElements.includes(child.tagName)) { + copyStylesInline(child, sourceNode.childNodes[cd]) + continue + } + + const style = sourceNode.childNodes[cd].currentStyle || window.getComputedStyle(sourceNode.childNodes[cd]) + if (style === 'undefined' || style == null) continue + for (let st = 0; st < style.length; st++) { + child.style.setProperty(style[st], style.getPropertyValue(style[st])) + } + } +} + +function triggerDownload(imgURI: string, fileName: string) { + const evt = new MouseEvent('click', { + view: window, + bubbles: false, + cancelable: true, + }) + const a = document.createElement('a') + a.setAttribute('download', fileName) + a.setAttribute('href', imgURI) + a.setAttribute('target', '_blank') + a.dispatchEvent(evt) +} + +function downloadSvg(svg: SVGGraphicsElement, fileName: string) { + const copy = svg.cloneNode(true) + + copyStylesInline(copy, svg) + + const canvas = document.createElement('canvas') + const bbox = svg.getBBox() + canvas.width = bbox.width + canvas.height = bbox.height + + const ctx = canvas.getContext('2d')! + ctx.clearRect(0, 0, bbox.width, bbox.height) + + const data = new XMLSerializer().serializeToString(copy) + const DOMURL = window.URL || window.webkitURL || window + const img = new Image() + const svgBlob = new Blob([data], { type: 'image/svg+xml;charset=utf-8' }) + const url = DOMURL.createObjectURL(svgBlob) + + img.onload = function () { + ctx.drawImage(img, 0, 0) + DOMURL.revokeObjectURL(url) + if (typeof navigator !== 'undefined' && navigator.msSaveOrOpenBlob) { + const blob = canvas.msToBlob() + navigator.msSaveOrOpenBlob(blob, fileName) + } else { + const imgURI = canvas.toDataURL('image/png').replace('image/png', 'image/octet-stream') + triggerDownload(imgURI, fileName) + } + console.log(canvas) + + // TODO: Somehow canvas dom element is getting deleted + // document.removeChild(canvas) + } + img.src = url +} + +export { downloadSvg } From 97fed6fe29db99e6ec47532c50662d89b07d409a Mon Sep 17 00:00:00 2001 From: Muhammed Mustafa Date: Tue, 7 Nov 2023 10:42:15 +0000 Subject: [PATCH 04/16] fix: Added download button to qrcode cell --- .../nc-gui/components/virtual-cell/QrCode.vue | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/nc-gui/components/virtual-cell/QrCode.vue b/packages/nc-gui/components/virtual-cell/QrCode.vue index 9ce66087e3..9dba2538ff 100644 --- a/packages/nc-gui/components/virtual-cell/QrCode.vue +++ b/packages/nc-gui/components/virtual-cell/QrCode.vue @@ -59,8 +59,20 @@ const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning } = us @ok="handleModalOkClick" > From d4205e8c7170f506f11c571dccdbc8a73ad11cfb Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Tue, 7 Nov 2023 10:42:15 +0000 Subject: [PATCH 05/16] fix: barcode i18n error text --- packages/nc-gui/lang/en.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/nc-gui/lang/en.json b/packages/nc-gui/lang/en.json index 09d44d2da6..ec83115482 100644 --- a/packages/nc-gui/lang/en.json +++ b/packages/nc-gui/lang/en.json @@ -1010,7 +1010,8 @@ }, "nonEditableFields": { "computedFieldUnableToClear": "Warning: Computed field - unable to clear text", - "qrFieldsCannotBeDirectlyChanged": "Warning: QR fields cannot be directly changed." + "qrFieldsCannotBeDirectlyChanged": "Warning: QR fields cannot be directly changed.", + "barcodeFieldsCannotBeDirectlyChanged": "Warning: Barcode fields cannot be directly changed." }, "duplicateProject": "Are you sure you want to duplicate the base?", "duplicateTable": "Are you sure you want to duplicate the table?" From 032c60d7b6df6e6fa5b91a6f60bf72eff3206048 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 7 Nov 2023 21:05:20 +0000 Subject: [PATCH 06/16] fix: import nuxt composables from #imports --- packages/nc-gui/components/account/License.vue | 2 +- packages/nc-gui/components/dashboard/TreeView/ProjectNode.vue | 2 +- packages/nc-gui/components/dashboard/TreeView/TableList.vue | 2 +- packages/nc-gui/components/dashboard/TreeView/TableNode.vue | 2 +- packages/nc-gui/components/dashboard/TreeView/index.vue | 2 +- packages/nc-gui/components/dlg/QuickImport.vue | 2 +- packages/nc-gui/components/workspace/ProjectList.vue | 2 +- packages/nc-gui/composables/useGlobal/actions.ts | 2 +- packages/nc-gui/composables/useGlobal/index.ts | 2 +- packages/nc-gui/helpers/parsers/JSONUrlTemplateAdapter.ts | 2 +- packages/nc-gui/plugins/state.ts | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/nc-gui/components/account/License.vue b/packages/nc-gui/components/account/License.vue index e4d780bc17..cfd1f684b4 100644 --- a/packages/nc-gui/components/account/License.vue +++ b/packages/nc-gui/components/account/License.vue @@ -1,5 +1,5 @@ -
From 6d103911b036684fac52aea8b1bc524ae97d46ca Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Wed, 8 Nov 2023 10:17:33 +0000 Subject: [PATCH 13/16] misc: column name correction --- packages/nc-gui/components/dashboard/settings/UIAcl.vue | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/nc-gui/components/dashboard/settings/UIAcl.vue b/packages/nc-gui/components/dashboard/settings/UIAcl.vue index b613510f48..a48c20372a 100644 --- a/packages/nc-gui/components/dashboard/settings/UIAcl.vue +++ b/packages/nc-gui/components/dashboard/settings/UIAcl.vue @@ -110,11 +110,11 @@ const tableHeaderRenderer = (label: string) => () => h('div', { class: 'text-gra const columns = [ { title: tableHeaderRenderer(t('labels.tableName')), - name: 'table_name', + name: 'Table Name', }, { title: tableHeaderRenderer(t('labels.viewName')), - name: 'view_name', + name: 'View Name', }, { title: tableHeaderRenderer(t('objects.roleType.editor')), @@ -203,7 +203,7 @@ const toggleSelectAll = (role: Role) => {