diff --git a/js/apps/system/aardvark/frontend/js/lib/jquery.uploadfile.js b/js/apps/system/aardvark/frontend/js/lib/jquery.uploadfile.js
new file mode 100644
index 0000000000..758a9bf18c
--- /dev/null
+++ b/js/apps/system/aardvark/frontend/js/lib/jquery.uploadfile.js
@@ -0,0 +1,534 @@
+/*!
+ * jQuery Upload File Plugin
+ * version: 3.1.0
+ * @requires jQuery v1.5 or later & form plugin
+ * Copyright (c) 2013 Ravishanker Kusuma
+ * http://hayageek.com/
+ */
+(function ($) {
+ if ($.fn.ajaxForm == undefined) {
+ $.getScript("http://malsup.github.io/jquery.form.js");
+ }
+ var feature = {};
+ feature.fileapi = $(" ").get(0).files !== undefined;
+ feature.formdata = window.FormData !== undefined;
+
+ $.fn.uploadFile = function (options) {
+ // This is the easiest way to have default options.
+ var s = $.extend({
+ // These are the defaults.
+ url: "",
+ method: "POST",
+ enctype: "multipart/form-data",
+ formData: null,
+ returnType: null,
+ allowedTypes: "*",
+ fileName: "file",
+ formData: {},
+ dynamicFormData: function () {
+ return {};
+ },
+ maxFileSize: -1,
+ multiple: true,
+ dragDrop: true,
+ autoSubmit: true,
+ showCancel: true,
+ showAbort: true,
+ showDone: true,
+ showDelete:false,
+ showError: true,
+ showStatusAfterSuccess: true,
+ showStatusAfterError: true,
+ showFileCounter:true,
+ fileCounterStyle:"). ",
+ showProgress:false,
+ onSelect:function(files){ return true;},
+ onSubmit: function (files, xhr) {},
+ onSuccess: function (files, response, xhr) {},
+ onError: function (files, status, message) {},
+ deleteCallback: false,
+ afterUploadAll: false,
+ uploadButtonClass: "ajax-file-upload",
+ dragDropStr: "Drag & Drop Files ",
+ abortStr: "Abort",
+ cancelStr: "Cancel",
+ deletelStr: "Delete",
+ doneStr: "Done",
+ multiDragErrorStr: "Multiple File Drag & Drop is not allowed.",
+ extErrorStr: "is not allowed. Allowed extensions: ",
+ sizeErrorStr: "is not allowed. Allowed Max size: ",
+ uploadErrorStr: "Upload is not allowed"
+ }, options);
+
+ this.fileCounter = 1;
+ this.fCounter = 0; //failed uploads
+ this.sCounter = 0; //success uploads
+ this.tCounter = 0; //total uploads
+ var formGroup = "ajax-file-upload-" + (new Date().getTime());
+ this.formGroup = formGroup;
+ this.hide();
+ this.errorLog = $("
"); //Writing errors
+ this.after(this.errorLog);
+ this.responses = [];
+ if (!feature.formdata) //check drag drop enabled.
+ {
+ s.dragDrop = false;
+ }
+
+
+ var obj = this;
+
+ var uploadLabel = $('' + $(this).html() + '
');
+ $(uploadLabel).addClass(s.uploadButtonClass);
+
+ //wait form ajax Form plugin and initialize
+ (function checkAjaxFormLoaded() {
+ if ($.fn.ajaxForm) {
+
+ if (s.dragDrop) {
+ var dragDrop = $('
');
+ $(obj).before(dragDrop);
+ $(dragDrop).append(uploadLabel);
+ $(dragDrop).append($(s.dragDropStr));
+ setDragDropHandlers(obj, s, dragDrop);
+
+ } else {
+ $(obj).before(uploadLabel);
+ }
+
+ createCutomInputFile(obj, formGroup, s, uploadLabel);
+
+ } else window.setTimeout(checkAjaxFormLoaded, 10);
+ })();
+
+ this.startUpload = function () {
+ $("." + this.formGroup).each(function (i, items) {
+ if ($(this).is('form')) $(this).submit();
+ });
+ }
+ this.stopUpload = function () {
+ $(".ajax-file-upload-red").each(function (i, items) {
+ if ($(this).hasClass(obj.formGroup)) $(this).click();
+ });
+ }
+
+ this.getResponses = function () {
+ return this.responses;
+ }
+ var checking = false;
+
+ function checkPendingUploads() {
+ if (s.afterUploadAll && !checking) {
+ checking = true;
+ (function checkPending() {
+ if (obj.sCounter != 0 && (obj.sCounter + obj.fCounter == obj.tCounter)) {
+ s.afterUploadAll(obj);
+ checking = false;
+ } else window.setTimeout(checkPending, 100);
+ })();
+ }
+
+ }
+
+ function setDragDropHandlers(obj, s, ddObj) {
+ ddObj.on('dragenter', function (e) {
+ e.stopPropagation();
+ e.preventDefault();
+ $(this).css('border', '2px solid #A5A5C7');
+ });
+ ddObj.on('dragover', function (e) {
+ e.stopPropagation();
+ e.preventDefault();
+ });
+ ddObj.on('drop', function (e) {
+ $(this).css('border', '2px dotted #A5A5C7');
+ e.preventDefault();
+ obj.errorLog.html("");
+ var files = e.originalEvent.dataTransfer.files;
+ if (!s.multiple && files.length > 1) {
+ if (s.showError) $("" + s.multiDragErrorStr + "
").appendTo(obj.errorLog);
+ return;
+ }
+ if(s.onSelect(files) == false)
+ return;
+ serializeAndUploadFiles(s, obj, files);
+ });
+
+ $(document).on('dragenter', function (e) {
+ e.stopPropagation();
+ e.preventDefault();
+ });
+ $(document).on('dragover', function (e) {
+ e.stopPropagation();
+ e.preventDefault();
+ ddObj.css('border', '2px dotted #A5A5C7');
+ });
+ $(document).on('drop', function (e) {
+ e.stopPropagation();
+ e.preventDefault();
+ ddObj.css('border', '2px dotted #A5A5C7');
+ });
+
+ }
+
+ function getSizeStr(size) {
+ var sizeStr = "";
+ var sizeKB = size / 1024;
+ if (parseInt(sizeKB) > 1024) {
+ var sizeMB = sizeKB / 1024;
+ sizeStr = sizeMB.toFixed(2) + " MB";
+ } else {
+ sizeStr = sizeKB.toFixed(2) + " KB";
+ }
+ return sizeStr;
+ }
+
+ function serializeData(extraData) {
+ var serialized = [];
+ if (jQuery.type(extraData) == "string") {
+ serialized = extraData.split('&');
+ } else {
+ serialized = $.param(extraData).split('&');
+ }
+ var len = serialized.length;
+ var result = [];
+ var i, part;
+ for (i = 0; i < len; i++) {
+ serialized[i] = serialized[i].replace(/\+/g, ' ');
+ part = serialized[i].split('=');
+ result.push([decodeURIComponent(part[0]), decodeURIComponent(part[1])]);
+ }
+ return result;
+ }
+
+ function serializeAndUploadFiles(s, obj, files) {
+ for (var i = 0; i < files.length; i++) {
+ if (!isFileTypeAllowed(obj, s, files[i].name)) {
+ if (s.showError) $("" + files[i].name + " " + s.extErrorStr + s.allowedTypes + "
").appendTo(obj.errorLog);
+ continue;
+ }
+ if (s.maxFileSize != -1 && files[i].size > s.maxFileSize) {
+ if (s.showError) $("" + files[i].name + " " + s.sizeErrorStr + getSizeStr(s.maxFileSize) + "
").appendTo(obj.errorLog);
+ continue;
+ }
+ var ts = s;
+ var fd = new FormData();
+ var fileName = s.fileName.replace("[]", "");
+ fd.append(fileName, files[i]);
+ var extraData = s.formData;
+ if (extraData) {
+ var sData = serializeData(extraData);
+ for (var j = 0; j < sData.length; j++) {
+ if (sData[j]) {
+ fd.append(sData[j][0], sData[j][1]);
+ }
+ }
+ }
+ ts.fileData = fd;
+
+ var pd = new createProgressDiv(obj, s);
+ var fileNameStr="";
+ if(s.showFileCounter)
+ fileNameStr = obj.fileCounter + s.fileCounterStyle + files[i].name
+ else
+ fileNameStr = files[i].name;
+
+ pd.filename.html(fileNameStr);
+ var form = $("");
+ form.appendTo('body');
+ var fileArray = [];
+ fileArray.push(files[i].name);
+ ajaxFormSubmit(form, ts, pd, fileArray, obj);
+ obj.fileCounter++;
+
+
+ }
+ }
+
+ function isFileTypeAllowed(obj, s, fileName) {
+ var fileExtensions = s.allowedTypes.toLowerCase().split(",");
+ var ext = fileName.split('.').pop().toLowerCase();
+ if (s.allowedTypes != "*" && jQuery.inArray(ext, fileExtensions) < 0) {
+ return false;
+ }
+ return true;
+ }
+
+ function createCutomInputFile(obj, group, s, uploadLabel) {
+
+ var fileUploadId = "ajax-upload-id-" + (new Date().getTime());
+
+ var form = $("");
+ var fileInputStr = " ";
+ if (s.multiple) {
+ if (s.fileName.indexOf("[]") != s.fileName.length - 2) // if it does not endwith
+ {
+ s.fileName += "[]";
+ }
+ fileInputStr = " ";
+ }
+ var fileInput = $(fileInputStr).appendTo(form);
+
+ fileInput.change(function () {
+
+ obj.errorLog.html("");
+ var fileExtensions = s.allowedTypes.toLowerCase().split(",");
+ var fileArray = [];
+ if (this.files) //support reading files
+ {
+ for (i = 0; i < this.files.length; i++)
+ {
+ fileArray.push(this.files[i].name);
+ }
+
+ if(s.onSelect(this.files) == false)
+ return;
+ } else {
+ var filenameStr = $(this).val();
+ var flist = [];
+ fileArray.push(filenameStr);
+ if (!isFileTypeAllowed(obj, s, filenameStr)) {
+ if (s.showError) $("" + filenameStr + " " + s.extErrorStr + s.allowedTypes + "
").appendTo(obj.errorLog);
+ return;
+ }
+ //fallback for browser without FileAPI
+ flist.push({name:filenameStr,size:'NA'});
+ if(s.onSelect(flist) == false)
+ return;
+
+ }
+ uploadLabel.unbind("click");
+ form.hide();
+ createCutomInputFile(obj, group, s, uploadLabel);
+
+ form.addClass(group);
+ if (feature.fileapi && feature.formdata) //use HTML5 support and split file submission
+ {
+ form.removeClass(group); //Stop Submitting when.
+ var files = this.files;
+ serializeAndUploadFiles(s, obj, files);
+ } else {
+ var fileList = "";
+ for (var i = 0; i < fileArray.length; i++) {
+ if(s.showFileCounter)
+ fileList += obj.fileCounter + s.fileCounterStyle + fileArray[i]+" ";
+ else
+ fileList += fileArray[i]+" ";;
+ obj.fileCounter++;
+ }
+ var pd = new createProgressDiv(obj, s);
+ pd.filename.html(fileList);
+ ajaxFormSubmit(form, s, pd, fileArray, obj);
+ }
+
+
+
+ });
+
+ form.css({'margin':0,'padding':0});
+ var uwidth=$(uploadLabel).width()+10;
+ if(uwidth == 10)
+ uwidth =120;
+
+ var uheight=uploadLabel.height()+10;
+ if(uheight == 10)
+ uheight = 35;
+
+ uploadLabel.css({position: 'relative',overflow:'hidden',cursor:'default'});
+ fileInput.css({position: 'absolute','cursor':'pointer',
+ 'top': '0px',
+ 'width': uwidth,
+ 'height':uheight,
+ 'left': '0px',
+ 'z-index': '100',
+ 'opacity': '0.0',
+ 'filter':'alpha(opacity=0)',
+ '-ms-filter':"alpha(opacity=0)",
+ '-khtml-opacity':'0.0',
+ '-moz-opacity':'0.0'
+ });
+ form.appendTo(uploadLabel);
+
+ //dont hide it, but move it to
+ /* form.css({
+ margin: 0,
+ padding: 0,
+ display: 'block',
+ position: 'absolute',
+ left: '50px'
+ });
+ if (navigator.appVersion.indexOf("MSIE ") != -1) //IE Browser
+ {
+ uploadLabel.attr('for', fileUploadId);
+ } else {
+ uploadLabel.click(function () {
+ fileInput.click();
+ });
+ }*/
+
+
+ }
+
+
+ function createProgressDiv(obj, s) {
+ this.statusbar = $("
");
+ this.filename = $("
").appendTo(this.statusbar);
+ this.progressDiv = $("").appendTo(this.statusbar).hide();
+ this.progressbar = $("
").appendTo(this.progressDiv);
+ this.abort = $("
" + s.abortStr + "
").appendTo(this.statusbar).hide();
+ this.cancel = $("
" + s.cancelStr + "
").appendTo(this.statusbar).hide();
+ this.done = $("
" + s.doneStr + "
").appendTo(this.statusbar).hide();
+ this.del = $("
" + s.deletelStr + "
").appendTo(this.statusbar).hide();
+ obj.errorLog.after(this.statusbar);
+ return this;
+ }
+
+
+ function ajaxFormSubmit(form, s, pd, fileArray, obj) {
+ var currentXHR = null;
+ var options = {
+ cache: false,
+ contentType: false,
+ processData: false,
+ forceSync: false,
+ data: s.formData,
+ formData: s.fileData,
+ dataType: s.returnType,
+ beforeSubmit: function (formData, $form, options) {
+ if (s.onSubmit.call(this, fileArray) != false) {
+ var dynData = s.dynamicFormData();
+ if (dynData) {
+ var sData = serializeData(dynData);
+ if (sData) {
+ for (var j = 0; j < sData.length; j++) {
+ if (sData[j]) {
+ if (s.fileData != undefined) options.formData.append(sData[j][0], sData[j][1]);
+ else options.data[sData[j][0]] = sData[j][1];
+ }
+ }
+ }
+ }
+ obj.tCounter += fileArray.length;
+ //window.setTimeout(checkPendingUploads, 1000); //not so critical
+ checkPendingUploads();
+ return true;
+ }
+ pd.statusbar.append("
" + s.uploadErrorStr + "
");
+ pd.cancel.show()
+ form.remove();
+ pd.cancel.click(function () {
+ pd.statusbar.remove();
+ });
+ return false;
+ },
+ beforeSend: function (xhr, o) {
+
+ pd.progressDiv.show();
+ pd.cancel.hide();
+ pd.done.hide();
+ if (s.showAbort) {
+ pd.abort.show();
+ pd.abort.click(function () {
+ xhr.abort();
+ });
+ }
+ if (!feature.formdata) //For iframe based push
+ {
+ pd.progressbar.width('5%');
+ } else pd.progressbar.width('1%'); //Fix for small files
+ },
+ uploadProgress: function (event, position, total, percentComplete) {
+ //Fix for smaller file uploads in MAC
+ if(percentComplete > 98) percentComplete =98;
+
+ var percentVal = percentComplete + '%';
+ if (percentComplete > 1) pd.progressbar.width(percentVal)
+ if(s.showProgress)
+ {
+ pd.progressbar.html(percentVal);
+ pd.progressbar.css('text-align', 'center');
+ }
+
+ },
+ success: function (data, message, xhr) {
+ obj.responses.push(data);
+ pd.progressbar.width('100%')
+ if(s.showProgress)
+ {
+ pd.progressbar.html('100%');
+ pd.progressbar.css('text-align', 'center');
+ }
+
+ pd.abort.hide();
+ s.onSuccess.call(this, fileArray, data, xhr);
+ if (s.showStatusAfterSuccess) {
+ if (s.showDone) {
+ pd.done.show();
+ pd.done.click(function () {
+ pd.statusbar.hide("slow");
+ pd.statusbar.remove();
+ });
+ } else {
+ pd.done.hide();
+ }
+ if(s.showDelete)
+ {
+ pd.del.show();
+ pd.del.click(function () {
+ if(s.deleteCallback) s.deleteCallback.call(this, data,pd);
+ });
+ }
+ else
+ {
+ pd.del.hide();
+ }
+ } else {
+ pd.statusbar.hide("slow");
+ pd.statusbar.remove();
+
+ }
+ form.remove();
+ obj.sCounter += fileArray.length;
+ },
+ error: function (xhr, status, errMsg) {
+ pd.abort.hide();
+ if (xhr.statusText == "abort") //we aborted it
+ {
+ pd.statusbar.hide("slow");
+ } else {
+ s.onError.call(this, fileArray, status, errMsg);
+ if (s.showStatusAfterError) {
+ pd.progressDiv.hide();
+ pd.statusbar.append("
ERROR: " + errMsg + " ");
+ } else {
+ pd.statusbar.hide();
+ pd.statusbar.remove();
+ }
+ }
+
+ form.remove();
+ obj.fCounter += fileArray.length;
+
+ }
+ };
+ if (s.autoSubmit) {
+ form.ajaxSubmit(options);
+ } else {
+ if (s.showCancel) {
+ pd.cancel.show();
+ pd.cancel.click(function () {
+ form.remove();
+ pd.statusbar.remove();
+ });
+ }
+ form.ajaxForm(options);
+
+ }
+
+ }
+ return this;
+
+ }
+
+
+}(jQuery));
\ No newline at end of file
diff --git a/js/apps/system/aardvark/frontend/js/templates/modalApplicationMount.ejs b/js/apps/system/aardvark/frontend/js/templates/modalApplicationMount.ejs
index a468a0e554..59a4c3d097 100644
--- a/js/apps/system/aardvark/frontend/js/templates/modalApplicationMount.ejs
+++ b/js/apps/system/aardvark/frontend/js/templates/modalApplicationMount.ejs
@@ -67,7 +67,9 @@
-
The repository has to be public. The version has to be a git tag LINKTOTAG.
+
+ Download a foxx application from a public
github.com repository. In order to define a version please add a
git tag to your repository using the following format: "v1.2.3". To connect to github your username and the name of the repository are sufficient.
+
@@ -91,19 +93,15 @@
-
Todo how ZIP.
-
+
+ Upload a ZIP-packed foxx application to ArangoDB.
+ The ZIP file has to be created from the folder containing the manifest.json file of your App, do not include the databases folder structure created by ArangoDB.
+ This is also compatible with the download format for ZIP files on github.com .
+ Remember to change to a new version number in the manifest.json when uploading an update.
+
+
Upload Foxx.zip
diff --git a/js/apps/system/aardvark/frontend/js/views/applicationsView.js b/js/apps/system/aardvark/frontend/js/views/applicationsView.js
index 11ec4c39ee..908b549de8 100644
--- a/js/apps/system/aardvark/frontend/js/views/applicationsView.js
+++ b/js/apps/system/aardvark/frontend/js/views/applicationsView.js
@@ -371,7 +371,40 @@
///// NEW CODE
- installFoxxFromZip: function() {
+ installFoxxFromZip: function(files, data) {
+ var self = this;
+ $.ajax({
+ type: "POST",
+ async: false,
+ url: "/_admin/aardvark/foxxes/inspect",
+ data: JSON.stringify(data),
+ contentType: "application/json"
+ }).done(function(res) {
+ $.ajax({
+ type: "POST",
+ async: false,
+ url: '/_admin/foxx/fetch',
+ data: JSON.stringify({
+ name: res.name,
+ version: res.version,
+ filename: res.filename
+ }),
+ processData: false
+ }).done(function (result) {
+ if (result.error === false) {
+ window.modalView.hide();
+ self.showConfigureDialog(res.configuration, res.name, res.version);
+ }
+ }).fail(function (err) {
+ var error = JSON.parse(err.responseText);
+ arangoHelper.arangoError("Error: " + error.errorMessage);
+ });
+ }).fail(function(err) {
+ var error = JSON.parse(err.responseText);
+ arangoHelper.arangoError("Error: " + error.error);
+ });
+ self.hideImportModal();
+ /*
var self = this;
if (this.allowUpload) {
this.showSpinner();
@@ -384,53 +417,14 @@
contentType: 'application/octet-stream',
complete: function(res) {
if (res.readyState === 4) {
- if (res.status === 201) {
- $.ajax({
- type: "POST",
- async: false,
- url: "/_admin/aardvark/foxxes/inspect",
- data: res.responseText,
- contentType: "application/json"
- }).done(function(res) {
- console.log("Peter2", res);
- $.ajax({
- type: "POST",
- async: false,
- url: '/_admin/foxx/fetch',
- data: JSON.stringify({
- name: res.name,
- version: res.version,
- filename: res.filename
- }),
- processData: false
- }).done(function (result) {
- console.log("Peter", result);
- if (result.error === false) {
- window.modalView.hide();
- self.showConfigureDialog(res.configuration, res.name, res.version);
- }
- }).fail(function (err) {
- self.hideSpinner();
- var error = JSON.parse(err.responseText);
- arangoHelper.arangoError("Error: " + error.errorMessage);
- });
- }).fail(function(err) {
- self.hideSpinner();
- var error = JSON.parse(err.responseText);
- arangoHelper.arangoError("Error: " + error.error);
- });
- delete self.file;
- self.allowUpload = false;
- self.hideSpinner();
- self.hideImportModal();
- return;
- }
+ if (res.status === 201)
}
self.hideSpinner();
arangoHelper.arangoError("Upload error");
}
});
}
+ */
},
installFoxxFromStore: function(e) {
@@ -685,9 +679,9 @@
event.preventDefault();
var buttons = [];
var modalEvents = {
- "click #infoTab a": this.switchModalButton.bind(this),
- "click .install-app" : this.installFoxxFromStore.bind(this),
- "change #zip-file" : this.uploadSetup.bind(this)
+ "click #infoTab a" : this.switchModalButton.bind(this),
+ "click .install-app" : this.installFoxxFromStore.bind(this),
+ "change #zip-file" : this.uploadSetup.bind(this)
};
buttons.push(
window.modalView.createSuccessButton("Generate", this.addAppAction.bind(this))
@@ -706,6 +700,11 @@
minimumResultsForSearch: -1,
width: "336px"
});
+ $("#upload-foxx-zip").uploadFile({
+ url: "/_api/upload",
+ allowedTypes: "zip",
+ onSuccess: this.installFoxxFromZip.bind(this)
+ });
var listTempl = this.appStoreTemplate;
$.get("foxxes/fishbowl", function(list) {
var table = $("#appstore-content");
diff --git a/js/apps/system/aardvark/frontend/scss/_uploadfile.scss b/js/apps/system/aardvark/frontend/scss/_uploadfile.scss
new file mode 100644
index 0000000000..996572b7e5
--- /dev/null
+++ b/js/apps/system/aardvark/frontend/scss/_uploadfile.scss
@@ -0,0 +1,123 @@
+.ajax-file-upload-statusbar {
+ border: 1px solid #0ba1b5;
+ margin-top: 10px;
+ width: 420px;
+ margin-right: 10px;
+ margin: 5px;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ padding: 5px 5px 5px 5px
+}
+.ajax-file-upload-filename {
+ width: 100%;
+ height: auto;
+ margin: 0 5px 5px 10px;
+ color: #807579
+}
+.ajax-file-upload-progress {
+ margin: 0 10px 5px 10px;
+ position: relative;
+ width: 250px;
+ border: 1px solid #ddd;
+ padding: 1px;
+ border-radius: 3px;
+ display: inline-block
+}
+.ajax-file-upload-bar {
+ background-color: #0ba1b5;
+ width: 0;
+ height: 20px;
+ border-radius: 3px;
+ color:#FFFFFF;
+}
+.ajax-file-upload-percent {
+ position: absolute;
+ display: inline-block;
+ top: 3px;
+ left: 48%
+}
+.ajax-file-upload-red {
+ -moz-box-shadow: inset 0 39px 0 -24px #e67a73;
+ -webkit-box-shadow: inset 0 39px 0 -24px #e67a73;
+ box-shadow: inset 0 39px 0 -24px #e67a73;
+ background-color: #e4685d;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ display: inline-block;
+ color: #fff;
+ font-family: arial;
+ font-size: 13px;
+ font-weight: normal;
+ padding: 4px 15px;
+ text-decoration: none;
+ text-shadow: 0 1px 0 #b23e35;
+ cursor: pointer;
+ vertical-align: top;
+ margin-right:5px;
+}
+.ajax-file-upload-green {
+ background-color: #77b55a;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ margin: 0;
+ padding: 0;
+ display: inline-block;
+ color: #fff;
+ font-family: arial;
+ font-size: 13px;
+ font-weight: normal;
+ padding: 4px 15px;
+ text-decoration: none;
+ cursor: pointer;
+ text-shadow: 0 1px 0 #5b8a3c;
+ vertical-align: top;
+ margin-right:5px;
+}
+.ajax-file-upload {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 16px;
+ font-weight: bold;
+ padding: 15px 20px;
+ cursor:pointer;
+ line-height:20px;
+ height:25px;
+ margin:0 10px 10px 0;
+ display: inline-block;
+ background: #fff;
+ border: 1px solid #e8e8e8;
+ color: #888;
+ text-decoration: none;
+ border-radius: 3px;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ -moz-box-shadow: 0 2px 0 0 #e8e8e8;
+ -webkit-box-shadow: 0 2px 0 0 #e8e8e8;
+ box-shadow: 0 2px 0 0 #e8e8e8;
+ padding: 6px 10px 4px 10px;
+ color: #fff;
+ background: #2f8ab9;
+ border: none;
+ -moz-box-shadow: 0 2px 0 0 #13648d;
+ -webkit-box-shadow: 0 2px 0 0 #13648d;
+ box-shadow: 0 2px 0 0 #13648d;
+ vertical-align:middle;
+}
+
+.ajax-file-upload:hover {
+ background: #3396c9;
+ -moz-box-shadow: 0 2px 0 0 #15719f;
+ -webkit-box-shadow: 0 2px 0 0 #15719f;
+ box-shadow: 0 2px 0 0 #15719f;
+}
+
+.ajax-upload-dragdrop {
+ border:2px dotted #A5A5C7;
+ width:420px;
+ color: #DADCE3;
+ text-align:left;
+ vertical-align:middle;
+ padding:10px 10px 0px 10px;
+}
diff --git a/js/apps/system/aardvark/manifest.json b/js/apps/system/aardvark/manifest.json
index 6d2ac5b9b2..893f670ffc 100644
--- a/js/apps/system/aardvark/manifest.json
+++ b/js/apps/system/aardvark/manifest.json
@@ -215,6 +215,7 @@
"frontend/js/lib/jquery.wiggle.min.js",
"frontend/js/lib/jquery.contextmenu.js",
"frontend/js/lib/jquery.hotkeys.js",
+ "frontend/js/lib/jquery.uploadfile.js",
"frontend/js/lib/select2.min.js",
"frontend/js/lib/handlebars-1.0.rc.1.js",
"frontend/js/lib/underscore.js",