/* * rhwebimport * * Copyright (C) 2014-2016 Christian Pointner * Copyright (C) 2015-2016 Peter Grassberger * * This file is part of rhwebimport. * * rhwebimport is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * rhwebimport is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with rhwebimport. If not, see . */ 'use strict'; var Rdxport = Rdxport || {}; Rdxport.Importer = function(username, token, rhimpordEndpoint) { this.username = username; this.token = token; this.rhimpordEndpoint = rhimpordEndpoint; this.$el = $('#uploadModal'); this.listWebSocket = null; this.uploads = []; this.initListWebSocket(); }; Rdxport.Importer.CMD_LIST = 'list'; Rdxport.Importer.CMD_NEW = 'new'; Rdxport.Importer.CMD_RECONNECT = 'reconnect'; Rdxport.Importer.ERROR_OK = 'ok'; Rdxport.Importer.ERROR_ERROR = 'error'; Rdxport.Importer.TYPE_ERROR = 'error'; Rdxport.Importer.TYPE_ACK = 'ack'; Rdxport.Importer.TYPE_LIST = 'list'; Rdxport.Importer.TYPE_PROGRESS = 'progress'; Rdxport.Importer.TYPE_DONE = 'done'; Rdxport.Importer.prototype.initListWebSocket = function() { var self = this; this.listWebSocket = new WebSocket(this.rhimpordEndpoint); this.listWebSocket.onclose = function(code, reason) { console.log('close'); console.log(code); console.log(reason); }; this.listWebSocket.onerror = function(error) { console.log('error'); console.log(error); }; this.listWebSocket.onopen = function() { var sendOptions = { COMMAND: Rdxport.Importer.CMD_LIST, LOGIN_NAME: importer.username, PASSWORD: importer.token }; this.send(JSON.stringify(sendOptions)); var self = this; setInterval(function() { self.send(JSON.stringify(sendOptions)); }, 3 * 1000); }; this.listWebSocket.onmessage = function(event) { var data = $.parseJSON(event.data); if (data.TYPE.toLowerCase() === Rdxport.Importer.TYPE_LIST) { $.each(data.SESSIONS, function(id, reference) { if (importer.getUploadById(id) !== null) { return true; //continue; } var reference = reference.split('/'); var groupName = reference[0]; var cartNumber = reference[1]; var filename = reference[2]; var groupViews = null; switch (router.activeRoute) { default: //fallthrough case 'shows': if (showListView) { groupViews = showListView.showViews; } case 'jingles': if (jingleGroupListView) { groupViews = jingleGroupListView.jingleGroupViews; } case 'musicpools': if (musicpoolsView) { groupViews = musicpoolsView.musicpoolViews; } } var groupView = groupViews.find(function (element) { return element.model.groupName === groupName; }); if (!groupView) { return true; //continue; } var group = groupView.model; var upload = new Rdxport.Upload('/' + filename, group, groupView, cartNumber, cartNumber, null); upload.reconnect(id, reference); self.uploads.push(upload); }); } }; }; Rdxport.Importer.prototype.resetModal = function() { $('div.modal-header h4', this.$el).text("Datei auswählen..."); $('.modal-body .drop', this.$el).css("background-image", "url('/img/dz-backdrop.png')"); $('.modal-body .drop form input[type="file"]', this.$el).val(''); $('.modal-body #sourceUri', this.$el).val(''); $('#uploadModal-confirm', this.$el).attr('disabled','disabled').off('click'); $('form input[type="file"]', this.$el).removeAttr('multiple'); }; Rdxport.Importer.prototype.openModal = function(group, groupView, cartNumber, useMetadata, multifiles) { this.resetModal(); var $drop = $('.modal-body .drop', this.$el); var $form = $('form', $drop); var $fileInput = $('input[type="file"]', $form); if (multifiles) { $fileInput.attr('multiple', 'multiple'); } else { $fileInput.removeAttr('multiple'); } $drop.off('click').on('click', function(event) { $fileInput.get(0).click(); }); $fileInput.off('change').on('change', function() { handleFiles($(this).get(0).files); }); $drop.off('dragenter dragover').on('dragenter dragover', function(event) { event.stopPropagation(); event.preventDefault(); }); $drop.off('drop').on('drop', function(event) { event.stopPropagation(); event.preventDefault(); var dataTransfer = event.dataTransfer; handleFiles(dataTransfer.files); }); var self = this; function handleFiles(files) { /*if (!Dropzone.isValidFile(file, dropzone.options.acceptedFiles)) { $('div.modal-header h4', self.$el).text('Nicht unterstützter Dateityp.'); $('.modal-body .drop', this.$el).css("background-image", "url('/img/dz-backdrop.png')"); $('#uploadModal-confirm', this.$el).attr('disabled','disabled').off('click'); return; }*/ if (multifiles && files.length > 1) { $('div.modal-header h4', self.$el).text(files.length + ' files.'); } else { $('div.modal-header h4', self.$el).text(files[0].name); } $('div.modal-body .drop', self.$el).css("background-image", "url('/img/audio_file.png')"); $('.modal-body #sourceUri', self.$el).val(''); $('#uploadModal-confirm', self.$el).off('click').on('click', function() { if (!multifiles) { var upload = new Rdxport.Upload(files[0], group, groupView, cartNumber, useMetadata); upload.import(); self.uploads.push(upload); } else { $.each(files, function(index, file) { var upload = new Rdxport.Upload(file, group, groupView, cartNumber, useMetadata); upload.import(); self.uploads.push(upload); }); } self.$el.off('hide.bs.modal'); self.$el.modal('hide'); }) .removeAttr('disabled').focus(); } $('form', this.$el).off('submit').on('submit', function(event) { event.preventDefault(); }); $('.modal-body #sourceUri', this.$el).off().on('keyup change', function(event) { $form = $(this).parent('form'); if ($(this).val() === '') { $('#uploadModal-confirm', self.$el).off('click').attr('disabled', 'disabled'); $form.off('submit'); return; } $('.modal-body .drop', self.$el).css("background-image", "url('/img/dz-backdrop.png')"); $('.modal-body .drop form input[type="file"]', self.$el).val(''); $form.off('submit').on('submit', function(event) { event.preventDefault(); handleSource(); }); $('#uploadModal-confirm', self.$el).off('click').on('click', function(event) { event.preventDefault(); handleSource(); }).removeAttr('disabled'); function handleSource() { var sourceUri = $('.modal-body #sourceUri', self.$el).val(); var upload = new Rdxport.Upload(sourceUri, group, groupView, cartNumber, useMetadata); upload.import(); self.uploads.push(upload); self.$el.off('hide.bs.modal'); self.$el.modal('hide'); } }); this.$el.modal({keyboard: true}); }; Rdxport.Importer.prototype.isUploading = function() { var $result = false; $.each(this.uploads, function(index, upload) { if (upload && upload.isUploading()) { $result = true; return false; //break; } }); return $result; }; Rdxport.Importer.prototype.closeAllUploads = function() { $.each(this.uploads, function(index, upload) { if (upload) { upload.close(); } }); }; Rdxport.Importer.prototype.cancelAllUploads = function() { $.each(this.uploads, function(index, upload) { if (upload) { upload.cancel(); } }); }; Rdxport.Importer.prototype.removeUpload = function(upload) { var self = this; $.each(this.uploads, function(index, currentUpload){ if(currentUpload === upload) { self.uploads.splice(index, 1); return false; //break; } }); }; Rdxport.Importer.prototype.getUploadByCartNumber = function(cartNumber) { if (cartNumber === null) { return null; } var upload = null; $.each(this.uploads, function(index, currentUpload) { if (currentUpload.cartNumber === parseInt(cartNumber)) { upload = currentUpload; return false; //break; } }); return upload; }; Rdxport.Importer.prototype.getUploadById = function(uploadId) { if (uploadId === null) { return null; } var upload = null; $.each(this.uploads, function(index, currentUpload) { if (currentUpload.uploadId === uploadId ) { upload = currentUpload; return false; //break; } }); return upload; }; Rdxport.Importer.prototype.getUploadsByCartNumber = function(cartNumber) { if (cartNumber === null) { return null; } return this.uploads.filter(function (currentUpload) { return currentUpload.cartNumber === parseInt(cartNumber); }); }; Rdxport.Importer.prototype.getUploadsByGroupName = function(groupName) { if (groupName === null) { return null; } return this.uploads.filter(function (currentUpload) { return currentUpload.group.name === groupName; }); }; Rdxport.Upload = function(fileOrsourceUri, group, groupView, cartNumber, useMetadata) { this.sourceUri = ''; this.file = null; this.filename = ''; if (typeof fileOrsourceUri === "string") { this.sourceUri = fileOrsourceUri; this.filename = fileOrsourceUri ? fileOrsourceUri.substr(fileOrsourceUri.lastIndexOf('/') + 1) : ''; } else { this.file = fileOrsourceUri; this.filename = fileOrsourceUri.name; this.sourceUri = 'attachment://' + fileOrsourceUri.size + '/' + this.filename; } this.title = this.filename; this.group = group; this.groupView = groupView; this.cartNumber = parseInt(cartNumber); this.cutNumber = null; this.useMetadata = useMetadata; this.uploadId = null; this.webSocket = null; this.uploadprogress = { current: 0, total: 0, progress: 0, progress_step: 0, progress_step_name: '' }; this.sendingFile = false; this.error = false; this.errorStatus = ''; this.errorString = ''; this.uploadInterval = null; }; Rdxport.Upload.prototype.isUploading = function() { return this.file && !this.error && this.uploadprogress.progress_step < 2; }; Rdxport.Upload.prototype.onclose = function(code, reason) { console.log('close'); console.log(code); console.log(reason); }; Rdxport.Upload.prototype.onerror = function(error) { console.log('error'); console.log(error); this.importFileUploadError(500, error); }; Rdxport.Upload.prototype.onmessage = function(event) { var data = $.parseJSON(event.data); this.uploadId = data.ID; switch (data.TYPE.toLowerCase()) { case Rdxport.Importer.TYPE_ERROR: this.importFileUploadError(data.RESPONSE_CODE, data.ERROR_STRING); break; case Rdxport.Importer.TYPE_ACK: console.log(data); this.group.fetchCarts(); this.groupView.uploadProgress(this); break; case Rdxport.Importer.TYPE_PROGRESS: //console.log(data); this.uploadprogress.current = data.CURRENT; this.uploadprogress.total = data.TOTAL; this.uploadprogress.progress = data.PROGRESS; this.uploadprogress.progress_step = data.PROGRESS_STEP; this.uploadprogress.progress_step_name = data.PROGRESS_STEP_NAME; if (data.CART_NUMBER) { this.cartNumber = data.CART_NUMBER; } if (data.CUT_NUMBER) { this.cutNumber = data.CUT_NUMBER; } if (data.TITLE) { this.title = data.TITLE; } this.groupView.uploadProgress(this); break; case Rdxport.Importer.TYPE_DONE: console.log(data); if(data.RESPONSE_CODE < 400) { this.importFileUploadSuccess(); } else { this.importFileUploadError(data.RESPONSE_CODE, data.ERROR_STRING); } break; } if (this.file && !this.sendingFile) { this.sendingFile = true; var chunkSize = 60 * 1024; var start = 0; var end = chunkSize; var self = this; this.uploadInterval = setInterval(function() { for(var i = 0; i < 16; i++) { if (self.webSocket.bufferedAmount > 16 * chunkSize) { return true; } var blob = self.file.slice(start, end, {type: "application/octet-stream"}); self.webSocket.send(blob); if (self.file.size === end) { clearInterval(self.uploadInterval); return true; } start += chunkSize; end += chunkSize; end = end > self.file.size ? self.file.size : end; } }, 10); } }; Rdxport.Upload.prototype.import = function() { var self = this; this.webSocket = new WebSocket(importer.rhimpordEndpoint); this.webSocket.onclose = function(code, reason) { self.onclose(code, reason) }; this.webSocket.onerror = function(error) { self.onerror(error); }; this.webSocket.onmessage = function(event) { self.onmessage(event) }; this.webSocket.onopen = function() { var sendOptions = { COMMAND: Rdxport.Importer.CMD_NEW, LOGIN_NAME: importer.username, PASSWORD: importer.token, TIMEOUT: 7200, // 2 hours SOURCE_URI: self.sourceUri, CHANNELS: 2, NORMALIZATION_LEVEL: self.group.normlevel, AUTOTRIM_LEVEL: self.group.trimlevel, USE_METADATA: self.useMetadata }; if (self.group instanceof Rdxport.Show) { sendOptions.SHOW_ID = self.group.id; } if (self.cartNumber) { sendOptions.REFERENCE_ID = self.group.groupName + '/' + self.cartNumber + '/' + self.filename; sendOptions.CART_NUMBER = parseInt(self.cartNumber); } else if (self.group instanceof Rdxport.Musicpool) { sendOptions.REFERENCE_ID = self.group.groupName + '/' + self.filename; sendOptions.MUSIC_POOL_GROUP = self.group.groupName; } console.log(sendOptions); this.send(JSON.stringify(sendOptions)); }; }; Rdxport.Upload.prototype.reconnect = function(id, reference) { var self = this; this.webSocket = new WebSocket(importer.rhimpordEndpoint); this.webSocket.onclose = function(code, reason) { self.onclose(code, reason) }; this.webSocket.onerror = function(error) { self.onerror(error); }; this.webSocket.onmessage = function(event) { self.onmessage(event) }; this.webSocket.onopen = function() { var reconnectOptions = { COMMAND: Rdxport.Importer.CMD_RECONNECT, LOGIN_NAME: importer.username, PASSWORD: importer.token, ID: id }; this.send(JSON.stringify(reconnectOptions)); self.group.fetchCarts(); }; }; Rdxport.Upload.prototype.close = function() { this.webSocket.close(); importer.removeUpload(this); this.group.fetchCarts(); }; Rdxport.Upload.prototype.cancel = function() { clearInterval(this.uploadInterval); this.webSocket.send(JSON.stringify({ COMMAND: 'cancel' })); }; Rdxport.Upload.prototype.importFileUploadSuccess = function() { importer.removeUpload(this); this.group.fetchCarts(); }; Rdxport.Upload.prototype.importFileUploadError = function(status, errorString) { this.error = true; this.errorStatus = status; this.errorString = errorString; this.uploadprogress.progress_step = 99; // makes isUploading return false var self = this; this.groupView.uploadError(this); };