1
0
Fork 0

Finished implementing upload and mount by github repo. This includes a checked dialog for configuration. This is reusable for zip / appstore as well

This commit is contained in:
Michael Hackstein 2014-12-12 22:45:13 +01:00
parent 37dd5cd218
commit 83004b08f4
6 changed files with 621 additions and 369 deletions

View File

@ -123,7 +123,9 @@ controller.post("/foxxes/gitinstall", function (req, res) {
res.json({
error: false,
configuration: app.manifest.configuration || {},
app: appID
app: appID,
name: app.name,
version: app.version
});
}).summary("Installs a foxx or update existing")
.notes("This function is used to install or update a (new) foxx.");

View File

@ -45,13 +45,13 @@
contentType: "application/json",
processData: false,
success: function(data) {
result = true;
result = data;
},
error: function(data) {
if (data.responseText.indexOf() !== -1) {
alert("Already newest app version installed.");
}
result = false;
console.log(data);
result = {
error: true
};
}
});
return result;

View File

@ -32,14 +32,6 @@
<input type="text" id="tag" value="" placeholder="master">
</th>
</tr>
<tr class="tableRow">
<th class="collectionInfoTh">
Mount*:
</th>
<th class="collectionInfoTh">
<input type="text" id="tag" value="" placeholder="/foxx/app">
</th>
</tr>
</table>
<button id="installGithub" class="button-success pull-right" style="margin-right:8px">Install</button>
</div>
@ -57,14 +49,6 @@
<input id="zip-file" name="zip-file" type="file"/>
</th>
</tr>
<tr class="tableRow">
<th class="collectionInfoTh">
Mount*:
</th>
<th class="collectionInfoTh">
<input type="text" id="tag" value="" placeholder="/foxx/app">
</th>
</tr>
</table>
<button id="installZip" class="button-success pull-right" style="margin-right:8px">Install</button>
</div>

View File

@ -1,6 +1,17 @@
/*jshint browser: true */
/*jshint strict: false, unused: false */
/*global Backbone, $, window, arangoHelper, templateEngine, Joi, _*/
(function() {
"use strict";
var splitSnakeCase = function(snakeCase) {
var str = snakeCase.replace(/([a-z])([A-Z])/g, "$1 $2");
str = str.replace(/([a-z])([0-9])/gi, "$1 $2");
str = str.replace(/_+/, " ");
return _.map(str.split(/\s+/), function(s) {
return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
}).join(" ");
};
window.ApplicationsView = Backbone.View.extend({
el: '#content',
@ -9,6 +20,8 @@ window.ApplicationsView = Backbone.View.extend({
events: {
"click #addApp" : "createInstallModal",
"change #zip-file" : "uploadSetup",
"click #checkDevel" : "toggleDevel",
"click #checkActive" : "toggleActive",
"click .checkSystem" : "toggleSystem",
@ -21,6 +34,7 @@ window.ApplicationsView = Backbone.View.extend({
"change #appsDesc" : "sorting"
},
checkBoxes: function (e) {
//chrome bugfix
var clicked = e.currentTarget.id;
@ -93,8 +107,8 @@ window.ApplicationsView = Backbone.View.extend({
//fetch needed information, need client side verification
//remove name handling on server side because not needed
name = "";
url = $('#github-url').val();
version = $('#github-version').val();
url = $('#repository').val();
version = $('#tag').val();
if (version === '') {
version = "master";
@ -103,7 +117,7 @@ window.ApplicationsView = Backbone.View.extend({
//send server req through collection
result = this.collection.installFoxxFromGithub(url, name, version);
if (result === true) {
this.closeGithubModal();
window.modalView.hide();
this.reload();
}
},
@ -354,14 +368,269 @@ window.ApplicationsView = Backbone.View.extend({
});
},
installFoxxFromZip: function() {
var self = this;
if (this.allowUpload) {
this.showSpinner();
$.ajax({
type: "POST",
async: false,
url: '/_api/upload',
data: self.file,
processData: false,
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) {
$.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 () {
self.reload();
}).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;
}
}
self.hideSpinner();
arangoHelper.arangoError("Upload error");
}
});
}
},
installFoxxFromStore: function() {
//Todo
},
installFoxxFromGithub: function() {
var name, url, version, result;
//fetch needed information, need client side verification
//remove name handling on server side because not needed
name = "";
url = $('#repository').val();
version = $('#tag').val();
if (version === '') {
version = "master";
}
//send server req through collection
result = this.collection.installFoxxFromGithub(url, name, version);
console.log(result);
if (result.error === false) {
window.modalView.hide();
this.showConfigureDialog(result.configuration, result.name, result.version);
}
},
showConfigureDialog: function(config, name, version) {
var buttons = [],
tableContent = [],
entry;
tableContent.push(
window.modalView.createTextEntry(
"mount-point",
"Mount",
"",
"The path the App will be mounted. Has to start with /. Is not allowed to start with /_",
"/my/app",
true,
//TODO nochmal schauen
[
{
rule: Joi.string().required(),
msg: "No mountpoint given."
},
{
rule: Joi.string().regex(/^\/[^_]/),
msg: "Mountpoints with _ are reserved for internal use."
},
{
rule: Joi.string().regex(/^(\/[a-zA-Z0-9_\-%]+)+$/),
msg: "Mountpoints have to start with / and can only contain [a-zA-Z0-9_-%]"
}
]
)
);
_.each(config, function(obj, name) {
var def;
var check;
switch (obj.type) {
case "boolean":
case "bool":
def = obj.default || false;
entry = window.modalView.createCheckboxEntry(
"app_config_" + name,
name,
def,
obj.description,
def
);
break;
case "integer":
check = [{
rule: Joi.number().integer(),
msg: "Has to be an integer."
}];
default:
if (check === undefined) {
check = [{
rule: Joi.string(),
msg: "Has to be non-empty."
}];
}
if (obj.default === undefined) {
def = "";
} else {
def = String(obj.default);
}
entry = window.modalView.createTextEntry(
"app_config_" + name,
name,
def,
obj.description,
def,
true,
check
);
}
tableContent.push(entry);
});
buttons.push(
window.modalView.createSuccessButton("Configure", this.mountFoxx.bind(this, config, name, version))
);
window.modalView.show(
"modalTable.ejs", "Configure Application", buttons, tableContent
);
},
mountFoxx: function(config, name, version) {
var cfg = {};
try {
_.each(config, function(opt, key) {
var $el = $("#app_config_" + key);
var val = $el.val();
if (opt.type === "boolean") {
cfg[key] = $el.is(":checked");
return;
}
if (val === "" && !opt.hasOwnProperty("default")) {
throw new SyntaxError(
"Must specify value for field \"" +
(opt.label || splitSnakeCase(key)) +
"\"!"
);
}
if (opt.type === "number") {
cfg[key] = parseFloat(val);
} else if (opt.type === "integer") {
cfg[key] = parseInt(val, 10);
} else {
cfg[key] = val;
return;
}
if (_.isNaN(cfg[key])) {
throw new SyntaxError(
"Invalid value for field \"" +
(opt.label || splitSnakeCase(key)) +
"\"!"
);
}
if (opt.type === "integer" && cfg[key] !== Math.floor(parseFloat(val))) {
throw new SyntaxError(
"Expected non-decimal value in field \"" +
(opt.label || splitSnakeCase(key)) +
"\"!"
);
}
});
} catch (err) {
if (err instanceof SyntaxError) {
alert(err.message);
return false;
}
throw err;
}
var self = this;
this.collection.create({
mount: $("#mount-point").val(),
name: name,
version: version,
options: {
configuration: cfg
}
},
{
success: function() {
window.modalView.hide();
self.reload();
},
error: function(e, info) {
if (info.responseText.indexOf("already used by") > -1) {
alert("Mount-Path already in use.");
} else if (info.responseText.indexOf("app is not defined") > -1) {
//temp ignore this message, fix needs to be server-side
window.modalView.hide();
self.reload();
} else {
alert(info.statusText);
}
}
});
},
installFoxx: function() {
this.reload();
},
createInstallModal: function(event) {
event.preventDefault();
var buttons = [];
var modalEvents = {
"click #installGithub" : this.installFoxxFromGithub.bind(this),
"click #installZip" : this.submitGithubFoxx.bind(this),
"click .install-app" : this.submitGithubFoxx.bind(this),
};
window.modalView.show(
"modalApplicationMount.ejs",
"Pijotr",
buttons
"Install Application",
buttons,
undefined,
undefined,
modalEvents
);
}
});
}());

View File

@ -400,8 +400,7 @@
var opts = this.model.get("manifest").configuration;
if (opts && _.keys(opts).length) {
try {
_.each(_.keys(opts), function(key) {
var opt = opts[key];
_.each(opts, function(opt, key) {
var $el = $("#foxx_configs_" + key);
var val = $el.val();
if (opt.type === "boolean") {
@ -453,7 +452,6 @@
version: version
});
//this.model.collection.create({
toCreate.collection.create({
mount: mountPoint,
name: toCreate.get("name"),

View File

@ -14,22 +14,22 @@
};
};
var createTextStub = function(type, label, value, info, placeholder, mandatory, regexp,
var createTextStub = function(type, label, value, info, placeholder, mandatory, joiObj,
addDelete, addAdd, maxEntrySize, tags) {
var obj = {
type: type,
label: label
};
if (value) {
if (value !== undefined) {
obj.value = value;
}
if (info) {
if (info !== undefined) {
obj.info = info;
}
if (placeholder) {
if (placeholder !== undefined) {
obj.placeholder = placeholder;
}
if (mandatory) {
if (mandatory !== undefined) {
obj.mandatory = mandatory;
}
if (addDelete !== undefined) {
@ -44,11 +44,11 @@
if (tags !== undefined) {
obj.tags = tags;
}
if (regexp){
if (joiObj){
// returns true if the string contains the match
obj.validateInput = function(el){
obj.validateInput = function() {
// return regexp.test(el.val());
return regexp;
return joiObj;
};
}
return obj;
@ -311,14 +311,14 @@
self.testInput = (function(){
_.each(completeTableContent,function(r){
if(r.validateInput) {
if(r.validateInput !== undefined) {
//catch result of validation and act
$('#' + r.id).on('keyup focusout', function(e){
var validation = r.validateInput($('#' + r.id));
var error = false, msg;
_.each(validation, function(validator, key) {
_.each(validation, function(validator) {
var schema = Joi.object().keys({
toCheck: validator.rule
@ -334,8 +334,7 @@
toCheck: valueToCheck
},
schema,
function (err, value) {
function (err) {
if (err) {
msg = validator.msg;
error = true;