From 12f62ed100a472dc793943ed5c0be0924561d29c Mon Sep 17 00:00:00 2001 From: flisowna Date: Thu, 1 Dec 2022 20:14:09 +0300 Subject: [PATCH 01/31] Barcode column type: add vue-barcode library --- packages/nc-gui/package-lock.json | 82 +++++++++++++++++++++++++++++++ packages/nc-gui/package.json | 1 + 2 files changed, 83 insertions(+) diff --git a/packages/nc-gui/package-lock.json b/packages/nc-gui/package-lock.json index 676878a194..4acbc03a98 100644 --- a/packages/nc-gui/package-lock.json +++ b/packages/nc-gui/package-lock.json @@ -34,6 +34,7 @@ "tinycolor2": "^1.4.2", "unique-names-generator": "^4.7.1", "validator": "^13.7.0", + "vue-barcode": "^1.3.0", "vue-dompurify-html": "^3.0.0", "vue-github-button": "^3.0.3", "vue-i18n": "^9.2.2", @@ -10207,6 +10208,66 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbarcode": { + "version": "3.11.5", + "resolved": "https://registry.npmjs.org/jsbarcode/-/jsbarcode-3.11.5.tgz", + "integrity": "sha512-zv3KsH51zD00I/LrFzFSM6dst7rDn0vIMzaiZFL7qusTjPZiPtxg3zxetp0RR7obmjTw4f6NyGgbdkBCgZUIrA==", + "bin": { + "auto.js": "bin/barcodes/CODE128/auto.js", + "Barcode.js": "bin/barcodes/Barcode.js", + "barcodes": "bin/barcodes", + "canvas.js": "bin/renderers/canvas.js", + "checksums.js": "bin/barcodes/MSI/checksums.js", + "codabar": "bin/barcodes/codabar", + "CODE128": "bin/barcodes/CODE128", + "CODE128_AUTO.js": "bin/barcodes/CODE128/CODE128_AUTO.js", + "CODE128.js": "bin/barcodes/CODE128/CODE128.js", + "CODE128A.js": "bin/barcodes/CODE128/CODE128A.js", + "CODE128B.js": "bin/barcodes/CODE128/CODE128B.js", + "CODE128C.js": "bin/barcodes/CODE128/CODE128C.js", + "CODE39": "bin/barcodes/CODE39", + "constants.js": "bin/barcodes/ITF/constants.js", + "defaults.js": "bin/options/defaults.js", + "EAN_UPC": "bin/barcodes/EAN_UPC", + "EAN.js": "bin/barcodes/EAN_UPC/EAN.js", + "EAN13.js": "bin/barcodes/EAN_UPC/EAN13.js", + "EAN2.js": "bin/barcodes/EAN_UPC/EAN2.js", + "EAN5.js": "bin/barcodes/EAN_UPC/EAN5.js", + "EAN8.js": "bin/barcodes/EAN_UPC/EAN8.js", + "encoder.js": "bin/barcodes/EAN_UPC/encoder.js", + "ErrorHandler.js": "bin/exceptions/ErrorHandler.js", + "exceptions": "bin/exceptions", + "exceptions.js": "bin/exceptions/exceptions.js", + "fixOptions.js": "bin/help/fixOptions.js", + "GenericBarcode": "bin/barcodes/GenericBarcode", + "getOptionsFromElement.js": "bin/help/getOptionsFromElement.js", + "getRenderProperties.js": "bin/help/getRenderProperties.js", + "help": "bin/help", + "index.js": "bin/renderers/index.js", + "index.tmp.js": "bin/barcodes/index.tmp.js", + "ITF": "bin/barcodes/ITF", + "ITF.js": "bin/barcodes/ITF/ITF.js", + "ITF14.js": "bin/barcodes/ITF/ITF14.js", + "JsBarcode.js": "bin/JsBarcode.js", + "linearizeEncodings.js": "bin/help/linearizeEncodings.js", + "merge.js": "bin/help/merge.js", + "MSI": "bin/barcodes/MSI", + "MSI.js": "bin/barcodes/MSI/MSI.js", + "MSI10.js": "bin/barcodes/MSI/MSI10.js", + "MSI1010.js": "bin/barcodes/MSI/MSI1010.js", + "MSI11.js": "bin/barcodes/MSI/MSI11.js", + "MSI1110.js": "bin/barcodes/MSI/MSI1110.js", + "object.js": "bin/renderers/object.js", + "options": "bin/options", + "optionsFromStrings.js": "bin/help/optionsFromStrings.js", + "pharmacode": "bin/barcodes/pharmacode", + "renderers": "bin/renderers", + "shared.js": "bin/renderers/shared.js", + "svg.js": "bin/renderers/svg.js", + "UPC.js": "bin/barcodes/EAN_UPC/UPC.js", + "UPCE.js": "bin/barcodes/EAN_UPC/UPCE.js" + } + }, "node_modules/jsdom": { "version": "20.0.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.0.tgz", @@ -16805,6 +16866,14 @@ "@vue/shared": "3.2.41" } }, + "node_modules/vue-barcode": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/vue-barcode/-/vue-barcode-1.3.0.tgz", + "integrity": "sha512-DxQ0hxes/dP6GajsJumpW6jV14VwlnTwStZbtE6G0wkewuJVDoDOdxUr5seGuxsMT9fJ0aty4X47Z5TG0M/gxg==", + "dependencies": { + "jsbarcode": "^3.5.8" + } + }, "node_modules/vue-bundle-renderer": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/vue-bundle-renderer/-/vue-bundle-renderer-0.4.4.tgz", @@ -24902,6 +24971,11 @@ "argparse": "^2.0.1" } }, + "jsbarcode": { + "version": "3.11.5", + "resolved": "https://registry.npmjs.org/jsbarcode/-/jsbarcode-3.11.5.tgz", + "integrity": "sha512-zv3KsH51zD00I/LrFzFSM6dst7rDn0vIMzaiZFL7qusTjPZiPtxg3zxetp0RR7obmjTw4f6NyGgbdkBCgZUIrA==" + }, "jsdom": { "version": "20.0.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.0.tgz", @@ -29670,6 +29744,14 @@ "@vue/shared": "3.2.41" } }, + "vue-barcode": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/vue-barcode/-/vue-barcode-1.3.0.tgz", + "integrity": "sha512-DxQ0hxes/dP6GajsJumpW6jV14VwlnTwStZbtE6G0wkewuJVDoDOdxUr5seGuxsMT9fJ0aty4X47Z5TG0M/gxg==", + "requires": { + "jsbarcode": "^3.5.8" + } + }, "vue-bundle-renderer": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/vue-bundle-renderer/-/vue-bundle-renderer-0.4.4.tgz", diff --git a/packages/nc-gui/package.json b/packages/nc-gui/package.json index ab0ed240b7..ea7967d795 100644 --- a/packages/nc-gui/package.json +++ b/packages/nc-gui/package.json @@ -57,6 +57,7 @@ "tinycolor2": "^1.4.2", "unique-names-generator": "^4.7.1", "validator": "^13.7.0", + "vue-barcode": "^1.3.0", "vue-dompurify-html": "^3.0.0", "vue-github-button": "^3.0.3", "vue-i18n": "^9.2.2", From e7a15b77ec6c1ad0a24efe2d8fe53b97e93d46f4 Mon Sep 17 00:00:00 2001 From: flisowna Date: Thu, 1 Dec 2022 20:14:58 +0300 Subject: [PATCH 02/31] Barcode column type - WIP (mainly FE related code) --- .../nc-gui/components/smartsheet/Form.vue | 6 +- .../components/smartsheet/VirtualCell.vue | 2 + .../smartsheet/column/BarcodeOptions.vue | 68 +++++++++++++++++++ .../smartsheet/column/EditOrAdd.vue | 1 + .../smartsheet/column/FormulaOptions.vue | 2 +- .../smartsheet/column/LookupOptions.vue | 2 +- .../smartsheet/column/QrCodeOptions.vue | 4 +- .../toolbar/FieldListAutoCompleteDropdown.vue | 2 +- .../components/virtual-cell/Barcode.vue | 0 packages/nc-gui/composables/useSharedView.ts | 1 + packages/nc-gui/composables/useViewData.ts | 1 + packages/nc-gui/lang/en.json | 1 + packages/nc-gui/utils/columnUtils.ts | 6 ++ packages/nc-gui/utils/virtualCell.ts | 1 + .../src/lib/columnRules/QrCodeRules.ts | 2 +- packages/nocodb/src/lib/models/Column.ts | 4 +- 16 files changed, 93 insertions(+), 10 deletions(-) create mode 100644 packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue create mode 100644 packages/nc-gui/components/virtual-cell/Barcode.vue diff --git a/packages/nc-gui/components/smartsheet/Form.vue b/packages/nc-gui/components/smartsheet/Form.vue index 30b7da12c7..19a9482c63 100644 --- a/packages/nc-gui/components/smartsheet/Form.vue +++ b/packages/nc-gui/components/smartsheet/Form.vue @@ -33,7 +33,7 @@ provide(IsGalleryInj, ref(false)) // todo: generate hideCols based on default values const hiddenCols = ['created_at', 'updated_at'] -const hiddenColTypes = [UITypes.Rollup, UITypes.Lookup, UITypes.Formula, UITypes.QrCode, UITypes.SpecificDBType] +const hiddenColTypes = [UITypes.Rollup, UITypes.Lookup, UITypes.Formula, UITypes.QrCode, UITypes.Barcode, UITypes.SpecificDBType] const state = useGlobal() @@ -229,7 +229,9 @@ async function addAllColumns() { } function shouldSkipColumn(col: Record) { - return isDbRequired(col) || !!col.required || (!!col.rqd && !col.cdf) || col.uidt === UITypes.QrCode + return ( + isDbRequired(col) || !!col.required || (!!col.rqd && !col.cdf) || col.uidt === UITypes.QrCode || col.uidt === UITypes.Barcode + ) } async function removeAllColumns() { diff --git a/packages/nc-gui/components/smartsheet/VirtualCell.vue b/packages/nc-gui/components/smartsheet/VirtualCell.vue index dcf44f2c06..fe7f463ac8 100644 --- a/packages/nc-gui/components/smartsheet/VirtualCell.vue +++ b/packages/nc-gui/components/smartsheet/VirtualCell.vue @@ -14,6 +14,7 @@ import { isLookup, isMm, isQrCode, + isBarcode, isRollup, provide, toRef, @@ -59,6 +60,7 @@ function onNavigate(dir: NavigateDir, e: KeyboardEvent) { + diff --git a/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue b/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue new file mode 100644 index 0000000000..0033598bb2 --- /dev/null +++ b/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue @@ -0,0 +1,68 @@ + + + diff --git a/packages/nc-gui/components/smartsheet/column/EditOrAdd.vue b/packages/nc-gui/components/smartsheet/column/EditOrAdd.vue index f7a63fe1de..144c9f043c 100644 --- a/packages/nc-gui/components/smartsheet/column/EditOrAdd.vue +++ b/packages/nc-gui/components/smartsheet/column/EditOrAdd.vue @@ -171,6 +171,7 @@ useEventListener('keydown', (e: KeyboardEvent) => { + diff --git a/packages/nc-gui/components/smartsheet/column/FormulaOptions.vue b/packages/nc-gui/components/smartsheet/column/FormulaOptions.vue index 1ccb069b43..76b0124440 100644 --- a/packages/nc-gui/components/smartsheet/column/FormulaOptions.vue +++ b/packages/nc-gui/components/smartsheet/column/FormulaOptions.vue @@ -26,7 +26,7 @@ const props = defineProps<{ const emit = defineEmits(['update:value']) -const uiTypesNotSupportedInFormulas = [UITypes.QrCode] +const uiTypesNotSupportedInFormulas = [UITypes.QrCode, UITypes.Barcode] const vModel = useVModel(props, 'value', emit) diff --git a/packages/nc-gui/components/smartsheet/column/LookupOptions.vue b/packages/nc-gui/components/smartsheet/column/LookupOptions.vue index 1bb039bc7d..c98e83512f 100644 --- a/packages/nc-gui/components/smartsheet/column/LookupOptions.vue +++ b/packages/nc-gui/components/smartsheet/column/LookupOptions.vue @@ -55,7 +55,7 @@ const columns = $computed(() => { } return metas[selectedTable.id].columns.filter((c: any) => { - return !(isSystemColumn(c) || c.uidt === UITypes.QrCode) + return !(isSystemColumn(c) || c.uidt === UITypes.QrCode || c.uidt === UITypes.Barcode) }) }) diff --git a/packages/nc-gui/components/smartsheet/column/QrCodeOptions.vue b/packages/nc-gui/components/smartsheet/column/QrCodeOptions.vue index be08672d7a..3b7dd7d993 100644 --- a/packages/nc-gui/components/smartsheet/column/QrCodeOptions.vue +++ b/packages/nc-gui/components/smartsheet/column/QrCodeOptions.vue @@ -1,6 +1,6 @@ @@ -53,11 +53,11 @@ setAdditionalValidations({ { return { icon: FormulaIcon, color: 'text-grey' } case UITypes.QrCode: return { icon: QrCodeScan, color: 'text-grey' } + case UITypes.Barcode: + return { icon: BarcodeScan, color: 'text-grey' } case UITypes.Lookup: switch ((relationColumn?.colOptions as LinkToAnotherRecordType)?.type) { case RelationTypes.MANY_TO_MANY: diff --git a/packages/nc-gui/components/virtual-cell/Barcode.vue b/packages/nc-gui/components/virtual-cell/Barcode.vue index e69de29bb2..097656f47f 100644 --- a/packages/nc-gui/components/virtual-cell/Barcode.vue +++ b/packages/nc-gui/components/virtual-cell/Barcode.vue @@ -0,0 +1,61 @@ + + + diff --git a/packages/nc-gui/package-lock.json b/packages/nc-gui/package-lock.json index 4acbc03a98..b9188420bd 100644 --- a/packages/nc-gui/package-lock.json +++ b/packages/nc-gui/package-lock.json @@ -8,6 +8,7 @@ "hasInstallScript": true, "license": "AGPL-3.0-or-later", "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", @@ -21,6 +22,7 @@ "dayjs": "^1.11.3", "file-saver": "^2.0.5", "httpsnippet": "^2.0.0", + "jsbarcode": "^3.11.5", "jsep": "^1.3.6", "just-clone": "^6.1.1", "jwt-decode": "^3.1.2", @@ -34,7 +36,6 @@ "tinycolor2": "^1.4.2", "unique-names-generator": "^4.7.1", "validator": "^13.7.0", - "vue-barcode": "^1.3.0", "vue-dompurify-html": "^3.0.0", "vue-github-button": "^3.0.3", "vue-i18n": "^9.2.2", @@ -869,6 +870,15 @@ "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", @@ -16866,14 +16876,6 @@ "@vue/shared": "3.2.41" } }, - "node_modules/vue-barcode": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/vue-barcode/-/vue-barcode-1.3.0.tgz", - "integrity": "sha512-DxQ0hxes/dP6GajsJumpW6jV14VwlnTwStZbtE6G0wkewuJVDoDOdxUr5seGuxsMT9fJ0aty4X47Z5TG0M/gxg==", - "dependencies": { - "jsbarcode": "^3.5.8" - } - }, "node_modules/vue-bundle-renderer": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/vue-bundle-renderer/-/vue-bundle-renderer-0.4.4.tgz", @@ -18229,6 +18231,12 @@ "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", @@ -29744,14 +29752,6 @@ "@vue/shared": "3.2.41" } }, - "vue-barcode": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/vue-barcode/-/vue-barcode-1.3.0.tgz", - "integrity": "sha512-DxQ0hxes/dP6GajsJumpW6jV14VwlnTwStZbtE6G0wkewuJVDoDOdxUr5seGuxsMT9fJ0aty4X47Z5TG0M/gxg==", - "requires": { - "jsbarcode": "^3.5.8" - } - }, "vue-bundle-renderer": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/vue-bundle-renderer/-/vue-bundle-renderer-0.4.4.tgz", diff --git a/packages/nc-gui/package.json b/packages/nc-gui/package.json index ea7967d795..0e7f64c920 100644 --- a/packages/nc-gui/package.json +++ b/packages/nc-gui/package.json @@ -31,6 +31,7 @@ "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", @@ -44,6 +45,7 @@ "dayjs": "^1.11.3", "file-saver": "^2.0.5", "httpsnippet": "^2.0.0", + "jsbarcode": "^3.11.5", "jsep": "^1.3.6", "just-clone": "^6.1.1", "jwt-decode": "^3.1.2", @@ -57,7 +59,6 @@ "tinycolor2": "^1.4.2", "unique-names-generator": "^4.7.1", "validator": "^13.7.0", - "vue-barcode": "^1.3.0", "vue-dompurify-html": "^3.0.0", "vue-github-button": "^3.0.3", "vue-i18n": "^9.2.2", diff --git a/packages/nc-gui/plugins/ant.ts b/packages/nc-gui/plugins/ant.ts index 9c8a4e4e05..5ee06e280c 100644 --- a/packages/nc-gui/plugins/ant.ts +++ b/packages/nc-gui/plugins/ant.ts @@ -1,7 +1,9 @@ import { Menu as AntMenu, Modal as AntModal, message } from 'ant-design-vue' +import VueBarcode from '@chenfengyuan/vue-barcode' import { defineNuxtPlugin } from '#imports' export default defineNuxtPlugin((nuxtApp) => { + nuxtApp.vueApp.component(VueBarcode.name, VueBarcode) nuxtApp.vueApp.component(AntMenu.name, AntMenu) nuxtApp.vueApp.component(AntModal.name, AntModal) message.config({ diff --git a/packages/nocodb-sdk/src/lib/columnRules/index.ts b/packages/nocodb-sdk/src/lib/columnRules/index.ts index 30acec12c9..4f08acd8b3 100644 --- a/packages/nocodb-sdk/src/lib/columnRules/index.ts +++ b/packages/nocodb-sdk/src/lib/columnRules/index.ts @@ -1 +1 @@ -export * from './QrCodeRules'; +export * from './QrAndBarcodeRules'; diff --git a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts index 429252ae59..9055a4e07c 100644 --- a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts +++ b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts @@ -45,6 +45,7 @@ import { customAlphabet } from 'nanoid'; import DOMPurify from 'isomorphic-dompurify'; import { sanitize, unsanitize } from './helpers/sanitize'; import QrCodeColumn from '../../../../models/QrCodeColumn'; +import BarcodeColumn from '../../../../models/BarcodeColumn'; const GROUP_COL = '__nc_group_id'; @@ -1470,6 +1471,38 @@ class BaseModelSqlv2 { break; } + case 'Barcode': { + const barcodeColumn = await column.getColOptions(); + const barcodeValueColumn = await Column.get({ + colId: barcodeColumn.fk_barcode_value_column_id, + }); + + // If the referenced value cannot be found: cancel current iteration + if (barcodeValueColumn == null) { + break; + } + + switch (barcodeValueColumn.uidt) { + case UITypes.Formula: + try { + const selectQb = await this.getSelectQueryBuilderForFormula( + barcodeValueColumn + ); + qb.select({ + [column.column_name]: selectQb.builder, + }); + } catch { + continue; + } + break; + default: { + qb.select({ [column.column_name]: barcodeValueColumn.column_name }); + break; + } + } + + break; + } case 'Formula': { try { @@ -2217,6 +2250,7 @@ class BaseModelSqlv2 { f.uidt !== UITypes.Lookup && f.uidt !== UITypes.Formula && f.uidt !== UITypes.QrCode && + f.uidt !== UITypes.Barcode && f.uidt !== UITypes.SpecificDBType ) .sort( diff --git a/packages/nocodb/src/lib/meta/api/columnApis.ts b/packages/nocodb/src/lib/meta/api/columnApis.ts index 00551e639f..d09d1fc534 100644 --- a/packages/nocodb/src/lib/meta/api/columnApis.ts +++ b/packages/nocodb/src/lib/meta/api/columnApis.ts @@ -512,6 +512,12 @@ export async function columnAdd( fk_model_id: table.id, }); break; + case UITypes.Barcode: + await Column.insert({ + ...colBody, + fk_model_id: table.id, + }); + break; case UITypes.Formula: colBody.formula = await substituteColumnAliasWithIdInFormula( colBody.formula_raw || colBody.formula, @@ -738,11 +744,12 @@ export async function columnUpdate(req: Request, res: Response) { UITypes.LinkToAnotherRecord, UITypes.Formula, UITypes.QrCode, + UITypes.Barcode, UITypes.ForeignKey, ].includes(column.uidt) ) { if (column.uidt === colBody.uidt) { - if (column.uidt === UITypes.QrCode) { + if ([UITypes.QrCode, UITypes.Barcode].includes(column.uidt)) { await Column.update(column.id, { ...column, ...colBody, @@ -774,6 +781,7 @@ export async function columnUpdate(req: Request, res: Response) { UITypes.LinkToAnotherRecord, UITypes.Formula, UITypes.QrCode, + UITypes.Barcode, UITypes.ForeignKey, ].includes(colBody.uidt) ) { @@ -1460,6 +1468,7 @@ export async function columnDelete(req: Request, res: Response) { case UITypes.Lookup: case UITypes.Rollup: case UITypes.QrCode: + case UITypes.Barcode: case UITypes.Formula: await Column.delete(req.params.columnId); break; diff --git a/packages/nocodb/src/lib/migrations/XcMigrationSourcev2.ts b/packages/nocodb/src/lib/migrations/XcMigrationSourcev2.ts index 280825dddc..ddf1fc6522 100644 --- a/packages/nocodb/src/lib/migrations/XcMigrationSourcev2.ts +++ b/packages/nocodb/src/lib/migrations/XcMigrationSourcev2.ts @@ -10,6 +10,7 @@ import * as nc_019_add_meta_in_meta_tables from './v2/nc_019_add_meta_in_meta_ta import * as nc_020_kanban_view from './v2/nc_020_kanban_view'; import * as nc_021_add_fields_in_token from './v2/nc_021_add_fields_in_token'; import * as nc_022_qr_code_column_type from './v2/nc_022_qr_code_column_type'; +import * as nc_023_barcode_column_type from './v2/nc_023_barcode_column_type'; // Create a custom migration source class export default class XcMigrationSourcev2 { @@ -31,6 +32,7 @@ export default class XcMigrationSourcev2 { 'nc_020_kanban_view', 'nc_021_add_fields_in_token', 'nc_022_qr_code_column_type', + 'nc_023_barcode_column_type', ]); } @@ -64,6 +66,8 @@ export default class XcMigrationSourcev2 { return nc_021_add_fields_in_token; case 'nc_022_qr_code_column_type': return nc_022_qr_code_column_type; + case 'nc_023_barcode_column_type': + return nc_023_barcode_column_type; } } } diff --git a/packages/nocodb/src/lib/migrations/v2/nc_023_barcode_column_type.ts b/packages/nocodb/src/lib/migrations/v2/nc_023_barcode_column_type.ts new file mode 100644 index 0000000000..e67f31a12e --- /dev/null +++ b/packages/nocodb/src/lib/migrations/v2/nc_023_barcode_column_type.ts @@ -0,0 +1,26 @@ +import { MetaTable } from '../../utils/globals'; +import { Knex } from 'knex'; + +const up = async (knex: Knex) => { + await knex.schema.createTable(MetaTable.COL_BARCODE, (table) => { + table.string('id', 20).primary().notNullable(); + + table.string('fk_column_id', 20); + table.foreign('fk_column_id').references(`${MetaTable.COLUMNS}.id`); + + table.string('fk_barcode_value_column_id', 20); + table + .foreign('fk_barcode_value_column_id') + .references(`${MetaTable.COLUMNS}.id`); + + table.boolean('deleted'); + table.float('order'); + table.timestamps(true, true); + }); +}; + +const down = async (knex: Knex) => { + await knex.schema.dropTable(MetaTable.COL_BARCODE); +}; + +export { up, down }; \ No newline at end of file diff --git a/packages/nocodb/tests/unit/factory/column.ts b/packages/nocodb/tests/unit/factory/column.ts index 391d766867..fe9c3fa4b8 100644 --- a/packages/nocodb/tests/unit/factory/column.ts +++ b/packages/nocodb/tests/unit/factory/column.ts @@ -262,6 +262,7 @@ export { defaultColumns, createColumn, createQrCodeColumn, + createBarcodeColumn, createRollupColumn, createLookupColumn, createLtarColumn, From d84eb431b6c16466123f6dfd115b82bf5c3f9364 Mon Sep 17 00:00:00 2001 From: flisowna Date: Mon, 5 Dec 2022 17:49:45 +0300 Subject: [PATCH 05/31] WIP barcode dynamic value --- .../virtual-cell/{ => barcode}/Barcode.vue | 25 +++---- .../virtual-cell/barcode/JsBarcodeWrapper.ts | 67 +++++++++++++++++++ packages/nc-gui/lang/en.json | 1 + packages/nc-gui/plugins/ant.ts | 4 +- 4 files changed, 78 insertions(+), 19 deletions(-) rename packages/nc-gui/components/virtual-cell/{ => barcode}/Barcode.vue (61%) create mode 100644 packages/nc-gui/components/virtual-cell/barcode/JsBarcodeWrapper.ts diff --git a/packages/nc-gui/components/virtual-cell/Barcode.vue b/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue similarity index 61% rename from packages/nc-gui/components/virtual-cell/Barcode.vue rename to packages/nc-gui/components/virtual-cell/barcode/Barcode.vue index 097656f47f..e7878bcf7e 100644 --- a/packages/nc-gui/components/virtual-cell/Barcode.vue +++ b/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue @@ -1,5 +1,6 @@ diff --git a/packages/nc-gui/components/virtual-cell/barcode/JsBarcodeWrapper.ts b/packages/nc-gui/components/virtual-cell/barcode/JsBarcodeWrapper.ts new file mode 100644 index 0000000000..511e4c74aa --- /dev/null +++ b/packages/nc-gui/components/virtual-cell/barcode/JsBarcodeWrapper.ts @@ -0,0 +1,67 @@ +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() { + JsBarcode(this.$el, String(this.value), this.options) + }, + }, + + render() { + return h(this.tag, this.$slots.default) + }, +}) diff --git a/packages/nc-gui/lang/en.json b/packages/nc-gui/lang/en.json index 39e1b1028b..d3f97bf83a 100644 --- a/packages/nc-gui/lang/en.json +++ b/packages/nc-gui/lang/en.json @@ -251,6 +251,7 @@ "qrCodeValueColumn": "Column with QR code value", "barcodeValueColumn": "Column with Barcode value", "qrCodeValueTooLong": "Too many characters for a QR code", + "barcodeValueTooLong": "Too many characters for a barcode", "aggregateFunction": "Aggregate function", "dbCreateIfNotExists": "Database : create if not exists", "clientKey": "Client Key", diff --git a/packages/nc-gui/plugins/ant.ts b/packages/nc-gui/plugins/ant.ts index 5ee06e280c..b1b5b403ff 100644 --- a/packages/nc-gui/plugins/ant.ts +++ b/packages/nc-gui/plugins/ant.ts @@ -1,9 +1,9 @@ import { Menu as AntMenu, Modal as AntModal, message } from 'ant-design-vue' -import VueBarcode from '@chenfengyuan/vue-barcode' +// import VueBarcode from '@chenfengyuan/vue-barcode' import { defineNuxtPlugin } from '#imports' export default defineNuxtPlugin((nuxtApp) => { - nuxtApp.vueApp.component(VueBarcode.name, VueBarcode) + // nuxtApp.vueApp.component(VueBarcode.name, VueBarcode) nuxtApp.vueApp.component(AntMenu.name, AntMenu) nuxtApp.vueApp.component(AntModal.name, AntModal) message.config({ From 9e2d663a5856431afd0ac9808feb3adfd14f5f51 Mon Sep 17 00:00:00 2001 From: flisowna Date: Mon, 5 Dec 2022 18:49:37 +0300 Subject: [PATCH 06/31] WIP barcode format select for barcode --- .../smartsheet/column/BarcodeOptions.vue | 30 +++++++++++++++++++ .../virtual-cell/barcode/Barcode.vue | 7 +---- packages/nc-gui/lang/en.json | 1 + 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue b/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue index 1446043e4d..b5aebe17ec 100644 --- a/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue +++ b/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue @@ -3,6 +3,8 @@ import type { UITypes } from 'nocodb-sdk' import { AllowedColumnTypesForQrAndBarcodes } from 'nocodb-sdk' import type { SelectProps } from 'ant-design-vue' import { useVModel } from '#imports' +import * as Ewa from '@chenfengyuan/vue-barcode' +import * as Daniel from 'JsBarcode' const props = defineProps<{ modelValue: any @@ -38,13 +40,29 @@ const columnsAllowedAsQrValue = computed(() => { }) }) +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: 'CODE39', label: 'CODE39' }, + { value: 'ITF14', label: 'ITF14' }, + { value: 'MSI', label: 'MSI' }, + { value: 'PHARMACODE', label: 'pharmacode' }, + { value: 'CODEBAR', label: 'codabar' }, +] + onMounted(() => { // set default value vModel.value.fk_barcode_value_column_id = (column?.value?.colOptions as Record)?.fk_barcode_value_column_id || '' + vModel.value.barcode_format = (column?.value?.colOptions as Record)?.barcode_format || '' }) setAdditionalValidations({ fk_barcode_value_column_id: [{ required: true, message: 'Required' }], + barcode_format: [{ required: true, message: 'Required' }], }) @@ -63,6 +81,18 @@ setAdditionalValidations({ @click.stop /> + + + diff --git a/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue b/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue index e7878bcf7e..73a1d10bd7 100644 --- a/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue +++ b/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue @@ -1,5 +1,4 @@ - @@ -81,7 +81,7 @@ setAdditionalValidations({ @click.stop /> - - + --> diff --git a/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue b/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue index 73a1d10bd7..d7cb6acef2 100644 --- a/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue +++ b/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue @@ -25,14 +25,21 @@ const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning } = us
- +
@@ -45,3 +52,9 @@ const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning } = us {{ $t('msg.warning.nonEditableFields.qrFieldsCannotBeDirectlyChanged') }}
+ + From ec86f321531d18e57ffc6e95f8bc2c0c088526c4 Mon Sep 17 00:00:00 2001 From: flisowna Date: Tue, 6 Dec 2022 19:30:33 +0300 Subject: [PATCH 09/31] barcode column type: fix FE issues (WIP) --- .../smartsheet/column/BarcodeOptions.vue | 18 ++++++++----- .../virtual-cell/barcode/Barcode.vue | 26 +++++++++++++++++-- .../virtual-cell/barcode/JsBarcodeWrapper.ts | 1 + 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue b/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue index 2d80d0d242..4d35356de3 100644 --- a/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue +++ b/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue @@ -3,8 +3,6 @@ import type { UITypes } from 'nocodb-sdk' import { AllowedColumnTypesForQrAndBarcodes } from 'nocodb-sdk' import type { SelectProps } from 'ant-design-vue' import { useVModel } from '#imports' -import * as Ewa from '@chenfengyuan/vue-barcode' -import * as Daniel from 'JsBarcode' const props = defineProps<{ modelValue: any @@ -57,13 +55,19 @@ const supportedBarcodeFormats = [ onMounted(() => { // set default value vModel.value.fk_barcode_value_column_id = (column?.value?.colOptions as Record)?.fk_barcode_value_column_id || '' - vModel.value.barcode_format = (column?.value?.colOptions as Record)?.barcode_format || '' + // vModel.value.meta.barcode_format = (column?.value?.colOptions as Record)?.barcode_format || '' }) setAdditionalValidations({ fk_barcode_value_column_id: [{ required: true, message: 'Required' }], - // barcode_format: [{ required: true, message: 'Required' }], + barcode_format: [{ required: true, message: 'Required' }], }) + +// set default meta value +vModel.value.meta = { + barcodeFormat: supportedBarcodeFormats[0].value, + ...vModel.value.meta, +} diff --git a/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue b/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue index d7cb6acef2..c4e5893980 100644 --- a/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue +++ b/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue @@ -5,6 +5,8 @@ const maxNumberOfAllowedCharsForQrValue = 2000 const cellValue = inject(CellValueInj) +const column = inject(ColumnInj) + const barcodeValue = computed(() => String(cellValue?.value)) const tooManyCharsForQrCode = computed(() => barcodeValue?.value.length > maxNumberOfAllowedCharsForQrValue) @@ -16,6 +18,18 @@ const showQrModal = (ev: MouseEvent) => { modalVisible.value = true } +const barcodeMeta = $computed(() => { + return { + barcodeFormat: 'CODE128', + ...(column?.value?.meta || {}), + } +}) + +const jsBarcodeOptions = $computed(() => ({ + format: barcodeMeta.barcodeFormat, + // format: 'CODE128', +})) + const handleModalOkClick = () => (modalVisible.value = false) const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning } = useShowNotEditableWarning() @@ -30,11 +44,19 @@ const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning } = us :footer="null" @ok="handleModalOkClick" > - +
+ FOO: {{ JSON.stringify(jsBarcodeOptions) }} .amodal-wrapper { - width: 100px; + // width: 100px; } diff --git a/packages/nc-gui/components/virtual-cell/barcode/JsBarcodeWrapper.ts b/packages/nc-gui/components/virtual-cell/barcode/JsBarcodeWrapper.ts index 511e4c74aa..cb94d72b60 100644 --- a/packages/nc-gui/components/virtual-cell/barcode/JsBarcodeWrapper.ts +++ b/packages/nc-gui/components/virtual-cell/barcode/JsBarcodeWrapper.ts @@ -57,6 +57,7 @@ export default defineComponent({ * Generate bar code. */ generate() { + // debugger JsBarcode(this.$el, String(this.value), this.options) }, }, From 645c61b31f54289c79db727b353ee9d928dbe802 Mon Sep 17 00:00:00 2001 From: Daniel Spaude Date: Thu, 8 Dec 2022 15:04:43 +0300 Subject: [PATCH 10/31] QR Code: don't show QR code for empty/undefined values --- packages/nc-gui/components/virtual-cell/QrCode.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/nc-gui/components/virtual-cell/QrCode.vue b/packages/nc-gui/components/virtual-cell/QrCode.vue index 3378753308..b4790542bb 100644 --- a/packages/nc-gui/components/virtual-cell/QrCode.vue +++ b/packages/nc-gui/components/virtual-cell/QrCode.vue @@ -6,8 +6,8 @@ const maxNumberOfAllowedCharsForQrValue = 2000 const cellValue = inject(CellValueInj) const qrValue = computed(() => String(cellValue?.value)) - const tooManyCharsForQrCode = computed(() => qrValue?.value.length > maxNumberOfAllowedCharsForQrValue) +const showQrCode = computed(() => qrValue?.value?.length > 0 && !tooManyCharsForQrCode.value) const qrCode = useQRCode(qrValue, { width: 150, @@ -40,12 +40,12 @@ const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning } = us - QR Code + QR Code
{{ $t('labels.qrCodeValueTooLong') }}
- QR Code + QR Code
{{ $t('msg.warning.nonEditableFields.computedFieldUnableToClear') }}
From aaf3b9b4b8860bcb7a4c594a25c06189fa5df085 Mon Sep 17 00:00:00 2001 From: Daniel Spaude Date: Wed, 7 Dec 2022 22:19:57 +0300 Subject: [PATCH 11/31] barcode: add wrapper component around JSBarcode --- .../smartsheet/column/BarcodeOptions.vue | 14 +-- .../virtual-cell/barcode/Barcode.vue | 59 +++++++------ .../virtual-cell/barcode/JsBarcodeWrapper.ts | 68 --------------- .../virtual-cell/barcode/JsBarcodeWrapper.vue | 42 +++++++++ packages/nc-gui/lang/de.json | 3 +- packages/nc-gui/lang/en.json | 3 + packages/nc-gui/package-lock.json | 85 ++++++------------- packages/nc-gui/package.json | 1 - packages/nocodb/package-lock.json | 47 ++-------- 9 files changed, 120 insertions(+), 202 deletions(-) delete mode 100644 packages/nc-gui/components/virtual-cell/barcode/JsBarcodeWrapper.ts create mode 100644 packages/nc-gui/components/virtual-cell/barcode/JsBarcodeWrapper.vue diff --git a/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue b/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue index 4d35356de3..ecba28449f 100644 --- a/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue +++ b/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue @@ -40,16 +40,16 @@ const columnsAllowedAsQrValue = computed(() => { 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(() => { diff --git a/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue b/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue index c4e5893980..79f46101e2 100644 --- a/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue +++ b/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue @@ -1,7 +1,7 @@ + + + + diff --git a/packages/nc-gui/lang/de.json b/packages/nc-gui/lang/de.json index 20b037afbf..16b357c1f8 100644 --- a/packages/nc-gui/lang/de.json +++ b/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": { diff --git a/packages/nc-gui/lang/en.json b/packages/nc-gui/lang/en.json index 91fff9118d..0db7d6d4ba 100644 --- a/packages/nc-gui/lang/en.json +++ b/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." diff --git a/packages/nc-gui/package-lock.json b/packages/nc-gui/package-lock.json index 9ecee88c1f..7603c6f582 100644 --- a/packages/nc-gui/package-lock.json +++ b/packages/nc-gui/package-lock.json @@ -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": { diff --git a/packages/nc-gui/package.json b/packages/nc-gui/package.json index b2c90778ed..bf81ec471c 100644 --- a/packages/nc-gui/package.json +++ b/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", diff --git a/packages/nocodb/package-lock.json b/packages/nocodb/package-lock.json index 4d65271a41..a3e2075d27 100644 --- a/packages/nocodb/package-lock.json +++ b/packages/nocodb/package-lock.json @@ -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": { From 58dfdc9d48e91970b516b14bc8f0c0094adab6cb Mon Sep 17 00:00:00 2001 From: flisowna Date: Fri, 9 Dec 2022 01:09:20 +0300 Subject: [PATCH 12/31] barcode column type: playwright tests (WIP) --- packages/nc-gui/package-lock.json | 69 +++++++++------- .../pages/Dashboard/Grid/Column/index.ts | 12 +++ tests/playwright/tests/columnBarcode.spec.ts | 80 +++++++++++++++++++ 3 files changed, 133 insertions(+), 28 deletions(-) create mode 100644 tests/playwright/tests/columnBarcode.spec.ts diff --git a/packages/nc-gui/package-lock.json b/packages/nc-gui/package-lock.json index 7603c6f582..5f14109b0e 100644 --- a/packages/nc-gui/package-lock.json +++ b/packages/nc-gui/package-lock.json @@ -91,6 +91,28 @@ "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", @@ -8418,6 +8440,7 @@ "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", @@ -11833,21 +11856,8 @@ } }, "node_modules/nocodb-sdk": { - "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" - } + "resolved": "../nocodb-sdk", + "link": true }, "node_modules/node-abi": { "version": "3.23.0", @@ -23693,7 +23703,8 @@ "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==" + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", + "devOptional": true }, "form-data": { "version": "4.0.0", @@ -26166,20 +26177,22 @@ } }, "nocodb-sdk": { - "version": "0.100.2", + "version": "file:../nocodb-sdk", "requires": { + "@typescript-eslint/eslint-plugin": "^4.0.1", + "@typescript-eslint/parser": "^4.0.1", "axios": "^0.21.1", - "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" - } - } + "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" } }, "node-abi": { diff --git a/tests/playwright/pages/Dashboard/Grid/Column/index.ts b/tests/playwright/pages/Dashboard/Grid/Column/index.ts index 787b2253d1..1658561ba5 100644 --- a/tests/playwright/pages/Dashboard/Grid/Column/index.ts +++ b/tests/playwright/pages/Dashboard/Grid/Column/index.ts @@ -30,6 +30,8 @@ export class ColumnPageObject extends BasePage { type = 'SingleLineText', formula = '', qrCodeValueColumnTitle = '', + barcodeValueColumnTitle = '', + barcodeFormat = '', childTable = '', childColumn = '', relationType = '', @@ -42,6 +44,8 @@ export class ColumnPageObject extends BasePage { type?: string; formula?: string; qrCodeValueColumnTitle?: string; + barcodeValueColumnTitle?: string; + barcodeFormat?: string; childTable?: string; childColumn?: string; relationType?: string; @@ -101,6 +105,14 @@ export class ColumnPageObject extends BasePage { }) .click(); break; + case 'Barcode': + await this.get().locator('.ant-select-single').nth(1).click(); + await this.rootPage + .locator(`.ant-select-item`, { + hasText: new RegExp(`^${barcodeValueColumnTitle}$`), + }) + .click(); + break; case 'Lookup': await this.get().locator('.ant-select-single').nth(1).click(); await this.rootPage diff --git a/tests/playwright/tests/columnBarcode.spec.ts b/tests/playwright/tests/columnBarcode.spec.ts new file mode 100644 index 0000000000..f29ce6318a --- /dev/null +++ b/tests/playwright/tests/columnBarcode.spec.ts @@ -0,0 +1,80 @@ +import { expect, test } from '@playwright/test'; +import { DashboardPage } from '../pages/Dashboard'; +import setup from '../setup'; +import { GridPage } from '../pages/Dashboard/Grid'; + +// type ExpectedBarcodeData = { +// referencedValue: string; +// base64EncodedSrc: string; +// }; + +const ONE_SVG_BARCODE_HTML = `A Corua (La Corua)`; + +test.describe('Virtual Columns', () => { + let dashboard: DashboardPage; + let grid: GridPage; + let context: any; + + test.beforeEach(async ({ page }) => { + context = await setup({ page }); + dashboard = new DashboardPage(page, context.project); + grid = dashboard.grid; + }); + + test.describe('Barcode Column', () => { + // async function qrCodeColumnVerify(qrColumnTitle: string, expectedQrCodeData: ExpectedQrCodeData[]) { + // for (let i = 0; i < expectedQrCodeData.length; i++) { + // await grid.cell.verifyQrCodeCell({ + // index: i, + // columnHeader: qrColumnTitle, + // expectedSrcValue: expectedQrCodeData[i].base64EncodedSrc, + // }); + // } + // } + test('creation, showing, updating value and change barcode column title and reference column', async () => { + // Add qr code column referencing the City column + // and compare the base64 encoded codes/src attributes for the first 3 rows. + // Column data from City table (Sakila DB) + /** + * City LastUpdate Address List Country + * A Corua (La Corua) 2006-02-15 04:45:25 939 Probolinggo Loop Spain + * Abha 2006-02-15 04:45:25 733 Mandaluyong Place Saudi Arabia + * Abu Dhabi 2006-02-15 04:45:25 535 Ahmadnagar Manor United Arab Emirates + */ + // const expectedQrCodeCellValues: ExpectedQrCodeData[] = [ + // { + // referencedValue: 'A Corua (La Corua)', + // base64EncodedSrc: + // 'data:image/png;base64,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', + // }, + // { + // referencedValue: 'Abha', + // base64EncodedSrc: + // 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAACWCAYAAAA8AXHiAAAAAXNSR0IArs4c6QAABx9JREFUeF7tndF22zgMROv//+j0xE2PbYW0ZghAMuy7zyAIDi5BkHK6l6+vr68//IcCyQpcACtZUdxdFQAsQChRALBKZMUpYMFAiQKAVSIrTgELBkoUAKwSWXEKWDBQogBglciKU8CCgRIFAKtEVpwCFgyUKABYJbLiFLBgoEQBwCqRFaeABQMlCgBWiaw4BSwYKFEAsEpkxSlgwUCJAiVgXS6XkmBXnc7+XmQUp/q3JeoanblX15cxTl23OhdgbZRSBQas54gBFmBdFVA3FBXrTgHnOFIFpmJRsaa7kR7rBoe6oV6uYmUHPlugA4tju52vomK9okYqSL/0qfhL6EjCVhfyf5wzt2MLWF5mDmveX3E3AhZHobxdHFgcWyqWnIKrIRXrhZ4bXrGqezjdrAELsHq/YzlvSeouGfl0jrfIzS4y9npUDD57qeuJ6OPMrc4zsju9YqkJGgWvJiIKtTqPGqOT3Gx9nLkB604BtRLMBFbhUBPuQB0BWI0bsITtoibCSa6aIMB6niCOwkSAVSidqqECXDG3IM3U5KPBUoVTj1fVDrBU5Td2UYHVaaNHoTqPuh7VDrBU5QHrqgBg3UDgKBQ2jwqMaudASI9VfOVXm1MnuQJTViVy5lZtAashWNlJU2GhYqlbummPBVi3xGV/AP/oHguwAGtYO6PPDYAFWIC10JY4n7Le7ihc0OvpEKeBHjmKVDH15uo079n6HDX36T1WtnCAta9oVKP9GT78p8lUrDfusRT6HZvobuQodNSe23IUCm9wEanPbKBncUc3n6LHYWApwVTZRJOrJkK1mzXQVetX/La9FSqLq7IBrH1lAWtfo18WgLUvGmDtawRYiRotuLoOocfaKBf5TESPdROzBKxVyjuNU58lso+YLhoB1mKmAOu5cIAFWIsKAFaNcOI/Oc5RWCL/+zrlKKRildANWCeA5Vy7R+GpSSshZuBUPc6cuCM+1ScRRx81HtVnSfMOWPvyq4lUtXSgHkWnxrO/sn8WgCUopYruJDfik4p1lzRVyCvt4o1LYCLFRI3diTviE7AAawo2YKXs+XgVUnepmrBZZYzMo/ZDZ8+dlNKnbkp6rIqbXiThMwVUELLtACsRbaf/UG8tasIBKzGRoisq1kaoSGV0QFdts+1ELsJmgAVYYYiGrc/Z//evyBGpVpeZcup450KwnctZnxpPpFVwtIgQV1Kx1PIdfbOKJOJ7bnU8YPmIAdZGM2dTKHJTsRSVRBsnOY7w2+nViuOUfyd2RQ5nfZH1RMbOqreyvumNmx7rURrAiuB0G3vYUZgT7qMXtfeZVQ11l0fsKtY9vIUZ31dV3SKxA9Zij5Vd2SJJdC9BgLWjtioQFWut0kdgp2JRsSL8TMcCFmD1Bks9tpxVOlf5kV+1KVfHRmNXNVL7O0cfdW51jYdVrOzA3YZVhUNNRnQ9KhzqDTCySd7yHUvdAarAjr9IMgDrudJULKHHUqudAzUVy1HrxzYimjOdemzNfFKxbspEK/BW45KK5cBxpq0K5lEAZm9IdX1teqwzYXHmVoUHLEfVf7ZULEEzwBJE2vaqFb9u8MM4ZwQVix6rhDzAAizAWlBA3ThtmndnQQt62UNmV+lInJG+y17AZoA6d/YTghN3SfMeSZgTvGoLWKpSeXaAtailWjUW3T8dps5NxapQ/84nFatY4IF7Ktai5mrVWHRPxRopkP1pwkmOM7dju40h2kceAaZTqbOPzcMqVnbgM9gcWBxbwHK2d9EnnUjCvPB/WztzO7aA5WWGiiW8EanHvSM9R6Gj1o9tpBIsTPcwxJnbsaVieZk5vWJFmmB110eb2OwYv1Ok+oysUZ3jO57sHhiwhKPQSdB2XztQj2oCYN2p4hwx2UmLzq0mUj0YAEtVSrCLJleY4mqiQuAkV/UZiZGjUFVvYwdYN0EcqDkKd4ADrH2w1D2b3Sqo80btaN5Pat7VxAEWzfuQleg1HrAAC7DuGaj4Kx16LHqsj+6xRiVGPXoqjriITzXuWW8XmXuo4ydXLMDKq6xbLalYwhuc+r6k3vRmD6SRqkHFWkykmlynv6NiUbHkGxdgOXXzjcFak2E+KgqWWsXUY8s5otTvlKqdo626HtXn6T2WGqhqB1iqUo92gLWjG2AB1poCgCX/XMgRmIoFWIB1z0D2jpjxxVHo1Kk3uBWuLTdnlPNjO3UDVAAcWe3LxXPUJ52IaNGxgBVV0B9/2HODH1reCMDK01L1BFgbpTgKVXSe2wEWYOWQtPFSAlZJpDhtpQBgtUpXn2ABq0+uWkUKWK3S1SdYwOqTq1aRAlardPUJFrD65KpVpIDVKl19ggWsPrlqFSlgtUpXn2ABq0+uWkUKWK3S1SdYwOqTq1aRAlardPUJFrD65KpVpIDVKl19ggWsPrlqFSlgtUpXn2ABq0+uWkUKWK3S1SfYvxJkkcY9Vq0GAAAAAElFTkSuQmCC', + // }, + // { + // referencedValue: 'Abu Dhabi', + // base64EncodedSrc: + // 'data:image/png;base64,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', + // }, + // ]; + + // close 'Team & Auth' tab + await dashboard.closeTab({ title: 'Team & Auth' }); + + await dashboard.treeView.openTable({ title: 'City' }); + + await grid.column.create({ + title: 'Barcode1', + type: 'Barcode', + barcodeValueColumnTitle: 'City', + }); + const FOO = await grid.cell.get({ index: 0, columnHeader: 'Barcode1' }); + const SVG = await FOO.locator('svg').innerHTML(); + expect(SVG).toEqual(ONE_SVG_BARCODE_HTML); + // const INNERHTML = await SVG.innerHTML(); + // console.log('INNERHTML'); + // console.log(INNERHTML); + }); + }); +}); From 7f75bbf8242d866a65f839b6691fc5b1e693b6af Mon Sep 17 00:00:00 2001 From: flisowna Date: Fri, 9 Dec 2022 15:13:59 +0300 Subject: [PATCH 13/31] barcode column type: playwright tests (WIP) --- .../virtual-cell/barcode/Barcode.vue | 1 + .../virtual-cell/barcode/JsBarcodeWrapper.vue | 2 +- .../pages/Dashboard/common/Cell/index.ts | 29 +++++++++ tests/playwright/tests/columnBarcode.spec.ts | 65 ++++++++----------- 4 files changed, 59 insertions(+), 38 deletions(-) diff --git a/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue b/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue index 79f46101e2..3f07245ebe 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 { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning } = us v-if="barcodeValue && !tooManyCharsForBarcode" :barcode-value="barcodeValue" :barcode-format="barcodeMeta.barcodeFormat" + class="nc-barcode-svg" @on-click-barcode="showBarcodeModal" > - - diff --git a/tests/playwright/pages/Dashboard/BarcodeOverlay/index.ts b/tests/playwright/pages/Dashboard/BarcodeOverlay/index.ts new file mode 100644 index 0000000000..ce70f07bcc --- /dev/null +++ b/tests/playwright/pages/Dashboard/BarcodeOverlay/index.ts @@ -0,0 +1,25 @@ +import { expect } from '@playwright/test'; +import BasePage from '../../Base'; +import { FormPage } from '../Form'; +import { GalleryPage } from '../Gallery'; +import { GridPage } from '../Grid'; +import { KanbanPage } from '../Kanban'; + +export class BarcodeOverlay extends BasePage { + constructor(parent: GridPage | GalleryPage | KanbanPage | FormPage) { + super(parent.rootPage); + } + + get() { + return this.rootPage.locator(`.nc-barcode-large`); + } + + async verifyBarcodeSvgValue(expectedValue: string) { + const foundBarcodeSvg = await this.get().getByTestId('barcode').innerHTML(); + await expect(foundBarcodeSvg).toContain(expectedValue); + } + + async clickCloseButton() { + await this.get().locator('.ant-modal-close-x').click(); + } +} diff --git a/tests/playwright/pages/Dashboard/Grid/index.ts b/tests/playwright/pages/Dashboard/Grid/index.ts index 66a85bee3b..9aa72c5644 100644 --- a/tests/playwright/pages/Dashboard/Grid/index.ts +++ b/tests/playwright/pages/Dashboard/Grid/index.ts @@ -6,12 +6,14 @@ import { ColumnPageObject } from './Column'; import { ToolbarPage } from '../common/Toolbar'; import { ProjectMenuObject } from '../common/ProjectMenu'; import { QrCodeOverlay } from '../QrCodeOverlay'; +import { BarcodeOverlay } from '../BarcodeOverlay'; export class GridPage extends BasePage { readonly dashboard: DashboardPage; readonly addNewTableButton: Locator; readonly dashboardPage: DashboardPage; readonly qrCodeOverlay: QrCodeOverlay; + readonly barcodeOverlay: BarcodeOverlay; readonly column: ColumnPageObject; readonly cell: CellPageObject; readonly toolbar: ToolbarPage; @@ -22,6 +24,7 @@ export class GridPage extends BasePage { this.dashboard = dashboardPage; this.addNewTableButton = dashboardPage.get().locator('.nc-add-new-table'); this.qrCodeOverlay = new QrCodeOverlay(this); + this.barcodeOverlay = new BarcodeOverlay(this); this.column = new ColumnPageObject(this); this.cell = new CellPageObject(this); this.toolbar = new ToolbarPage(this); diff --git a/tests/playwright/pages/Dashboard/common/Cell/index.ts b/tests/playwright/pages/Dashboard/common/Cell/index.ts index 41a49a3331..01577430de 100644 --- a/tests/playwright/pages/Dashboard/common/Cell/index.ts +++ b/tests/playwright/pages/Dashboard/common/Cell/index.ts @@ -157,10 +157,6 @@ export class CellPageObject extends BasePage { return await barcodeSvg.innerHTML(); }) .toEqual(expectedBarcodeSvg); - - // const SVG = await FOO.locator('svg'); - // expect(SVG).toEqual(ONE_SVG_BARCODE_HTML); - }; await _verify(expectedSvgValue); diff --git a/tests/playwright/tests/columnBarcode.spec.ts b/tests/playwright/tests/columnBarcode.spec.ts index f87929bf1e..874f07ae90 100644 --- a/tests/playwright/tests/columnBarcode.spec.ts +++ b/tests/playwright/tests/columnBarcode.spec.ts @@ -3,10 +3,15 @@ import { DashboardPage } from '../pages/Dashboard'; import setup from '../setup'; import { GridPage } from '../pages/Dashboard/Grid'; -type ExpectedBarcodeData = { +interface ExpectedBarcodeData { referencedValue: string; barcodeSvg: string; -}; + // barcodeSvgForModal: string; +} + +// interface ExpectedBarcodeDataWithOverlay extends ExpectedBarcodeData { +// barcodeSvgForModal: string; +// } // const ONE_SVG_BARCODE_HTML = `A Corua (La Corua)`; @@ -66,6 +71,26 @@ test.describe('Virtual Columns', () => { }); await barcodeColumnVerify('Barcode1', expectedBarcodeCellValues); + + await grid.cell.fillText({ columnHeader: 'City', index: 0, text: 'Berlin' }); + + const changedFirstBarcodeCellValue = { + referencedValue: 'Berlin', + barcodeSvg: + 'Berlin', + barcodeSvgForOverlay: + 'Berlin', + }; + const expectedBarcodeCellValuesAfterCityNameChange = [ + changedFirstBarcodeCellValue, + ...expectedBarcodeCellValues.slice(1), + ]; + await barcodeColumnVerify('Barcode1', expectedBarcodeCellValuesAfterCityNameChange); + + await grid.cell.get({ columnHeader: 'Barcode1', index: 0 }).click(); + const barcodeGridOverlay = grid.barcodeOverlay; + await barcodeGridOverlay.verifyBarcodeSvgValue(changedFirstBarcodeCellValue.barcodeSvgForOverlay); + await barcodeGridOverlay.clickCloseButton(); }); }); }); From 6c27d6bf42f750f58be01ce9117f8fed84630b7c Mon Sep 17 00:00:00 2001 From: flisowna Date: Fri, 9 Dec 2022 19:33:51 +0300 Subject: [PATCH 15/31] barcode column type: playwright tests (WIP) --- .../smartsheet/column/BarcodeOptions.vue | 4 +- .../pages/Dashboard/Grid/Column/index.ts | 11 +++++ tests/playwright/tests/columnBarcode.spec.ts | 41 ++++++++++++++++--- 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue b/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue index ecba28449f..16b866feea 100644 --- a/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue +++ b/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue @@ -74,7 +74,7 @@ vModel.value.meta = { @@ -86,7 +86,7 @@ vModel.value.meta = { /> diff --git a/tests/playwright/pages/Dashboard/Grid/Column/index.ts b/tests/playwright/pages/Dashboard/Grid/Column/index.ts index 1658561ba5..f407293abd 100644 --- a/tests/playwright/pages/Dashboard/Grid/Column/index.ts +++ b/tests/playwright/pages/Dashboard/Grid/Column/index.ts @@ -218,6 +218,17 @@ export class ColumnPageObject extends BasePage { await this.save(); } + async changeReferencedColumnForBarcode({ titleOfReferencedColumn }: { titleOfReferencedColumn: string }) { + await this.get().locator('.nc-barcode-value-column-select .ant-select-single').click(); + await this.rootPage + .locator(`.ant-select-item`, { + hasText: titleOfReferencedColumn, + }) + .click(); + + await this.save(); + } + async delete({ title }: { title: string }) { await this.getColumnHeader(title).locator('svg.ant-dropdown-trigger').click(); // await this.rootPage.locator('li[role="menuitem"]:has-text("Delete")').waitFor(); diff --git a/tests/playwright/tests/columnBarcode.spec.ts b/tests/playwright/tests/columnBarcode.spec.ts index 874f07ae90..5fbd91bc03 100644 --- a/tests/playwright/tests/columnBarcode.spec.ts +++ b/tests/playwright/tests/columnBarcode.spec.ts @@ -74,23 +74,54 @@ test.describe('Virtual Columns', () => { await grid.cell.fillText({ columnHeader: 'City', index: 0, text: 'Berlin' }); - const changedFirstBarcodeCellValue = { + const barcodeCellValuesForBerlin = { referencedValue: 'Berlin', barcodeSvg: 'Berlin', - barcodeSvgForOverlay: - 'Berlin', + // barcodeSvgForOverlay: + // 'Berlin', }; + + const barcodeCellValuesForIstanbul = { + referencedValue: 'Istanbul', + barcodeSvg: + 'Istanbul', + // barcodeSvgForOverlay: + // 'Berlin', + }; + const expectedBarcodeCellValuesAfterCityNameChange = [ - changedFirstBarcodeCellValue, + barcodeCellValuesForBerlin, ...expectedBarcodeCellValues.slice(1), ]; await barcodeColumnVerify('Barcode1', expectedBarcodeCellValuesAfterCityNameChange); await grid.cell.get({ columnHeader: 'Barcode1', index: 0 }).click(); const barcodeGridOverlay = grid.barcodeOverlay; - await barcodeGridOverlay.verifyBarcodeSvgValue(changedFirstBarcodeCellValue.barcodeSvgForOverlay); + await barcodeGridOverlay.verifyBarcodeSvgValue(barcodeCellValuesForBerlin.barcodeSvg); await barcodeGridOverlay.clickCloseButton(); + + // Change the QR Code column title + await grid.column.openEdit({ title: 'Barcode1' }); + await grid.column.fillTitle({ title: 'Barcode1 Renamed' }); + await grid.column.save({ isUpdated: true }); + await barcodeColumnVerify('Barcode1 Renamed', expectedBarcodeCellValuesAfterCityNameChange); + + // Change the referenced column title + await grid.column.openEdit({ title: 'City' }); + await grid.column.fillTitle({ title: 'City Renamed' }); + await grid.column.save({ isUpdated: true }); + await barcodeColumnVerify('Barcode1 Renamed', expectedBarcodeCellValuesAfterCityNameChange); + + // Change the referenced column + await grid.column.create({ title: 'New City Column' }); + await grid.cell.fillText({ columnHeader: 'New City Column', index: 0, text: 'Istanbul' }); + await grid.column.openEdit({ title: 'Barcode1 Renamed' }); + await grid.column.changeReferencedColumnForBarcode({ titleOfReferencedColumn: 'New City Column' }); + + await barcodeColumnVerify('Barcode1 Renamed', [barcodeCellValuesForIstanbul]); + + await dashboard.closeTab({ title: 'City' }); }); }); }); From b7ed402dae570f8164ac65797315654b79489962 Mon Sep 17 00:00:00 2001 From: flisowna Date: Fri, 9 Dec 2022 19:37:58 +0300 Subject: [PATCH 16/31] barcode column type: playwright tests (WIP) --- tests/playwright/tests/columnBarcode.spec.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/playwright/tests/columnBarcode.spec.ts b/tests/playwright/tests/columnBarcode.spec.ts index 5fbd91bc03..c963862241 100644 --- a/tests/playwright/tests/columnBarcode.spec.ts +++ b/tests/playwright/tests/columnBarcode.spec.ts @@ -123,5 +123,11 @@ test.describe('Virtual Columns', () => { await dashboard.closeTab({ title: 'City' }); }); + + test('deletion of the barcode column: directly and indirectly when the reference value column is deleted', async () => {}); + + test('changing the format of the Barcode is reflected in the change of the actual rendered barcode', async () => {}); + + test('barcode cells with invalid input for the choosen barcode format are showing a replacement message', async () => {}); }); }); From 1994b8622b6a7d3b96fa85373214fe70bcc51fe4 Mon Sep 17 00:00:00 2001 From: flisowna Date: Fri, 9 Dec 2022 20:29:10 +0300 Subject: [PATCH 17/31] barcode column type: playwright tests (WIP) --- .../smartsheet/column/BarcodeOptions.vue | 2 +- .../pages/Dashboard/Grid/Column/index.ts | 25 ++++++++++ tests/playwright/tests/columnBarcode.spec.ts | 49 ++++++++++++++++++- 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue b/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue index 16b866feea..810ab30866 100644 --- a/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue +++ b/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue @@ -86,7 +86,7 @@ vModel.value.meta = { /> diff --git a/tests/playwright/pages/Dashboard/Grid/Column/index.ts b/tests/playwright/pages/Dashboard/Grid/Column/index.ts index f407293abd..8d9712e650 100644 --- a/tests/playwright/pages/Dashboard/Grid/Column/index.ts +++ b/tests/playwright/pages/Dashboard/Grid/Column/index.ts @@ -112,6 +112,12 @@ export class ColumnPageObject extends BasePage { hasText: new RegExp(`^${barcodeValueColumnTitle}$`), }) .click(); + // await this.get().locator('.ant-select-single').nth(2).click(); + // await this.rootPage + // .locator(`.ant-select-item`, { + // hasText: new RegExp(`^${barcodeFormat}$`), + // }) + // .click(); break; case 'Lookup': await this.get().locator('.ant-select-single').nth(1).click(); @@ -229,6 +235,17 @@ export class ColumnPageObject extends BasePage { await this.save(); } + async changeBarcodeFormat({ barcodeFormatName }: { barcodeFormatName: string }) { + await this.get().locator('.nc-barcode-format-select .ant-select-single').click(); + await this.rootPage + .locator(`.ant-select-item`, { + hasText: barcodeFormatName, + }) + .click(); + + await this.save(); + } + async delete({ title }: { title: string }) { await this.getColumnHeader(title).locator('svg.ant-dropdown-trigger').click(); // await this.rootPage.locator('li[role="menuitem"]:has-text("Delete")').waitFor(); @@ -268,6 +285,14 @@ export class ColumnPageObject extends BasePage { }) .click(); break; + // case 'Barcode': + // await this.get().locator('.ant-select-single').nth(1).click(); + // await this.rootPage + // .locator(`.ant-select-item`, { + // hasText: format, + // }) + // .click(); + // break; default: break; } diff --git a/tests/playwright/tests/columnBarcode.spec.ts b/tests/playwright/tests/columnBarcode.spec.ts index c963862241..85a1ea47e0 100644 --- a/tests/playwright/tests/columnBarcode.spec.ts +++ b/tests/playwright/tests/columnBarcode.spec.ts @@ -124,9 +124,54 @@ test.describe('Virtual Columns', () => { await dashboard.closeTab({ title: 'City' }); }); - test('deletion of the barcode column: directly and indirectly when the reference value column is deleted', async () => {}); + test('deletion of the barcode column: directly and indirectly when the reference value column is deleted', async () => { + await dashboard.closeTab({ title: 'Team & Auth' }); + + await dashboard.treeView.openTable({ title: 'City' }); + + await grid.column.create({ title: 'column_name_a' }); + await grid.column.verify({ title: 'column_name_a' }); + await grid.column.create({ + title: 'Barcode2', + type: 'Barcode', + barcodeValueColumnTitle: 'column_name_a', + }); + await grid.column.verify({ title: 'Barcode2', isVisible: true }); + await grid.column.delete({ title: 'Barcode2' }); + await grid.column.verify({ title: 'Barcode2', isVisible: false }); + + await grid.column.create({ + title: 'Barcode2', + type: 'Barcode', + barcodeValueColumnTitle: 'column_name_a', + }); + await grid.column.verify({ title: 'Barcode2', isVisible: true }); + await grid.column.delete({ title: 'column_name_a' }); + await grid.column.verify({ title: 'Barcode2', isVisible: false }); + + await dashboard.closeTab({ title: 'City' }); + }); + + test('changing the format of the Barcode is reflected in the change of the actual rendered barcode', async () => { + await dashboard.closeTab({ title: 'Team & Auth' }); + + await dashboard.treeView.openTable({ title: 'City' }); - test('changing the format of the Barcode is reflected in the change of the actual rendered barcode', async () => {}); + await grid.column.create({ title: 'column_name_b' }); + await grid.column.verify({ title: 'column_name_b' }); + await grid.column.create({ + title: 'Barcode3', + type: 'Barcode', + barcodeValueColumnTitle: 'column_name_b', + barcodeFormat: 'CODE128', + }); + await grid.column.openEdit({ + title: 'Barcode3', + type: 'Barcode', + }); + await grid.column.changeBarcodeFormat({ barcodeFormatName: 'CODE39' }); + + }); test('barcode cells with invalid input for the choosen barcode format are showing a replacement message', async () => {}); }); From ad8eb298cf3f88149c4412e0e903aa27cbb5dfe9 Mon Sep 17 00:00:00 2001 From: flisowna Date: Fri, 9 Dec 2022 20:43:42 +0300 Subject: [PATCH 18/31] barcode column type: playwright tests (WIP) --- tests/playwright/tests/columnBarcode.spec.ts | 89 +++++++++++--------- 1 file changed, 48 insertions(+), 41 deletions(-) diff --git a/tests/playwright/tests/columnBarcode.spec.ts b/tests/playwright/tests/columnBarcode.spec.ts index 85a1ea47e0..354974fdff 100644 --- a/tests/playwright/tests/columnBarcode.spec.ts +++ b/tests/playwright/tests/columnBarcode.spec.ts @@ -27,6 +27,43 @@ test.describe('Virtual Columns', () => { }); test.describe('Barcode Column', () => { + const expectedBarcodeCellValues: ExpectedBarcodeData[] = [ + { + referencedValue: 'A Corua (La Corua)', + barcodeSvg: + 'A Corua (La Corua)', + }, + { + referencedValue: 'Abha', + barcodeSvg: + 'Abha', + }, + ]; + + const barcodeCellValuesForBerlin = { + referencedValue: 'Berlin', + barcodeSvg: + 'Berlin', + // barcodeSvgForOverlay: + // 'Berlin', + }; + + const barcodeCellValuesForIstanbul = { + referencedValue: 'Istanbul', + barcodeSvg: + 'Istanbul', + // barcodeSvgForOverlay: + // 'Berlin', + }; + + const barcodeCode39SvgForBerlin = + 'BERLIN'; + + const expectedBarcodeCellValuesAfterCityNameChange = [ + barcodeCellValuesForBerlin, + ...expectedBarcodeCellValues.slice(1), + ]; + async function barcodeColumnVerify(barcodeColumnTitle: string, expectedBarcodeCodeData: ExpectedBarcodeData[]) { for (let i = 0; i < expectedBarcodeCodeData.length; i++) { await grid.cell.verifyBarcodeCell({ @@ -46,19 +83,6 @@ test.describe('Virtual Columns', () => { * Abha 2006-02-15 04:45:25 733 Mandaluyong Place Saudi Arabia * Abu Dhabi 2006-02-15 04:45:25 535 Ahmadnagar Manor United Arab Emirates */ - const expectedBarcodeCellValues: ExpectedBarcodeData[] = [ - { - referencedValue: 'A Corua (La Corua)', - barcodeSvg: - 'A Corua (La Corua)', - }, - { - referencedValue: 'Abha', - barcodeSvg: - 'Abha', - }, - ]; - // close 'Team & Auth' tab await dashboard.closeTab({ title: 'Team & Auth' }); @@ -74,26 +98,6 @@ test.describe('Virtual Columns', () => { await grid.cell.fillText({ columnHeader: 'City', index: 0, text: 'Berlin' }); - const barcodeCellValuesForBerlin = { - referencedValue: 'Berlin', - barcodeSvg: - 'Berlin', - // barcodeSvgForOverlay: - // 'Berlin', - }; - - const barcodeCellValuesForIstanbul = { - referencedValue: 'Istanbul', - barcodeSvg: - 'Istanbul', - // barcodeSvgForOverlay: - // 'Berlin', - }; - - const expectedBarcodeCellValuesAfterCityNameChange = [ - barcodeCellValuesForBerlin, - ...expectedBarcodeCellValues.slice(1), - ]; await barcodeColumnVerify('Barcode1', expectedBarcodeCellValuesAfterCityNameChange); await grid.cell.get({ columnHeader: 'Barcode1', index: 0 }).click(); @@ -157,20 +161,23 @@ test.describe('Virtual Columns', () => { await dashboard.treeView.openTable({ title: 'City' }); - await grid.column.create({ title: 'column_name_b' }); - await grid.column.verify({ title: 'column_name_b' }); + await grid.cell.fillText({ columnHeader: 'City', index: 0, text: 'Berlin' }); + await grid.column.create({ - title: 'Barcode3', + title: 'Barcode1', type: 'Barcode', - barcodeValueColumnTitle: 'column_name_b', - barcodeFormat: 'CODE128', + barcodeValueColumnTitle: 'City', }); + + await barcodeColumnVerify('Barcode1', [barcodeCellValuesForBerlin]); + await grid.column.openEdit({ - title: 'Barcode3', - type: 'Barcode', + title: 'Barcode1', }); await grid.column.changeBarcodeFormat({ barcodeFormatName: 'CODE39' }); - + await barcodeColumnVerify('Barcode1 Renamed', [ + { referencedValue: 'Berlin', barcodeSvg: barcodeCode39SvgForBerlin }, + ]); }); test('barcode cells with invalid input for the choosen barcode format are showing a replacement message', async () => {}); From f52107b94313c342f6f0cd26a967d3cb6299a395 Mon Sep 17 00:00:00 2001 From: flisowna Date: Fri, 9 Dec 2022 20:57:03 +0300 Subject: [PATCH 19/31] barcode column type: playwright tests (WIP) --- .../virtual-cell/barcode/Barcode.vue | 7 +------ .../pages/Dashboard/common/Cell/index.ts | 17 ++++++++++++++++ tests/playwright/tests/columnBarcode.spec.ts | 20 +++++++++---------- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue b/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue index 110d89cd37..cb68936b1e 100644 --- a/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue +++ b/packages/nc-gui/components/virtual-cell/barcode/Barcode.vue @@ -43,11 +43,6 @@ const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning } = us :barcode-value="barcodeValue" :barcode-format="barcodeMeta.barcodeFormat" > -
diff --git a/tests/playwright/pages/Dashboard/common/Cell/index.ts b/tests/playwright/pages/Dashboard/common/Cell/index.ts index 01577430de..1de2a1db40 100644 --- a/tests/playwright/pages/Dashboard/common/Cell/index.ts +++ b/tests/playwright/pages/Dashboard/common/Cell/index.ts @@ -137,6 +137,23 @@ export class CellPageObject extends BasePage { await _verify(expectedSrcValue); } + async verifyBarcodeCellShowsInvalidInputMessage({ index, columnHeader }: { index: number; columnHeader: string }) { + const _verify = async expectedInvalidInputMessage => { + await expect + .poll(async () => { + const barcodeCell = await this.get({ + index, + columnHeader, + }); + const barcodeInvalidInputMessage = await barcodeCell.getByTestId('barcode-invalid-input-message'); + return await barcodeInvalidInputMessage.textContent(); + }) + .toEqual(expectedInvalidInputMessage); + }; + + await _verify('Barcode error - please check compatibility between input and barcode type'); + } + async verifyBarcodeCell({ index, columnHeader, diff --git a/tests/playwright/tests/columnBarcode.spec.ts b/tests/playwright/tests/columnBarcode.spec.ts index 354974fdff..18aac6e2fe 100644 --- a/tests/playwright/tests/columnBarcode.spec.ts +++ b/tests/playwright/tests/columnBarcode.spec.ts @@ -156,30 +156,30 @@ test.describe('Virtual Columns', () => { await dashboard.closeTab({ title: 'City' }); }); - test('changing the format of the Barcode is reflected in the change of the actual rendered barcode', async () => { + test('a) showing an error message for non-compatible barcode input and b) changing the format of the Barcode is reflected in the change of the actual rendered barcode', async () => { await dashboard.closeTab({ title: 'Team & Auth' }); await dashboard.treeView.openTable({ title: 'City' }); - await grid.cell.fillText({ columnHeader: 'City', index: 0, text: 'Berlin' }); - await grid.column.create({ title: 'Barcode1', type: 'Barcode', barcodeValueColumnTitle: 'City', }); - await barcodeColumnVerify('Barcode1', [barcodeCellValuesForBerlin]); - await grid.column.openEdit({ title: 'Barcode1', }); await grid.column.changeBarcodeFormat({ barcodeFormatName: 'CODE39' }); - await barcodeColumnVerify('Barcode1 Renamed', [ - { referencedValue: 'Berlin', barcodeSvg: barcodeCode39SvgForBerlin }, - ]); - }); - test('barcode cells with invalid input for the choosen barcode format are showing a replacement message', async () => {}); + await grid.cell.verifyBarcodeCellShowsInvalidInputMessage({ + index: 0, + columnHeader: 'Barcode1', + }); + + await grid.cell.fillText({ columnHeader: 'City', index: 0, text: 'Berlin' }); + + await barcodeColumnVerify('Barcode1', [{ referencedValue: 'Berlin', barcodeSvg: barcodeCode39SvgForBerlin }]); + }); }); }); From 86d5c71ca9ad9100559fbbc3a40538b5360762ae Mon Sep 17 00:00:00 2001 From: flisowna Date: Mon, 12 Dec 2022 22:28:07 +0300 Subject: [PATCH 20/31] clean code --- .../smartsheet/column/BarcodeOptions.vue | 5 +--- tests/playwright/tests/columnBarcode.spec.ts | 23 +++++-------------- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue b/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue index 810ab30866..79de2228de 100644 --- a/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue +++ b/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue @@ -26,9 +26,7 @@ const columnsAllowedAsQrValue = computed(() => { return fields.value ?.filter( (el) => - el.fk_column_id && - // AllowedColumnTypesForQrCode.map((el) => el.toString()).includes(metaColumnById.value[el.fk_column_id].uidt), - AllowedColumnTypesForQrAndBarcodes.includes(metaColumnById.value[el.fk_column_id].uidt as UITypes), + el.fk_column_id && AllowedColumnTypesForQrAndBarcodes.includes(metaColumnById.value[el.fk_column_id].uidt as UITypes), ) .map((field) => { return { @@ -55,7 +53,6 @@ const supportedBarcodeFormats = [ onMounted(() => { // set default value vModel.value.fk_barcode_value_column_id = (column?.value?.colOptions as Record)?.fk_barcode_value_column_id || '' - // vModel.value.meta.barcode_format = (column?.value?.colOptions as Record)?.barcode_format || '' }) setAdditionalValidations({ diff --git a/tests/playwright/tests/columnBarcode.spec.ts b/tests/playwright/tests/columnBarcode.spec.ts index 18aac6e2fe..52cc5e5be2 100644 --- a/tests/playwright/tests/columnBarcode.spec.ts +++ b/tests/playwright/tests/columnBarcode.spec.ts @@ -6,15 +6,8 @@ import { GridPage } from '../pages/Dashboard/Grid'; interface ExpectedBarcodeData { referencedValue: string; barcodeSvg: string; - // barcodeSvgForModal: string; } -// interface ExpectedBarcodeDataWithOverlay extends ExpectedBarcodeData { -// barcodeSvgForModal: string; -// } - -// const ONE_SVG_BARCODE_HTML = `A Corua (La Corua)`; - test.describe('Virtual Columns', () => { let dashboard: DashboardPage; let grid: GridPage; @@ -27,7 +20,7 @@ test.describe('Virtual Columns', () => { }); test.describe('Barcode Column', () => { - const expectedBarcodeCellValues: ExpectedBarcodeData[] = [ + const initiallyExpectedBarcodeCellValues: ExpectedBarcodeData[] = [ { referencedValue: 'A Corua (La Corua)', barcodeSvg: @@ -44,16 +37,12 @@ test.describe('Virtual Columns', () => { referencedValue: 'Berlin', barcodeSvg: 'Berlin', - // barcodeSvgForOverlay: - // 'Berlin', }; const barcodeCellValuesForIstanbul = { referencedValue: 'Istanbul', barcodeSvg: 'Istanbul', - // barcodeSvgForOverlay: - // 'Berlin', }; const barcodeCode39SvgForBerlin = @@ -61,7 +50,7 @@ test.describe('Virtual Columns', () => { const expectedBarcodeCellValuesAfterCityNameChange = [ barcodeCellValuesForBerlin, - ...expectedBarcodeCellValues.slice(1), + ...initiallyExpectedBarcodeCellValues.slice(1), ]; async function barcodeColumnVerify(barcodeColumnTitle: string, expectedBarcodeCodeData: ExpectedBarcodeData[]) { @@ -74,7 +63,7 @@ test.describe('Virtual Columns', () => { } } test('creation, showing, updating value and change barcode column title and reference column', async () => { - // Add qr code column referencing the City column + // Add barcode code column referencing the City column // and compare the base64 encoded codes/src attributes for the first 3 rows. // Column data from City table (Sakila DB) /** @@ -94,7 +83,7 @@ test.describe('Virtual Columns', () => { barcodeValueColumnTitle: 'City', }); - await barcodeColumnVerify('Barcode1', expectedBarcodeCellValues); + await barcodeColumnVerify('Barcode1', initiallyExpectedBarcodeCellValues); await grid.cell.fillText({ columnHeader: 'City', index: 0, text: 'Berlin' }); @@ -105,7 +94,7 @@ test.describe('Virtual Columns', () => { await barcodeGridOverlay.verifyBarcodeSvgValue(barcodeCellValuesForBerlin.barcodeSvg); await barcodeGridOverlay.clickCloseButton(); - // Change the QR Code column title + // Change the barcode column title await grid.column.openEdit({ title: 'Barcode1' }); await grid.column.fillTitle({ title: 'Barcode1 Renamed' }); await grid.column.save({ isUpdated: true }); @@ -128,7 +117,7 @@ test.describe('Virtual Columns', () => { await dashboard.closeTab({ title: 'City' }); }); - test('deletion of the barcode column: directly and indirectly when the reference value column is deleted', async () => { + test('deletion of the barcode column: a) directly and b) indirectly when the reference value column is deleted', async () => { await dashboard.closeTab({ title: 'Team & Auth' }); await dashboard.treeView.openTable({ title: 'City' }); From cd9ea66947ead051aa809cf277a3b7631cb580a6 Mon Sep 17 00:00:00 2001 From: flisowna Date: Mon, 12 Dec 2022 23:05:22 +0300 Subject: [PATCH 21/31] clean code --- .../pages/Dashboard/Grid/Column/index.ts | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/tests/playwright/pages/Dashboard/Grid/Column/index.ts b/tests/playwright/pages/Dashboard/Grid/Column/index.ts index 8d9712e650..59d19d443c 100644 --- a/tests/playwright/pages/Dashboard/Grid/Column/index.ts +++ b/tests/playwright/pages/Dashboard/Grid/Column/index.ts @@ -112,12 +112,6 @@ export class ColumnPageObject extends BasePage { hasText: new RegExp(`^${barcodeValueColumnTitle}$`), }) .click(); - // await this.get().locator('.ant-select-single').nth(2).click(); - // await this.rootPage - // .locator(`.ant-select-item`, { - // hasText: new RegExp(`^${barcodeFormat}$`), - // }) - // .click(); break; case 'Lookup': await this.get().locator('.ant-select-single').nth(1).click(); @@ -285,14 +279,6 @@ export class ColumnPageObject extends BasePage { }) .click(); break; - // case 'Barcode': - // await this.get().locator('.ant-select-single').nth(1).click(); - // await this.rootPage - // .locator(`.ant-select-item`, { - // hasText: format, - // }) - // .click(); - // break; default: break; } From 27f3d53ca625c736c84c50d6a356ce0496e3df01 Mon Sep 17 00:00:00 2001 From: flisowna Date: Wed, 21 Dec 2022 13:44:02 +0100 Subject: [PATCH 22/31] adjust to PR comments --- .../smartsheet/column/BarcodeOptions.vue | 24 ++++++++++++------- .../virtual-cell/barcode/JsBarcodeWrapper.vue | 10 +++----- .../v2/nc_023_barcode_column_type.ts | 1 - .../nocodb/src/lib/models/BarcodeColumn.ts | 3 +-- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue b/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue index 79de2228de..95ea238db3 100644 --- a/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue +++ b/packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue @@ -2,7 +2,7 @@ import type { UITypes } from 'nocodb-sdk' import { AllowedColumnTypesForQrAndBarcodes } from 'nocodb-sdk' import type { SelectProps } from 'ant-design-vue' -import { useVModel } from '#imports' +import { onMounted, useVModel, watch } from '#imports' const props = defineProps<{ modelValue: any @@ -22,7 +22,7 @@ const vModel = useVModel(props, 'modelValue', emit) const { setAdditionalValidations, validateInfos, column } = useColumnCreateStoreOrThrow() -const columnsAllowedAsQrValue = computed(() => { +const columnsAllowedAsBarcodeValue = computed(() => { return fields.value ?.filter( (el) => @@ -52,7 +52,18 @@ const supportedBarcodeFormats = [ onMounted(() => { // set default value - vModel.value.fk_barcode_value_column_id = (column?.value?.colOptions as Record)?.fk_barcode_value_column_id || '' + vModel.value.meta = { + barcodeFormat: supportedBarcodeFormats[0].value, + ...vModel.value.meta, + } + vModel.value.fk_barcode_value_column_id = + (column?.value?.colOptions as Record)?.fk_barcode_value_column_id || columnsAllowedAsBarcodeValue.value?.[0] +}) + +watch(columnsAllowedAsBarcodeValue, (newColumnsAllowedAsBarcodeValue) => { + if (vModel.value.fk_barcode_value_column_id == null) { + vModel.value.fk_barcode_value_column_id = newColumnsAllowedAsBarcodeValue?.[0].value + } }) setAdditionalValidations({ @@ -61,10 +72,6 @@ setAdditionalValidations({ }) // set default meta value -vModel.value.meta = { - barcodeFormat: supportedBarcodeFormats[0].value, - ...vModel.value.meta, -}