qrcode: add retry button to refetch metadata on error (#86091)
gitea/passerelle/pipeline/head This commit looks good
Details
gitea/passerelle/pipeline/head This commit looks good
Details
This commit is contained in:
parent
3729c4605d
commit
96c1e49e23
|
@ -12,6 +12,12 @@ qrcode-reader {
|
||||||
display: grid;
|
display: grid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%button {
|
||||||
|
margin: 5px 10px 10px 10px;
|
||||||
|
padding: 5px;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
.qrcode-reader {
|
.qrcode-reader {
|
||||||
|
|
||||||
&--video-wrapper {
|
&--video-wrapper {
|
||||||
|
@ -115,9 +121,7 @@ qrcode-reader {
|
||||||
}
|
}
|
||||||
|
|
||||||
&--close-popup-button {
|
&--close-popup-button {
|
||||||
margin: 5px 10px 10px 10px;
|
@extend %button;
|
||||||
padding: 5px;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,10 +235,21 @@ qrcode-reader-validity {
|
||||||
qrcode-reader-data {
|
qrcode-reader-data {
|
||||||
.qrcode-reader-section--content {
|
.qrcode-reader-section--content {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: auto 1fr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.qrcode-reader-data {
|
.qrcode-reader-data {
|
||||||
|
&--retry-button {
|
||||||
|
@extend %button;
|
||||||
|
font-size: 1rem;
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
&--items {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
&--item-label {
|
&--item-label {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
justify-self: end;
|
justify-self: end;
|
||||||
|
@ -245,4 +260,8 @@ qrcode-reader-data {
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.qrcode-reader-section.error .qrcode-reader-data--retry-button {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -405,6 +405,11 @@ class QRCodeReaderValidity extends QRCodeReaderSection {
|
||||||
window.customElements.define('qrcode-reader-validity', QRCodeReaderValidity)
|
window.customElements.define('qrcode-reader-validity', QRCodeReaderValidity)
|
||||||
|
|
||||||
|
|
||||||
|
const dataTemplate = template(`
|
||||||
|
<button class="qrcode-reader-data--retry-button">${translate('retry')}</button>
|
||||||
|
<div class="qrcode-reader-data--items"></div>
|
||||||
|
`)
|
||||||
|
|
||||||
const dataItemTemplate = template(`
|
const dataItemTemplate = template(`
|
||||||
<span class="qrcode-reader-data--item-label">{label} : </span>
|
<span class="qrcode-reader-data--item-label">{label} : </span>
|
||||||
<span class="qrcode-reader-data--item-value">{value}</span>
|
<span class="qrcode-reader-data--item-value">{value}</span>
|
||||||
|
@ -418,24 +423,32 @@ class QRCodeReaderData extends QRCodeReaderSection {
|
||||||
|
|
||||||
async refresh(data, metadataUrl, certificateUUID) {
|
async refresh(data, metadataUrl, certificateUUID) {
|
||||||
this.reset()
|
this.reset()
|
||||||
this.contentElement.innerHTML = ''
|
const contentElement = dataTemplate.content.cloneNode(true)
|
||||||
|
const itemsElement = contentElement.querySelector('.qrcode-reader-data--items')
|
||||||
|
const retryButton = contentElement.querySelector('.qrcode-reader-data--retry-button')
|
||||||
|
|
||||||
|
retryButton.addEventListener('click', () => {
|
||||||
|
this.refresh(data, metadataUrl, certificateUUID)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.setContent(contentElement)
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(data)) {
|
for (const [key, value] of Object.entries(data)) {
|
||||||
this.#addItem(key, value)
|
this.#addItem(itemsElement, key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.load(async () => {
|
await this.load(async () => {
|
||||||
await this.#showMetadata(metadataUrl, certificateUUID)
|
await this.#showMetadata(itemsElement, metadataUrl, certificateUUID)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#addItem(label, value) {
|
#addItem(itemsElement, label, value) {
|
||||||
const dataItem = dataItemTemplate.cloneNode(true)
|
const dataItem = dataItemTemplate.cloneNode(true)
|
||||||
dataItem.innerHTML = dataItem.innerHTML.replace('{label}', label).replace('{value}', value)
|
dataItem.innerHTML = dataItem.innerHTML.replace('{label}', label).replace('{value}', value)
|
||||||
this.contentElement.append(dataItem.content)
|
itemsElement.append(dataItem.content)
|
||||||
}
|
}
|
||||||
|
|
||||||
async #showMetadata(metadataUrl, certificateUUID) {
|
async #showMetadata(itemsElement, metadataUrl, certificateUUID) {
|
||||||
if(metadataUrl === null) {
|
if(metadataUrl === null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -446,7 +459,7 @@ class QRCodeReaderData extends QRCodeReaderSection {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(metadata)) {
|
for (const [key, value] of Object.entries(metadata)) {
|
||||||
this.#addItem(key, value)
|
this.#addItem(itemsElement, key, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,7 +487,6 @@ class QRCodeReaderData extends QRCodeReaderSection {
|
||||||
|
|
||||||
return metadata
|
return metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
window.customElements.define('qrcode-reader-data', QRCodeReaderData)
|
window.customElements.define('qrcode-reader-data', QRCodeReaderData)
|
||||||
|
|
|
@ -382,6 +382,37 @@ qrcodeReaderMetadataTest("qrcode reader doesn't refetch metadata for the same ce
|
||||||
expect(reader.querySelectorAll('.qrcode-reader-data--item-value').length).toStrictEqual(3)
|
expect(reader.querySelectorAll('.qrcode-reader-data--item-value').length).toStrictEqual(3)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
qrcodeReaderMetadataTest('retry button refetches metadata', async ({mock, loadMetadata}) => {
|
||||||
|
const { reader, scan } = mock
|
||||||
|
|
||||||
|
await loadMetadata(okCodeData, async (url) => {
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
json: () => new Promise((resolve) => {
|
||||||
|
resolve({'err': 1})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const section = reader.querySelector('qrcode-reader-data .qrcode-reader-section')
|
||||||
|
expect(section.classList.contains('error')).toBe(true)
|
||||||
|
|
||||||
|
const retryButton = reader.querySelector('.qrcode-reader-data--retry-button')
|
||||||
|
expect(retryButton).not.toBe(null)
|
||||||
|
|
||||||
|
fetch.mockImplementationOnce(async (url) => {
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
json: async () => ({'err': 0, 'data': {'Classe': 'Oui', 'Ravioles': 'Non'}})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
retryButton.dispatchEvent(new Event('click'))
|
||||||
|
await new Promise(resolve => setTimeout(resolve))
|
||||||
|
|
||||||
|
expect(section.classList.contains('error')).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
const qrcodeReaderTallyTest = qrcodeReaderTest.extend({
|
const qrcodeReaderTallyTest = qrcodeReaderTest.extend({
|
||||||
loadTally: async ({ task, mock }, use) => {
|
loadTally: async ({ task, mock }, use) => {
|
||||||
const loadTally = async (qrCodeData, mockFetch) => {
|
const loadTally = async (qrCodeData, mockFetch) => {
|
||||||
|
|
Loading…
Reference in New Issue