| | |
| | | |
| | | this.isRestoring = false; |
| | | this.hasListeners = false; |
| | | this.hasUploads = false; |
| | | this.summaryTemplate = false; |
| | | |
| | | this.init(); |
| | |
| | | this.initListeners(); |
| | | this.initStore(); |
| | | this.initValidators(); |
| | | this.initUploadSubscription(); |
| | | } |
| | | |
| | | initUploadSubscription() { |
| | | window.jvbUploads.subscribe((event, data) => { |
| | | if (!this.hasUploads) return; |
| | | if (event === 'upload-received') { |
| | | let form = this.getForm(data.field); |
| | | if (form) { |
| | | this.updateItem(`${data.field.dataset.field}_tempUpload`, data.id, form); |
| | | } |
| | | |
| | | } |
| | | }); |
| | | } |
| | | initElements() { |
| | | this.inputSelectors = 'input, textarea, select'; |
| | |
| | | status: '.fstatus', |
| | | message: '.fstatus .message', |
| | | icon: '.fstatus .icon', |
| | | actions: '.fstatus .actions' |
| | | actions: '.fstatus .actions', |
| | | }, |
| | | restore: { |
| | | container: '.restore-form', |
| | | restore: '[data-action="restore"]', |
| | | clear: '[data-action="clear"]', |
| | | } |
| | | }, |
| | | inputs: this.inputSelectors, //querySelectorAll |
| | |
| | | return; |
| | | } |
| | | |
| | | const notification = document.createElement('div'); |
| | | notification.className = 'pendingChanges'; |
| | | notification.innerHTML = ` |
| | | <p>We noticed unsaved changes from last time. Would you like to restore them?</p> |
| | | <button class="restore" type="button" data-form-id="${formId}">Restore</button> |
| | | <button class="discard" type="button" data-form-id="${formId}">Discard</button>`; |
| | | |
| | | element.insertBefore(notification, form.ui.status.status); |
| | | |
| | | notification.querySelector('.restore').addEventListener('click', async () => { |
| | | form.ui.restore.container.hidden = false; |
| | | const handleRestore = async (changes, element) => { |
| | | this.isRestoring = true; |
| | | |
| | | let theChanges = {['fields']: changes}; |
| | | await this.checkStoredUploads(changes, element); |
| | | this.populate.populate(element, theChanges); |
| | | this.a11y.announce('Previous changes restored'); |
| | | |
| | | this.isRestoring = false; |
| | | notification.remove(); |
| | | }); |
| | | |
| | | notification.querySelector('.discard').addEventListener('click', async () => { |
| | | form.ui.restore.container.remove(); |
| | | }; |
| | | const clearRestore = async (formId) => { |
| | | await this.checkStoredUploads(changes, element, false); |
| | | await this.store.delete(formId); |
| | | this.a11y.announce('Previous changes discarded'); |
| | | notification.remove(); |
| | | }); |
| | | form.ui.restore.container.remove(); |
| | | }; |
| | | form.ui.restore.restore.addEventListener('click', () => handleRestore(changes, element)); |
| | | form.ui.restore.clear.addEventListener('click', async () => clearRestore(formId)); |
| | | } |
| | | async checkStoredUploads(changes, element, restore = true) { |
| | | let form = this.forms.get(element.dataset.formId); |
| | | if (!form) return; |
| | | let uploads = []; |
| | | for (let [key, value] of Object.entries(changes)) { |
| | | if (key.includes('_tempUpload')) { |
| | | let field = key.replace('_tempUpload', ''); |
| | | |
| | | if (Object.hasOwn(form.ui.uploads, field)) { |
| | | uploads.push(value); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (uploads.length > 0) { |
| | | if (restore) { |
| | | await window.jvbUploads.restoreUploads(uploads); |
| | | } else { |
| | | await window.jvbUploads.clearUploads(uploads); |
| | | } |
| | | |
| | | } |
| | | } |
| | | initValidators() { |
| | | this.validators = { |
| | |
| | | * @param form |
| | | */ |
| | | updateItem(name, value, form) { |
| | | if (value === undefined) return; |
| | | if (!this.changes.has(form.id)) { |
| | | this.changes.set(form.id, { |
| | | id: form.id, |
| | |
| | | } |
| | | } |
| | | checkForImageUploads(form, config) { |
| | | this.hasUploads = true; |
| | | window.jvbUploads.scanFields(form, config.options.autoUpload, config.options.imageMeta); |
| | | let uploads = form.querySelectorAll('[data-field-type="upload"]'); |
| | | if (uploads) { |
| | | config.ui.uploads = {}; |
| | | uploads.forEach(upload => { |
| | | config.ui.uploads[upload.dataset.field] = upload; |
| | | }); |
| | | } |
| | | } |
| | | |
| | | checkForTabs(form, config) { |
| | |
| | | return this.getTagListValue(element, conf); |
| | | |
| | | case 'group': |
| | | return null; |
| | | //Do we actually need anything here? I think each subfield just |
| | | break; |
| | | |
| | | case 'location': |
| | | return this.getLocationValue(element, conf); |
| | |
| | | if (element.tagName !== 'INPUT' || element.type !== 'hidden'){ |
| | | element = element.querySelector('input[type="hidden"][name="'+fieldName+'"]'); |
| | | if (!element) { |
| | | return; |
| | | return null; |
| | | } |
| | | } |
| | | |