/* * 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.$datepicker = null; this.listWebSocket = null; this.sessions = []; this.uploads = []; this.initListWebSocket(); setInterval(this.checkListWebSocket.bind(this), 5000); }; 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.connected = false; this.listWebSocket.onclose = function(code, reason) { //console.log(code); //console.log(reason); if(this.connected) { console.log('importer: list-socket closed, reconnect immediatly because it was connected before'); self.checkListWebSocket(); } else { console.log('importer: list-socket closed, not reconnecting immediatly because it was never connected'); } }; this.listWebSocket.onerror = function(error) { //console.log('error'); if(this.connected) { // only print errors if we are connected console.log(error); } }; this.listWebSocket.onopen = function() { this.connected = true; console.log('importer: list-socket is now connected'); var sendOptions = { COMMAND: Rdxport.Importer.CMD_LIST, LOGIN_NAME: importer.username, PASSWORD: importer.token }; this.send(JSON.stringify(sendOptions)); }; this.listWebSocket.onmessage = function(event) { var data = $.parseJSON(event.data); //console.log(data); if (data.TYPE.toLowerCase() !== Rdxport.Importer.TYPE_LIST) { return; } $.each(data.SESSIONS_ADDED, function(id, reference) { self.sessions.push({id: id, reference: reference}); }); $.each(data.SESSIONS_REMOVED, function(id, reference) { self.sessions = self.sessions.filter(function(element) { return element.reference !== reference; }); }); }; }; Rdxport.Importer.prototype.checkListWebSocket = function() { if(!this.listWebSocket || this.listWebSocket.readyState == 3) { this.initListWebSocket(); } }; Rdxport.Importer.prototype.syncUploads = function(route, groupView, done) { var sessions = this.sessions.filter(function(session) { var reference = session.reference.split('/'); return route === reference[0] && groupView.model.groupName === reference[1]; }); var self = this; $.each(sessions, function(index, session) { if (importer.getUploadById(session.id) !== null) { return true; //continue; } var reference = session.reference.split('/'); var cartNumber = reference[2]; var filename = reference[3]; var group = groupView.model; var upload = new Rdxport.Upload('/' + filename, group, groupView, cartNumber, null); upload.reconnect(session.id, session.reference); self.uploads.push(upload); }); if (done) { done(); } }; Rdxport.Importer.prototype.resetModal = function() { $('.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'); $('form ul', self.$el).empty(); // tab menu $('.nav-tabs li', this.$el).removeClass('active'); $('.nav-tabs li:first', this.$el).addClass('active'); $('.upload-tabs > div', self.$el).hide(); $('.upload-tabs div:first', self.$el).show(); if (this.$datepicker) { this.$datepicker.datepicker('remove'); } }; Rdxport.Importer.prototype.openModal = function(group, groupView, cartNumber, useMetadata, multifiles) { this.resetModal(); this.$datepicker = $('.datepicker', this.$el).datepicker({ format: "dd.mm.yyyy", language: "de", startDate: '01/01/2016', endDate: new Date() }); var $spinner = $('.spinner', this.$el); // tab menu var self = this; $('.nav-tabs li a', this.$el).off().on('click', function(event) { event.preventDefault(); $('.nav-tabs li', self.$el).removeClass('active'); $(this).parent().addClass('active'); var tabName = $(this).data('tab-name'); $('.upload-tabs > div', self.$el).hide(); $('.upload-tabs .tab-' + tabName, self.$el).show(); $('#uploadModal-confirm', this.$el).attr('disabled','disabled').off('click'); if (tabName === 'archive') { self.$datepicker.on('changeDate', function() { $('#uploadModal-confirm', this.$el).removeAttr('disabled').off().on('click', function() { var date = self.$datepicker.datepicker('getDate'); var spinnerVal = $spinner.val().split(':'); var hours = spinnerVal[0]; date.setHours(hours); var sourceUri = dateToArchiveUri(date); 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'); }); }); } }); 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) { var $formUl = $('form ul', self.$el).empty(); $.each(files, function(index, file) { //$formUl.append($('
  • ').text(file.name)); }); } else { $('form ul', self.$el).empty(); } $('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().trim(); 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(silent) { silent = silent || false; $.each(this.uploads, function(index, upload) { if (upload) { upload.close(silent); } }); }; 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 = ''; }; 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); if (this.file && !this.sendingFile) { this.sendingFile = true; var command = { type: "POST", contentType: "application/octet-stream", data: this.file, processData: false, dataType: 'json', error: function(req, status, err) { console.log({StatusText: status, ErrorString: err}); }, success: function(data, status, req) { console.log(data); } }; $.ajax('https://' + window.location.host + '/upload/' + importer.username + '/' + data.ID, command); } this.isNew = true; this.group.fetchCarts(); this.groupView.uploadProgress(this); break; case Rdxport.Importer.TYPE_PROGRESS: //console.log(data); this.isNew = false; 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; } }; 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 reference = ''; if (self.group instanceof Rdxport.Show) { reference += 'shows/'; } else if (self.group instanceof Rdxport.JingleGroup) { reference += 'jingles/'; } else if (self.group instanceof Rdxport.Musicpool) { reference += 'musicpools/'; } reference += self.group.groupName + '/'; reference += self.cartNumber ? self.cartNumber + '/' : '/'; reference += self.filename; 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, REFERENCE_ID: reference }; if (self.group instanceof Rdxport.Show) { sendOptions.SHOW_ID = self.group.id; } if (self.cartNumber) { sendOptions.CART_NUMBER = parseInt(self.cartNumber); } else if (self.group instanceof Rdxport.Musicpool) { 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(silent) { silent = silent || false; this.webSocket.close(); importer.removeUpload(this); if (!silent) { this.group.fetchCarts(); } }; Rdxport.Upload.prototype.cancel = function() { 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 this.groupView.uploadError(this); };