-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add QR code generation and scanning to UI (#808)
* Add clickable QRCode modal in navbar * Add qr code library * Add QRCodeModal component to formatted refcode * Add QRScanner functionality using `vue-qrcode-reader` * Add QR scanning from image * Add alert and spinner to handle camera authorisation/availaility * Add textual label to QRCode * Update default pURL resolver * Add query parameter redirect-to-ui to `/items` endpoint to allow link resolver to work more smoothly * List all QR codes in stream * Use auxiliary variable in store to map refcodes to IDs * Make sure item_id is set at top level of item response when querying by refcode * Redirect to the correct UI URL * Update config for qr code resolver and add warnings if unconfigured
- Loading branch information
Showing
15 changed files
with
409 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
<template> | ||
<div class="text-center"> | ||
<QRCodeVue3 | ||
:value="QRCodeUrl" | ||
:width="width" | ||
:height="width" | ||
:qr-options="{ typeNumber: 0, mode: 'Byte', errorCorrectionLevel: 'H' }" | ||
:image-options="{ hideBackgroundDots: false, imageSize: 0, margin: 0 }" | ||
:dots-options="{ | ||
type: 'square', | ||
color: 'black', | ||
}" | ||
:background-options="{ color: '#ffffff' }" | ||
:corners-square-options="{ type: 'square', color: 'black' }" | ||
:corners-dot-options="{ type: 'square', color: 'black' }" | ||
file-ext="png" | ||
/> | ||
<div | ||
id="qrcode-text-label" | ||
:style="{ width: width }" | ||
class="qrcode-text-label mx-auto text-center center-text" | ||
> | ||
{{ refcode }} | ||
</div> | ||
</div> | ||
<div class="alert alert-info"> | ||
QR_CODE_RESOLVER_URL is not set for this deployment.<br /> | ||
Links embedded within QR codes generated here will only work if this <i>datalab</i> instance | ||
remains at the same URL.<br /><br /> | ||
|
||
Visit <a :href="federationQRCodeUrl">{{ federationQRCodeUrl }}</a> to learn about persistent URL | ||
resolution in <i>datalab</i>. | ||
</div> | ||
</template> | ||
|
||
<script> | ||
import QRCodeVue3 from "qrcode-vue3"; | ||
import { FEDERATION_QR_CODE_RESOLVER_URL, QR_CODE_RESOLVER_URL, API_URL } from "@/resources.js"; | ||
export default { | ||
name: "QRCode", | ||
components: { | ||
QRCodeVue3, | ||
}, | ||
props: { | ||
refcode: { | ||
type: String, | ||
required: true, | ||
}, | ||
width: { | ||
type: Number, | ||
default: 200, | ||
}, | ||
}, | ||
data() { | ||
return { | ||
federationQRCodeUrl: FEDERATION_QR_CODE_RESOLVER_URL, | ||
}; | ||
}, | ||
computed: { | ||
QRCodeUrl() { | ||
// If the QR_CODE_RESOLVER_URL is not set, use the API_URL | ||
// with the redirect-to-ui option | ||
if (QR_CODE_RESOLVER_URL == null) { | ||
return API_URL + "/items/" + this.refcode + "?redirect-to-ui=true"; | ||
} | ||
return QR_CODE_RESOLVER_URL + "/" + this.refcode; | ||
}, | ||
}, | ||
}; | ||
</script> | ||
|
||
<style scoped> | ||
.qrcode-text-label { | ||
font-family: "Helvetica", "Arial", "Roboto Mono"; | ||
font-size: 1.8rem; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
<template> | ||
<form class="modal-enclosure" data-testid="qrcode-form"> | ||
<Modal :model-value="modelValue" @update:model-value="$emit('update:modelValue', $event)"> | ||
<template #header>QR Code</template> | ||
<template #body> | ||
<div class="form-row"> | ||
<div ref="qrcode" class="form-group mx-auto" data-testid="qrcode"> | ||
<QRCode :refcode="refcode" /> | ||
</div> | ||
</div> | ||
</template> | ||
<template #footer> | ||
<button type="submit" class="btn btn-info" value="Print" @click="printQR">Print</button> | ||
<button | ||
type="button" | ||
class="btn btn-secondary" | ||
data-dismiss="modal" | ||
@click="$emit('update:modelValue', false)" | ||
> | ||
Close | ||
</button> | ||
</template> | ||
</Modal> | ||
</form> | ||
</template> | ||
|
||
<script> | ||
import Modal from "@/components/Modal.vue"; | ||
import QRCode from "@/components/QRCode.vue"; | ||
export default { | ||
name: "QRCodeModal", | ||
components: { | ||
QRCode, | ||
Modal, | ||
}, | ||
props: { | ||
modelValue: Boolean, | ||
refcode: { type: String, required: true }, | ||
}, | ||
emits: ["update:modelValue"], | ||
methods: { | ||
printQR() { | ||
const printContents = this.$refs.qrcode.innerHTML; | ||
const printWindow = window.open("", "", "height=400, width=800"); | ||
printWindow.document.write( | ||
"<html><head><title>QR Code</title></head><body>" + printContents + "</body></html>", | ||
); | ||
printWindow.document.close(); | ||
printWindow.print(); | ||
}, | ||
}, | ||
}; | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<template> | ||
<form class="modal-enclosure" data-testid="qrcode-scanner"> | ||
<Modal :model-value="modelValue" @update:model-value="$emit('update:modelValue', $event)"> | ||
<template #header>Scan QR Code</template> | ||
<template #body> | ||
<div v-if="modelValue" class="form-row"> | ||
<div v-if="decodedQRs != null"> | ||
<div> | ||
Decoded QRs: | ||
<ul> | ||
<li v-for="qr in decodedQRs" :key="qr"> | ||
<a :href="qr">{{ qr }}</a> | ||
</li> | ||
</ul> | ||
</div> | ||
</div> | ||
<div v-else> | ||
<div v-show="!cameraReady"> | ||
<font-awesome-icon | ||
v-if="!cameraReady" | ||
icon="spinner" | ||
class="fa-spin mx-auto" | ||
fixed-width | ||
style="color: gray" | ||
size="2x" | ||
/> | ||
<div class="alert alert-info text-center"> | ||
No camera available. You may need to allow this page to have camera access in your | ||
browser. | ||
</div> | ||
</div> | ||
<div | ||
v-show="cameraReady" | ||
ref="qrcode-scanner" | ||
class="form-group mx-auto" | ||
data-testid="qrcode-scanner" | ||
> | ||
<QrcodeStream @camera-on="cameraReady = true" @detect="onDetect" /> | ||
</div> | ||
<div ref="qrcode-upload" data-testid="qrcode-upload"> | ||
<div>Or upload an image:</div> | ||
<QrcodeCapture id="upload-qr" class="button button-default" @detect="onDetect" /> | ||
</div> | ||
</div> | ||
</div> | ||
</template> | ||
<template #footer> | ||
<button | ||
type="button" | ||
class="btn btn-secondary" | ||
data-dismiss="modal" | ||
@click="$emit('update:modelValue', false)" | ||
> | ||
Close | ||
</button> | ||
</template> | ||
</Modal> | ||
</form> | ||
</template> | ||
|
||
<script> | ||
import Modal from "@/components/Modal.vue"; | ||
import { QrcodeStream, QrcodeCapture } from "vue-qrcode-reader"; | ||
export default { | ||
name: "QRScannerModal", | ||
components: { | ||
Modal, | ||
QrcodeCapture, | ||
QrcodeStream, | ||
}, | ||
props: { | ||
modelValue: Boolean, | ||
}, | ||
emits: ["update:modelValue"], | ||
data() { | ||
return { | ||
decodedQRs: null, | ||
cameraReady: false, | ||
}; | ||
}, | ||
methods: { | ||
onDetect(detectedQRs) { | ||
// get all raw values from decoded QRs | ||
this.decodedQRs = detectedQRs.map((qr) => qr.rawValue); | ||
// Reset camera stream div | ||
this.cameraReady = false; | ||
}, | ||
}, | ||
}; | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.