diff --git a/packages/builder/src/builderStore/store/screenTemplates/utils/commonComponents.js b/packages/builder/src/builderStore/store/screenTemplates/utils/commonComponents.js index 9176d535ab..ac40a10fea 100644 --- a/packages/builder/src/builderStore/store/screenTemplates/utils/commonComponents.js +++ b/packages/builder/src/builderStore/store/screenTemplates/utils/commonComponents.js @@ -138,6 +138,7 @@ const fieldTypeToComponentMap = { attachment: "attachmentfield", link: "relationshipfield", json: "jsonfield", + barcodeqr: "codescanner", } export function makeDatasourceFormComponents(datasource) { diff --git a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte index 3fd38bddeb..b7249ad60c 100644 --- a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte +++ b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte @@ -261,6 +261,7 @@ } else { return [ FIELDS.STRING, + FIELDS.BARCODEQR, FIELDS.LONGFORM, FIELDS.OPTIONS, FIELDS.DATETIME, diff --git a/packages/builder/src/components/backend/TableNavigator/TableDataImport.svelte b/packages/builder/src/components/backend/TableNavigator/TableDataImport.svelte index 774aac0677..ea0ce59169 100644 --- a/packages/builder/src/components/backend/TableNavigator/TableDataImport.svelte +++ b/packages/builder/src/components/backend/TableNavigator/TableDataImport.svelte @@ -124,6 +124,14 @@ label: "Multi-select", value: FIELDS.ARRAY.type, }, + { + label: "Barcode/QR", + value: FIELDS.BARCODEQR.type, + }, + { + label: "Long Form Text", + value: FIELDS.LONGFORM.type, + }, ] diff --git a/packages/builder/src/components/design/settings/componentSettings.js b/packages/builder/src/components/design/settings/componentSettings.js index 56ae3de490..c3b81968f4 100644 --- a/packages/builder/src/components/design/settings/componentSettings.js +++ b/packages/builder/src/components/design/settings/componentSettings.js @@ -51,6 +51,7 @@ const componentMap = { "field/link": FormFieldSelect, "field/array": FormFieldSelect, "field/json": FormFieldSelect, + "field/barcode/qr": FormFieldSelect, // Some validation types are the same as others, so not all types are // explicitly listed here. e.g. options uses string validation "validation/string": ValidationEditor, diff --git a/packages/builder/src/components/design/settings/controls/FormFieldSelect.svelte b/packages/builder/src/components/design/settings/controls/FormFieldSelect.svelte index 1f08c56ff5..a02ea41099 100644 --- a/packages/builder/src/components/design/settings/controls/FormFieldSelect.svelte +++ b/packages/builder/src/components/design/settings/controls/FormFieldSelect.svelte @@ -24,18 +24,17 @@ const getOptions = (schema, type) => { let entries = Object.entries(schema ?? {}) - let types = [] - if (type === "field/options") { + if (type === "field/options" || type === "field/barcode/qr") { // allow options to be used on both options and string fields types = [type, "field/string"] } else { types = [type] } - types = types.map(type => type.split("/")[1]) - entries = entries.filter(entry => types.includes(entry[1].type)) + types = types.map(type => type.slice(type.indexOf("/") + 1)) + entries = entries.filter(entry => types.includes(entry[1].type)) return entries.map(entry => entry[0]) } diff --git a/packages/builder/src/constants/backend/index.js b/packages/builder/src/constants/backend/index.js index 28ce35d9f7..427e8d80a1 100644 --- a/packages/builder/src/constants/backend/index.js +++ b/packages/builder/src/constants/backend/index.js @@ -8,6 +8,15 @@ export const FIELDS = { presence: false, }, }, + BARCODEQR: { + name: "Barcode/QR", + type: "barcodeqr", + constraints: { + type: "string", + length: {}, + presence: false, + }, + }, LONGFORM: { name: "Long Form Text", type: "longform", @@ -148,6 +157,7 @@ export const ALLOWABLE_STRING_OPTIONS = [ FIELDS.STRING, FIELDS.OPTIONS, FIELDS.LONGFORM, + FIELDS.BARCODEQR, ] export const ALLOWABLE_STRING_TYPES = ALLOWABLE_STRING_OPTIONS.map( opt => opt.type diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/componentStructure.json b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/componentStructure.json index 088f0c0989..3d9cf7e2a3 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/componentStructure.json +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/componentStructure.json @@ -66,7 +66,8 @@ "relationshipfield", "datetimefield", "multifieldselect", - "s3upload" + "s3upload", + "codescanner" ] }, { diff --git a/packages/client/manifest.json b/packages/client/manifest.json index bd5854dc9f..0edb5c0f39 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -3157,6 +3157,56 @@ } ] }, + "codescanner": { + "name": "Barcode/QR Scanner", + "icon": "Camera", + "styles": [ + "size" + ], + "illegalChildren": [ + "section" + ], + "settings": [ + { + "type": "field/barcode/qr", + "label": "Field", + "key": "field", + "required": true + }, + { + "type": "text", + "label": "Label", + "key": "label" + }, + { + "type": "text", + "label": "Button text", + "key": "scanButtonText" + }, + { + "type": "text", + "label": "Default value", + "key": "defaultValue" + }, + { + "type": "boolean", + "label": "Disabled", + "key": "disabled", + "defaultValue": false + }, + { + "type": "boolean", + "label": "Allow manual entry", + "key": "allowManualEntry", + "defaultValue": false + }, + { + "type": "validation/string", + "label": "Validation", + "key": "validation" + } + ] + }, "embeddedmap": { "name": "Embedded Map", "icon": "Location", @@ -4399,7 +4449,9 @@ "formblock": { "name": "Form Block", "icon": "Form", - "styles": ["size"], + "styles": [ + "size" + ], "block": true, "info": "Form blocks are only compatible with internal or SQL tables", "settings": [ @@ -4407,7 +4459,11 @@ "type": "select", "label": "Type", "key": "actionType", - "options": ["Create", "Update", "View"], + "options": [ + "Create", + "Update", + "View" + ], "defaultValue": "Create" }, { diff --git a/packages/client/package.json b/packages/client/package.json index 3040a731a7..dca199527a 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -33,6 +33,7 @@ "apexcharts": "^3.22.1", "dayjs": "^1.10.5", "downloadjs": "1.4.7", + "html5-qrcode": "^2.2.1", "leaflet": "^1.7.1", "regexparam": "^1.3.0", "sanitize-html": "^2.7.0", diff --git a/packages/client/rollup.config.js b/packages/client/rollup.config.js index 5206b63884..be94ace90c 100644 --- a/packages/client/rollup.config.js +++ b/packages/client/rollup.config.js @@ -27,6 +27,15 @@ export default { file: `./dist/budibase-client.js`, }, ], + onwarn(warning, warn) { + if ( + warning.code === "THIS_IS_UNDEFINED" || + warning.code === "CIRCULAR_DEPENDENCY" + ) { + return + } + warn(warning) + }, plugins: [ alias({ entries: [ diff --git a/packages/client/src/components/app/forms/CodeScanner.svelte b/packages/client/src/components/app/forms/CodeScanner.svelte new file mode 100644 index 0000000000..5dff3a96fa --- /dev/null +++ b/packages/client/src/components/app/forms/CodeScanner.svelte @@ -0,0 +1,234 @@ + + +