UX/UI updates and rollup config changes to exclude common warnings

This commit is contained in:
Dean 2022-10-06 09:54:43 +01:00
parent 644d0f2bdd
commit e060db2929
4 changed files with 202 additions and 94 deletions

View File

@ -3168,24 +3168,39 @@
"section" "section"
], ],
"settings": [ "settings": [
{
"type": "text",
"label": "Label",
"key": "label",
"defaultValue": true
},
{ {
"type": "field/code", "type": "field/code",
"label": "Field", "label": "Field",
"key": "field", "key": "field",
"required": true "required": true
}, },
{
"type": "text",
"label": "Label",
"key": "label"
},
{
"type": "text",
"label": "Button",
"key": "scanButtonText"
},
{
"type": "text",
"label": "Default value",
"key": "defaultValue"
},
{ {
"type": "boolean", "type": "boolean",
"label": "Disabled", "label": "Disabled",
"key": "disabled", "key": "disabled",
"defaultValue": false "defaultValue": false
}, },
{
"type": "boolean",
"label": "Allow manual entry",
"key": "allowManualEntry",
"defaultValue": false
},
{ {
"type": "validation/string", "type": "validation/string",
"label": "Validation", "label": "Validation",

View File

@ -27,6 +27,15 @@ export default {
file: `./dist/budibase-client.js`, file: `./dist/budibase-client.js`,
}, },
], ],
onwarn(warning, warn) {
if (
warning.code === "THIS_IS_UNDEFINED" ||
warning.code === "CIRCULAR_DEPENDENCY"
) {
return
}
warn(warning)
},
plugins: [ plugins: [
alias({ alias({
entries: [ entries: [

View File

@ -1,123 +1,189 @@
<script> <script>
import { ModalContent, Modal, Select } from "@budibase/bbui" import { ModalContent, Modal, Icon, ActionButton } from "@budibase/bbui"
import { Input, Button, StatusLight } from "@budibase/bbui" import { Input, Button, StatusLight } from "@budibase/bbui"
import { Html5Qrcode } from "html5-qrcode" import { Html5Qrcode } from "html5-qrcode"
export let code = "" export let value
export let disabled = false
export let allowManualEntry = false
export let scanButtonText = "Scan Code"
import { createEventDispatcher } from "svelte"
const dispatch = createEventDispatcher()
let videoEle let videoEle
let camModal let camModal
let manualMode = false let manualMode = false
let enabled = false let cameraEnabled
let cameraInit = false let cameraStarted = false
let html5QrCode let html5QrCode
let cameraId let cameraSetting = { facingMode: "environment" }
let cameraDevices = [] let cameraConfig = {
let selectedCam fps: 25,
qrbox: { width: 250, height: 250 },
}
const onScanSuccess = decodedText => {
if (value != decodedText) {
dispatch("change", decodedText)
}
}
const initReader = async () => {
if (html5QrCode) {
html5QrCode.stop()
}
html5QrCode = new Html5Qrcode("reader")
return new Promise(resolve => {
html5QrCode
.start(cameraSetting, cameraConfig, onScanSuccess)
.then(() => {
resolve({ initialised: true })
})
.catch(err => {
console.log("There was a problem scanning the image", err)
resolve({ initialised: false })
})
})
}
const checkCamera = async () => { const checkCamera = async () => {
return new Promise(resolve => { return new Promise(resolve => {
Html5Qrcode.getCameras() Html5Qrcode.getCameras()
.then(devices => { .then(devices => {
if (devices && devices.length) { if (devices && devices.length) {
cameraDevices = devices
cameraId = devices[0].id
resolve({ enabled: true }) resolve({ enabled: true })
} }
}) })
.catch(() => { .catch(e => {
console.error(e)
resolve({ enabled: false }) resolve({ enabled: false })
}) })
}) })
} }
$: if (enabled && videoEle && !cameraInit) { const start = async () => {
html5QrCode = new Html5Qrcode("reader") const status = await initReader()
html5QrCode cameraStarted = status.initialised
.start(
cameraId,
{
fps: 25,
qrbox: { width: 250, height: 250 },
},
(decodedText, decodedResult) => {
code = decodedText
console.log(decodedText, decodedResult)
} }
)
.catch(err => { $: if (cameraEnabled && videoEle && !cameraStarted) {
console.log("There was a problem scanning the image", err) start()
})
} }
const showReaderModal = async () => { const showReaderModal = async () => {
camModal.show() camModal.show()
const camStatus = await checkCamera() const camStatus = await checkCamera()
enabled = camStatus.enabled cameraEnabled = camStatus.enabled
} }
const hideReaderModal = async () => { const hideReaderModal = async () => {
camModal.hide() cameraEnabled = undefined
cameraStarted = false
if (html5QrCode) {
await html5QrCode.stop() await html5QrCode.stop()
html5QrCode = undefined
}
camModal.hide()
} }
</script> </script>
<div class="scanner-video-wrapper"> <div class="scanner-video-wrapper">
{#if code} {#if value && !manualMode}
<div class="scanner-value"> <div class="scanner-value field-display">
<StatusLight positive /> <StatusLight positive />
{code} {value}
</div> </div>
{/if} {/if}
<Button primary icon="Camera" on:click={showReaderModal}>Scan Code</Button>
{#if allowManualEntry && manualMode}
<div class="manual-input">
<Input
bind:value
on:change={() => {
dispatch("change", value)
}}
/>
</div>
{/if}
{#if value}
<ActionButton
on:click={() => {
dispatch("change", "")
}}
{disabled}
>
Clear
</ActionButton>
{:else}
<ActionButton
icon="Camera"
on:click={() => {
showReaderModal()
}}
{disabled}
>
{scanButtonText}
</ActionButton>
{/if}
</div> </div>
<div class="modal-wrap"> <div class="modal-wrap">
<Select
on:change={e => console.log(e)}
value={selectedCam}
options={cameraDevices}
getOptionLabel={() => cameraDevices}
/>
<Modal bind:this={camModal} on:hide={hideReaderModal}> <Modal bind:this={camModal} on:hide={hideReaderModal}>
<ModalContent <ModalContent
title="Scan Code" title={scanButtonText}
showCancelButton={false}
showConfirmButton={false} showConfirmButton={false}
showCancelButton={false}
> >
<div id="reader" bind:this={videoEle} /> <div id="reader" class="container" bind:this={videoEle}>
<div class="code-wrap"> <div class="camera-placeholder">
{#if manualMode} <Icon size="XXL" name="Camera" />
<Input label="Enter" bind:value={code} /> {#if cameraEnabled === false}
<div>Your camera is disabled.</div>
{/if} {/if}
{#if code} </div>
</div>
{#if cameraEnabled === true}
<div class="code-wrap">
{#if value}
<div class="scanner-value"> <div class="scanner-value">
<StatusLight positive /> <StatusLight positive />
{code} {value}
</div> </div>
{/if} {:else}
{#if !code && enabled && videoEle && cameraInit}
<div class="scanner-value"> <div class="scanner-value">
<StatusLight neutral /> <StatusLight neutral />
Searching for code... Searching for code...
</div> </div>
{/if} {/if}
</div> </div>
{/if}
<div slot="footer"> <div slot="footer">
<div class="footer-buttons"> <div class="footer-buttons">
{#if allowManualEntry}
<Button <Button
group group
secondary secondary
newStyles newStyles
on:click={() => { on:click={() => {
manualMode = !manualMode manualMode = !manualMode
camModal.hide()
}} }}
> >
Enter Manually Enter Manually
</Button> </Button>
{/if}
<Button group cta disabled={!code}>Confirm</Button> <Button
group
cta
on:click={() => {
camModal.hide()
}}
>
Confirm
</Button>
</div> </div>
</div> </div>
</ModalContent> </ModalContent>
@ -125,17 +191,45 @@
</div> </div>
<style> <style>
#reader :global(video) {
border-radius: 4px;
border: var(--border-light-2);
overflow: hidden;
}
.field-display :global(.spectrum-Tags-item) {
margin: 0px;
}
.footer-buttons { .footer-buttons {
display: flex; display: flex;
grid-area: buttonGroup; grid-area: buttonGroup;
gap: var(--spectrum-global-dimension-static-size-200); gap: var(--spectrum-global-dimension-static-size-200);
} }
.scanner-value { .scanner-value {
display: flex;
}
.field-display {
padding-top: var( padding-top: var(
--spectrum-fieldlabel-side-m-padding-top, --spectrum-fieldlabel-side-m-padding-top,
var(--spectrum-global-dimension-size-100) var(--spectrum-global-dimension-size-100)
); );
display: flex;
margin-bottom: var(--spacing-m); margin-bottom: var(--spacing-m);
} }
.camera-placeholder {
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
border: var(--border-light-2);
background-color: var(--spectrum-global-color-gray-200);
flex-direction: column;
gap: var(--spectrum-global-dimension-static-size-200);
}
.container,
.camera-placeholder {
width: 100%;
min-height: 240px;
}
.manual-input {
padding-bottom: var(--spacing-m);
}
</style> </style>

View File

@ -9,34 +9,18 @@
export let validation export let validation
export let defaultValue = "" export let defaultValue = ""
export let onChange export let onChange
export let allowManualEntry
export let scanButtonText
let fieldState let fieldState
let fieldApi let fieldApi
let scannedCode const handleUpdate = e => {
let loaded = false const changed = fieldApi.setValue(e.detail)
const handleInput = () => {
const changed = fieldApi.setValue(scannedCode)
if (onChange && changed) { if (onChange && changed) {
onChange({ value: scannedCode }) onChange({ value: e.detail })
} }
} }
$: if (!loaded && !scannedCode && fieldState?.value) {
scannedCode = fieldState.value + ""
loaded = true
}
/*
QR Nimiq has rollup issues?
QR qrcodejs 12b bundle?
https://github.com/davidshimjs/qrcodejs
BOTH html5-qrcode has a 330k bundle
https://github.com/mebjas/html5-qrcode
BOTH zxing 360k bundle size
https://github.com/zxing-js/library
*/
</script> </script>
<Field <Field
@ -50,6 +34,12 @@
bind:fieldApi bind:fieldApi
> >
{#if fieldState} {#if fieldState}
<CodeScanner bind:code={scannedCode} on:input={handleInput} /> <CodeScanner
value={fieldState.value}
on:change={handleUpdate}
disabled={fieldState.disabled}
{allowManualEntry}
{scanButtonText}
/>
{/if} {/if}
</Field> </Field>