Browse Source

barcode: add wrapper component around JSBarcode

pull/4641/head
Daniel Spaude 2 years ago
parent
commit
aaf3b9b4b8
No known key found for this signature in database
GPG Key ID: 654A3D1FA4F35FFE
  1. 14
      packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue
  2. 59
      packages/nc-gui/components/virtual-cell/barcode/Barcode.vue
  3. 68
      packages/nc-gui/components/virtual-cell/barcode/JsBarcodeWrapper.ts
  4. 42
      packages/nc-gui/components/virtual-cell/barcode/JsBarcodeWrapper.vue
  5. 3
      packages/nc-gui/lang/de.json
  6. 3
      packages/nc-gui/lang/en.json
  7. 85
      packages/nc-gui/package-lock.json
  8. 1
      packages/nc-gui/package.json
  9. 47
      packages/nocodb/package-lock.json

14
packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue

@ -40,16 +40,16 @@ const columnsAllowedAsQrValue = computed<SelectProps['options']>(() => {
const supportedBarcodeFormats = [
{ value: 'CODE128', label: 'CODE128' },
{ value: 'UPC', label: 'UPC' },
{ value: 'EAN13', label: 'EAN13' },
{ value: 'EAN8', label: 'EAN8' },
{ value: 'EAN5', label: 'EAN5' },
{ value: 'EAN2', label: 'EAN2' },
{ value: 'upc', label: 'UPC' },
{ value: 'EAN13', label: 'EAN-13' },
{ value: 'EAN8', label: 'EAN-8' },
{ value: 'EAN5', label: 'EAN-5' },
{ value: 'EAN2', label: 'EAN-2' },
{ value: 'CODE39', label: 'CODE39' },
{ value: 'ITF14', label: 'ITF14' },
{ value: 'ITF14', label: 'ITF-14' },
{ value: 'MSI', label: 'MSI' },
{ value: 'PHARMACODE', label: 'pharmacode' },
{ value: 'CODEBAR', label: 'codabar' },
{ value: 'CODABAR', label: 'codabar' },
]
onMounted(() => {

59
packages/nc-gui/components/virtual-cell/barcode/Barcode.vue

@ -1,7 +1,7 @@
<script setup lang="ts">
import JsBarcodeWrapper from './JsBarcodeWrapper'
import JsBarcodeWrapper from './JsBarcodeWrapper.vue'
const maxNumberOfAllowedCharsForQrValue = 2000
const maxNumberOfAllowedCharsForBarcodeValue = 100
const cellValue = inject(CellValueInj)
@ -9,12 +9,11 @@ const column = inject(ColumnInj)
const barcodeValue = computed(() => String(cellValue?.value))
const tooManyCharsForQrCode = computed(() => barcodeValue?.value.length > maxNumberOfAllowedCharsForQrValue)
const tooManyCharsForBarcode = computed(() => barcodeValue?.value.length > maxNumberOfAllowedCharsForBarcodeValue)
const modalVisible = ref(false)
const showQrModal = (ev: MouseEvent) => {
ev.stopPropagation()
const showBarcodeModal = () => {
modalVisible.value = true
}
@ -25,11 +24,6 @@ const barcodeMeta = $computed(() => {
}
})
const jsBarcodeOptions = $computed(() => ({
format: barcodeMeta.barcodeFormat,
// format: 'CODE128',
}))
const handleModalOkClick = () => (modalVisible.value = false)
const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning } = useShowNotEditableWarning()
@ -39,39 +33,44 @@ const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning } = us
<a-modal
v-model:visible="modalVisible"
:class="{ active: modalVisible }"
wrap-class-name="nc-qr-code-large amodal-wrapper"
wrap-class-name="nc-barcode-large amodal-wrapper"
:body-style="{ padding: '0px' }"
:footer="null"
@ok="handleModalOkClick"
>
<JsBarcodeWrapper
v-if="barcodeValue && !tooManyCharsForQrCode"
:options="jsBarcodeOptions"
tag="svg"
:value="barcodeValue"
width="3"
/>
v-if="barcodeValue && !tooManyCharsForBarcode"
:barcode-value="barcodeValue"
:barcode-format="barcodeMeta.barcodeFormat"
>
<template #barcodeRenderError>
<div class="text-left text-wrap mt-2 text-[#e65100] text-xs">
{{ $t('msg.warning.barcode.renderError') }}
</div>
</template>
</JsBarcodeWrapper>
</a-modal>
<div @click="showQrModal">
FOO: {{ JSON.stringify(jsBarcodeOptions) }}
<JsBarcodeWrapper
v-if="barcodeValue && !tooManyCharsForQrCode"
:options="jsBarcodeOptions"
tag="svg"
class="w-full"
:value="barcodeValue"
width="3"
></JsBarcodeWrapper>
</div>
<JsBarcodeWrapper
v-if="barcodeValue && !tooManyCharsForBarcode"
:barcode-value="barcodeValue"
:barcode-format="barcodeMeta.barcodeFormat"
@on-click-barcode="showBarcodeModal"
>
<template #barcodeRenderError>
<div class="text-left text-wrap mt-2 text-[#e65100] text-xs">
{{ $t('msg.warning.barcode.renderError') }}
</div>
</template>
</JsBarcodeWrapper>
<div v-if="tooManyCharsForQrCode" class="text-left text-wrap mt-2 text-[#e65100] text-xs">
<div v-if="tooManyCharsForBarcode" class="text-left text-wrap mt-2 text-[#e65100] text-xs">
{{ $t('labels.barcodeValueTooLong') }}
</div>
<div v-if="showEditNonEditableFieldWarning" class="text-left text-wrap mt-2 text-[#e65100] text-xs">
{{ $t('msg.warning.nonEditableFields.computedFieldUnableToClear') }}
</div>
<div v-if="showClearNonEditableFieldWarning" class="text-left text-wrap mt-2 text-[#e65100] text-xs">
{{ $t('msg.warning.nonEditableFields.qrFieldsCannotBeDirectlyChanged') }}
{{ $t('msg.warning.nonEditableFields.barcodeFieldsCannotBeDirectlyChanged') }}
</div>
</template>

68
packages/nc-gui/components/virtual-cell/barcode/JsBarcodeWrapper.ts

@ -1,68 +0,0 @@
import { defineComponent, h } from 'vue'
import JsBarcode from 'jsbarcode'
// TODO: add proper reference for the origin of this code here
export default defineComponent({
name: 'JsBarcodeWrapper',
props: {
/**
* The value of the bar code.
*/
value: {
type: String,
default: undefined,
},
/**
* The options for the bar code generator.
* {@link https://github.com/lindell/JsBarcode#options}
*/
options: {
type: Object,
default: undefined,
},
/**
* The tag name of the component's root element.
*/
tag: {
type: String,
default: 'canvas',
},
},
watch: {
$props: {
deep: true,
immediate: true,
/**
* Update the bar code when props changed.
*/
handler() {
if (this.$el) {
this.generate()
}
},
},
},
mounted() {
this.generate()
},
methods: {
/**
* Generate bar code.
*/
generate() {
// debugger
JsBarcode(this.$el, String(this.value), this.options)
},
},
render() {
return h(this.tag, this.$slots.default)
},
})

42
packages/nc-gui/components/virtual-cell/barcode/JsBarcodeWrapper.vue

@ -0,0 +1,42 @@
<script lang="ts" setup>
import JsBarcode from 'jsbarcode'
const props = defineProps({
barcodeValue: { type: String, required: true },
barcodeFormat: { type: String, required: true },
})
const emit = defineEmits(['onClickBarcode'])
const barcodeSvgRef = ref(null)
const errorForCurrentInput = ref(false)
const generate = () => {
try {
JsBarcode(barcodeSvgRef.value, String(props.barcodeValue), {
format: props.barcodeFormat,
})
errorForCurrentInput.value = false
} catch (e) {
console.log('e', e)
errorForCurrentInput.value = true
}
}
const onBarcodeClick = (ev: MouseEvent) => {
ev.stopPropagation()
emit('onClickBarcode')
}
watch(() => props.barcodeValue, generate)
watch(() => props.barcodeFormat, generate)
onMounted(generate)
</script>
<template>
<svg v-show="!errorForCurrentInput" ref="barcodeSvgRef" @click="onBarcodeClick"></svg>
<slot v-if="errorForCurrentInput" name="barcodeRenderError" />
</template>
<style scoped>
svg {
width: 100%;
}
</style>

3
packages/nc-gui/lang/de.json

@ -498,7 +498,8 @@
"warning": {
"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."
}
},
"info": {

3
packages/nc-gui/lang/en.json

@ -499,6 +499,9 @@
},
"msg": {
"warning": {
"barcode": {
"renderError": "Barcode error - please check compatibility between input and barcode type"
},
"nonEditableFields": {
"computedFieldUnableToClear": "Warning: Computed field - unable to clear text",
"qrFieldsCannotBeDirectlyChanged": "Warning: QR fields cannot be directly changed."

85
packages/nc-gui/package-lock.json generated

@ -8,7 +8,6 @@
"hasInstallScript": true,
"license": "AGPL-3.0-or-later",
"dependencies": {
"@chenfengyuan/vue-barcode": "^2.0.1",
"@ckpack/vue-color": "^1.2.0",
"@types/file-saver": "^2.0.5",
"@vue-flow/additional-components": "^1.2.0",
@ -92,28 +91,6 @@
"windicss": "^3.5.6"
}
},
"../nocodb-sdk": {
"version": "0.100.2",
"license": "AGPL-3.0-or-later",
"dependencies": {
"axios": "^0.21.1",
"jsep": "^1.3.6"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^4.0.1",
"@typescript-eslint/parser": "^4.0.1",
"cspell": "^4.1.0",
"eslint": "^7.8.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-functional": "^3.0.2",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-prettier": "^4.0.0",
"npm-run-all": "^4.1.5",
"prettier": "^2.1.1",
"typescript": "^4.0.2"
}
},
"node_modules/@ampproject/remapping": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
@ -873,15 +850,6 @@
"node": ">=6.9.0"
}
},
"node_modules/@chenfengyuan/vue-barcode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@chenfengyuan/vue-barcode/-/vue-barcode-2.0.1.tgz",
"integrity": "sha512-YTSV1o0vOIRDZMiZZ9t09zkc9VZXN8CG8rriJUZUMtrvdg4Xt/qOOuzRlZEyRD7hsSYjbQy/3RcByGn1WOb1EA==",
"peerDependencies": {
"jsbarcode": "^3.11.0",
"vue": "^3.0.0"
}
},
"node_modules/@ckpack/vue-color": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ckpack/vue-color/-/vue-color-1.2.0.tgz",
@ -8450,7 +8418,6 @@
"version": "1.15.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
"devOptional": true,
"funding": [
{
"type": "individual",
@ -11866,8 +11833,21 @@
}
},
"node_modules/nocodb-sdk": {
"resolved": "../nocodb-sdk",
"link": true
"version": "0.100.2",
"resolved": "file:../nocodb-sdk",
"license": "AGPL-3.0-or-later",
"dependencies": {
"axios": "^0.21.1",
"jsep": "^1.3.6"
}
},
"node_modules/nocodb-sdk/node_modules/axios": {
"version": "0.21.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"dependencies": {
"follow-redirects": "^1.14.0"
}
},
"node_modules/node-abi": {
"version": "3.23.0",
@ -18257,12 +18237,6 @@
"to-fast-properties": "^2.0.0"
}
},
"@chenfengyuan/vue-barcode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@chenfengyuan/vue-barcode/-/vue-barcode-2.0.1.tgz",
"integrity": "sha512-YTSV1o0vOIRDZMiZZ9t09zkc9VZXN8CG8rriJUZUMtrvdg4Xt/qOOuzRlZEyRD7hsSYjbQy/3RcByGn1WOb1EA==",
"requires": {}
},
"@ckpack/vue-color": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ckpack/vue-color/-/vue-color-1.2.0.tgz",
@ -23719,8 +23693,7 @@
"follow-redirects": {
"version": "1.15.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
"devOptional": true
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA=="
},
"form-data": {
"version": "4.0.0",
@ -26193,22 +26166,20 @@
}
},
"nocodb-sdk": {
"version": "file:../nocodb-sdk",
"version": "0.100.2",
"requires": {
"@typescript-eslint/eslint-plugin": "^4.0.1",
"@typescript-eslint/parser": "^4.0.1",
"axios": "^0.21.1",
"cspell": "^4.1.0",
"eslint": "^7.8.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-functional": "^3.0.2",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-prettier": "^4.0.0",
"jsep": "^1.3.6",
"npm-run-all": "^4.1.5",
"prettier": "^2.1.1",
"typescript": "^4.0.2"
"jsep": "^1.3.6"
},
"dependencies": {
"axios": {
"version": "0.21.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"requires": {
"follow-redirects": "^1.14.0"
}
}
}
},
"node-abi": {

1
packages/nc-gui/package.json

@ -31,7 +31,6 @@
"ci:run": "export NODE_OPTIONS=\"--max_old_space_size=16384\"; npm install; NUXT_PAGE_TRANSITION_DISABLE=true npm run build; NUXT_PUBLIC_NC_BACKEND_URL=http://localhost:8080 npm run start &"
},
"dependencies": {
"@chenfengyuan/vue-barcode": "^2.0.1",
"@ckpack/vue-color": "^1.2.0",
"@vue-flow/additional-components": "^1.2.0",
"@vue-flow/core": "^1.3.0",

47
packages/nocodb/package-lock.json generated

@ -151,28 +151,6 @@
"vuedraggable": "^2.24.3"
}
},
"../nocodb-sdk": {
"version": "0.100.2",
"license": "AGPL-3.0-or-later",
"dependencies": {
"axios": "^0.21.1",
"jsep": "^1.3.6"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^4.0.1",
"@typescript-eslint/parser": "^4.0.1",
"cspell": "^4.1.0",
"eslint": "^7.8.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-functional": "^3.0.2",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-prettier": "^4.0.0",
"npm-run-all": "^4.1.5",
"prettier": "^2.1.1",
"typescript": "^4.0.2"
}
},
"node_modules/@azure/abort-controller": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz",
@ -10656,8 +10634,13 @@
"dev": true
},
"node_modules/nocodb-sdk": {
"resolved": "../nocodb-sdk",
"link": true
"version": "0.100.2",
"resolved": "file:../nocodb-sdk",
"license": "AGPL-3.0-or-later",
"dependencies": {
"axios": "^0.21.1",
"jsep": "^1.3.6"
}
},
"node_modules/node-abort-controller": {
"version": "3.0.1",
@ -26059,22 +26042,10 @@
"dev": true
},
"nocodb-sdk": {
"version": "file:../nocodb-sdk",
"version": "0.100.2",
"requires": {
"@typescript-eslint/eslint-plugin": "^4.0.1",
"@typescript-eslint/parser": "^4.0.1",
"axios": "^0.21.1",
"cspell": "^4.1.0",
"eslint": "^7.8.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-functional": "^3.0.2",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-prettier": "^4.0.0",
"jsep": "^1.3.6",
"npm-run-all": "^4.1.5",
"prettier": "^2.1.1",
"typescript": "^4.0.2"
"jsep": "^1.3.6"
}
},
"node-abort-controller": {

Loading…
Cancel
Save