| | |
| | | |
| | | this.user = window.auth.getUser(); |
| | | |
| | | if (!this.user) { |
| | | return; |
| | | } |
| | | |
| | | |
| | | this.canUpdateUI = true; |
| | | this.isProcessing = false; |
| | |
| | | this.queue = new Map(); |
| | | this.items = new Map(); |
| | | this.subscribers = new Set(); |
| | | this.loadFromStorage = false; |
| | | |
| | | this.api = jvbSettings.api; |
| | | this.endpoint = 'queue'; |
| | | |
| | | this.queueItems = new Map(); |
| | | |
| | | this.init(); |
| | | } |
| | | init() { |
| | |
| | | count: '.qtoggle .count' |
| | | }, |
| | | refresh: { |
| | | button: '#queue .refresh .refreshNow', |
| | | countdown: '#queue .refresh .countdown' |
| | | button: '#queue .m-actions .refresh', |
| | | countdown: '#queue .m-actions .refresh .countdown' |
| | | }, |
| | | popup: { |
| | | popup: '#queue .popup', |
| | |
| | | window.addEventListener('online', this.onlineHandler); |
| | | window.addEventListener('offline', this.offlineHandler); |
| | | |
| | | window.addEventListener('beforeunload', this.unloadHandler); |
| | | // window.addEventListener('beforeunload', this.unloadHandler); |
| | | |
| | | document.addEventListener('visibilitychange', this.visibilityHandler); |
| | | } |
| | |
| | | keyPath: 'id', |
| | | endpoint: this.endpoint, |
| | | TTL: Infinity, |
| | | isAuth: true, |
| | | indexes: [ |
| | | {name: 'status', keyPath: 'status'}, |
| | | {name: 'type', keyPath: 'type'}, |
| | |
| | | } |
| | | |
| | | try { |
| | | const response = await fetch( |
| | | const response = await window.auth.fetch( |
| | | `${this.api}${this.endpoint}`, |
| | | { |
| | | method: 'POST', |
| | |
| | | this.updateOperationStatus(operation.id, 'uploading'); |
| | | |
| | | let requestBody; |
| | | let req; |
| | | if (operation.data instanceof FormData) { |
| | | operation.data.append('id', operation.id); |
| | | operation.data.append('user', window.auth.getUser()); |
| | | requestBody = operation.data; |
| | | req = operation.data; |
| | | } else { |
| | | requestBody = JSON.stringify({ |
| | | req = { |
| | | ...operation.data, |
| | | id: operation.id, |
| | | user: window.auth.getUser() |
| | | }); |
| | | }; |
| | | requestBody = JSON.stringify(req); |
| | | operation.headers['Content-Type'] = 'application/json'; |
| | | } |
| | | if (requestBody === undefined || requestBody === null) return; |
| | | if (operation.endpoint === 'unknown' || requestBody === undefined || requestBody === null) return; |
| | | |
| | | const response = await fetch( |
| | | |
| | | const response = await window.auth.fetch( |
| | | `${this.api}${operation.endpoint}`, |
| | | { |
| | | method: operation.method, |
| | |
| | | body: requestBody |
| | | } |
| | | ); |
| | | console.log('Sending request with data: ', req); |
| | | const result = await response.json(); |
| | | if (skip) { |
| | | operation.data = {}; |
| | | } |
| | | console.log('Result: ', result); |
| | | if (response.ok && result.success) { |
| | | this.notify('sent-to-server', req); |
| | | if (result.id && operation.id !== result.id) { |
| | | operation = await this.handleServerMerge(operation, result); |
| | | } else { |
| | |
| | | } |
| | | |
| | | getAllQueue() { |
| | | let ops = [... new Set([ |
| | | ...Array.from(this.store.data.values()), |
| | | let index = new Set(); |
| | | |
| | | let ops = [ |
| | | ... Array.from(this.queue.values()) |
| | | ])]; |
| | | ]; |
| | | if (!this.loadFromStorage) { |
| | | this.loadFromStorage = true; |
| | | ops = [ |
| | | ... ops, |
| | | ...Array.from(this.store.data.values()) |
| | | ]; |
| | | |
| | | ops = ops.filter(el => { |
| | | const isAdded = index.has(el.id); |
| | | index.add(el.id); |
| | | return !isAdded; |
| | | }); |
| | | } |
| | | //Sort operations by operation updated_at |
| | | return this.sortOperations(ops); |
| | | } |
| | |
| | | status = [status]; |
| | | } |
| | | |
| | | let ops = [...new Set([ |
| | | ...Array.from(this.store.filterByIndex({status: status})), |
| | | ...Array.from(this.queue.values()).filter(op => status.includes(op.status)) |
| | | ])]; |
| | | return this.sortOperations(ops); |
| | | let ops = this.getAllQueue(); |
| | | return ops.filter(op => status.includes(op.status)); |
| | | } |
| | | |
| | | |
| | | updateOperationStatus(itemID, status) { |
| | | let item = this.getQueue(itemID); |
| | | if (!item || !this.statuses.includes(status)) return; |
| | | if (!item) return; |
| | | if (!this.statuses.includes(status)) { |
| | | console.log('Invalid status: ', status); |
| | | return; |
| | | } |
| | | |
| | | item.status = status; |
| | | this.notify('operation-status', item); |
| | | this.setQueue(item); |
| | |
| | | try { |
| | | this.ui.refresh.button.classList.add('fetching'); |
| | | this.store.clearCache(); |
| | | await this.store.fetch(); |
| | | let response = await this.store.fetch(); |
| | | if (response.status === 429) { |
| | | console.log('Too many requests. Waiting 30 seconds'); |
| | | this.stopPolling(); |
| | | this.startCountdown(30, () => this.runPollCycle()); |
| | | return; |
| | | } |
| | | |
| | | this.ui.refresh.button.classList.remove('fetching'); |
| | | if (!this.maybeStartPolling()) { |
| | | this.stopPolling(); |
| | |
| | | this.ui.actions.retry.disabled = operations.filter(op => op.status === 'failed').length === 0; |
| | | this.ui.actions.clear.disabled = operations.filter(op => op.status === 'completed').length ===0; |
| | | |
| | | const activeCount = operations.filter(op => |
| | | let activeCount = operations.filter(op => |
| | | [...this.pendingStatuses, ...this.workingStatuses].includes(op.status) |
| | | ).length; |
| | | ); |
| | | activeCount = activeCount.length; |
| | | this.ui.toggle.count.hidden = activeCount === 0; |
| | | this.ui.toggle.count.textContent = activeCount; |
| | | |
| | |
| | | let op = this.getQueue(opId); |
| | | |
| | | let element = item.element; |
| | | element.classList.remove(this.statuses); |
| | | |
| | | element.classList.remove(... this.statuses); |
| | | element.classList.add(op.status); |
| | | |
| | | let progress = this.getProgress(op); |
| | |
| | | // Auto-dismiss merged operation after brief display |
| | | // The target operation already has all the merged data from server |
| | | setTimeout(() => { |
| | | this.store.delete(operation.id); |
| | | this.clearQueue(operation.id); |
| | | this.removeOperationFromUI(operation.id); |
| | | }, 3000); |
| | | } |