Skip to content

Commit

Permalink
[CE-36] Add smart contract functions for user dashboard
Browse files Browse the repository at this point in the history
Change-Id: I2255083025ed305987e8efb996a8ac9c7cc7e909
Signed-off-by: lixucheng <[email protected]>
  • Loading branch information
xuchengli committed May 8, 2017
1 parent a8455eb commit 64b7566
Show file tree
Hide file tree
Showing 19 changed files with 1,467 additions and 3 deletions.
1 change: 1 addition & 0 deletions user-dashboard/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ app.use("/", require("./routes/index"));
app.use("/dashboard", require("./routes/dashboard/filter"));
app.use("/dashboard", require("./routes/dashboard/home"));
app.use("/dashboard", require("./routes/dashboard/chain"));
app.use("/dashboard", require("./routes/dashboard/contract"));
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.send(err.message);
Expand Down
63 changes: 63 additions & 0 deletions user-dashboard/modules/mongoclient.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* Created by lixuc on 2017/5/8.
*/
var config = require("./configuration");
var f = require("util").format;
var mongo = require("mongodb");
var Grid = require("gridfs-stream");
var MongoClient = mongo.MongoClient;

function mongoclient() {
var _db;
var _gfs;
this.getDB = function() {
return new Promise(function(resolve, reject) {
if (_db) {
resolve(_db);
} else {
MongoClient.connect(this.url, function(err, db) {
if (err) reject(err);
else {
console.log("Connected successfully to Mongo DB server.");
_db = db;
resolve(db);
}
});
}
}.bind(this));
};
this.getGridFS = function() {
return new Promise(function(resolve, reject) {
if (_gfs) {
resolve(_gfs);
} else {
this.getDB().then(function(db) {
_gfs = Grid(db, mongo);
resolve(_gfs);
}).catch(function(err) {
reject(err);
});
}
}.bind(this));
};
}
mongoclient.prototype = {
url: config.mongodb.auth ?
f(
"mongodb://%s:%s@%s:%s/%s?authMechanism=%s",
encodeURIComponent(config.mongodb.username),
encodeURIComponent(config.mongodb.password),
config.mongodb.ip,
config.mongodb.port,
config.mongodb.name,
"DEFAULT"
)
:
f(
"mongodb://%s:%s/%s",
config.mongodb.ip,
config.mongodb.port,
config.mongodb.name
)
};
module.exports = new mongoclient();
10 changes: 7 additions & 3 deletions user-dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@
"description": "It is the nodeJS version of blockchain dashboard",
"main": "app.js",
"dependencies": {
"cookie-parser": "^1.4.3",
"body-parser": "^1.17.1",
"cookie-parser": "^1.4.3",
"express": "^4.15.2",
"express-session": "^1.15.2",
"gridfs-stream": "^1.1.1",
"mongodb": "^2.2.26",
"multer": "^1.3.0",
"multer-gridfs-storage": "^1.1.1",
"node-uuid": "^1.4.8",
"pug": "^2.0.0-rc.1",
"request-promise": "^4.2.0",
"request": "^2.81.0",
"node-uuid": "^1.4.8"
"request-promise": "^4.2.0"
},
"devDependencies": {},
"scripts": {
Expand Down
19 changes: 19 additions & 0 deletions user-dashboard/public/css/dashboard/contract-list.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@CHARSET "UTF-8";
.ds-sc-list{width:80%;margin-top:60px;font-family:"Helvetica Neue",Arial,sans-serif;}
.ds-sc-list h1{font-size:24px;color:#4178BE;margin-top:42px;border-bottom:2px solid #4178BE;}
.ds-sc-list th{font-size:16px;color:#4178BE;}
.ds-sc-list thead :hover{color:#FF5003;}
.break_word{word-break:break-all;word-wrap:break-word;}
.img-dropdown{margin-right:12px;margin-left:-2px;}
.add-section{margin-top:40px;}
.add-section a{color:#FF5003;line-height:29px;font-size:16px;}
.add-section a.not-active{color:#999;pointer-events:none;cursor:default;}
.gray{-webkit-filter:grayscale(100%);-moz-filter:grayscale(100%);-ms-filter:grayscale(100%);-o-filter:grayscale(100%);
filter:grayscale(100%);filter:gray;}
.no-result{color:#b2b2b2;text-align:center;line-height:80px;font-style:italic;font-size:24px;}
.upload-overlayer{position:absolute;top:0;left:0;width:100%;height:100%;
background:#fff;z-index:1000;opacity:0;display:none;}
.contract-placeholder{background:#fff none repeat scroll 0 0;border:1px dashed #ddd;border-radius:4px;
color:#999;width:100%;}
.modal_small{min-height:0;width:350px;}
.warning{background:url(/images/warning.png) no-repeat;padding-left:60px;line-height:48px;color:#666;}
87 changes: 87 additions & 0 deletions user-dashboard/public/js/app/dashboard/contract/delete.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
* Created by lixuc on 2017/5/8.
*/
define([
"jquery",
"cookie",
"app/kit/ui",
"app/kit/storage",
"plugin/text!resources/dashboard/contract/deletedialog.html"
], function($, Cookies, UI, Storage, deletedialog) {
var ui = new UI();
var storage = new Storage();
var $deletedialog;
var $deleteContractDialog;
var $deleteSubmit;
var $deleteCancel;

function deletecontract(list) {
function disableAllElement(disabled) {
if (disabled) {
$deleteContractDialog.options.bgclose = false;
} else {
$deleteContractDialog.options.bgclose = true;
}
$deleteSubmit.attr("disabled", disabled);
$deleteCancel.attr("disabled", disabled);
}
this.init = function(id) {
$deleteSubmit = $("#delete_contract_submit");
$deleteCancel = $("#delete_contract_cancel");

$deleteSubmit.on("click", function() {
var $spinner = $("<i class='uk-icon-spinner uk-icon-spin'></i>");
disableAllElement(true);
$(this).append($spinner);
var userInfo = Cookies.getJSON("BlockChainAccount");
$.ajax({
type: "POST",
url: "/api/" + userInfo.apikey + "/contract/" + id + "/delete",
dataType: "json",
success: function(data) {
$spinner.remove();
disableAllElement(false);
if (data.success) {
//将存储在本地的函数名和参数删除
storage.remove(id);
$deleteContractDialog.hide();
ui.dialog.success("Delete successfully.", 3000);
//Currently because only private contracts can be deleted,
//so after deleted, I only need to refresh private contract list
list.search("private", 1);
} else {
ui.dialog.error(data.message);
}
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
$spinner.remove();
disableAllElement(false);
ui.dialog.error(errorThrown);
}
});
});
$deleteCancel.on("click", function() {
$deleteContractDialog.hide();
});
}
}
deletecontract.prototype = {
show: function(id) {
var _self = this;
$deletedialog = $(deletedialog);
$deletedialog.on({
"show.uk.modal": function() {
_self.init(id);
},
"hide.uk.modal": function() {
$(this).remove();
}
});
$("body").append($deletedialog);
$deleteContractDialog = UIkit.modal($deletedialog);
$deleteContractDialog.options.center = true;
$deleteContractDialog.show();
}
};
return deletecontract;
});
188 changes: 188 additions & 0 deletions user-dashboard/public/js/app/dashboard/contract/deploy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
/**
* Created by lixuc on 2017/5/8.
*/
define([
"jquery",
"cookie",
"app/kit/ui",
"app/kit/common",
"app/kit/storage",
"plugin/text!resources/dashboard/contract/deploydialog.html",
"lodash"
], function($, Cookies, UI, Common, Storage, deploydialog) {
var ui = new UI();
var common = new Common();
var storage = new Storage();
var $deploydialog;
var $deployContractDialog;
var $deployChain;
var $instanceName;
var $deployFunction;
var $functionListDropdown;
var $functionList;
var $deployArgument;
var $deploySubmit;
var $deployCancel;

function deploycontract() {
function disableAllElement(disabled) {
if (disabled) {
$deployContractDialog.options.bgclose = false;
} else {
$deployContractDialog.options.bgclose = true;
}
$deployChain.attr("disabled", disabled);
$instanceName.attr("disabled", disabled);
$deployFunction.attr("disabled", disabled);
$deployArgument.attr("disabled", disabled);
$deploySubmit.attr("disabled", disabled);
$deployCancel.attr("disabled", disabled);
}
function loadChain() {
var userInfo = Cookies.getJSON("BlockChainAccount");
disableAllElement(true);
$.ajax({
type: "GET",
url: "/api/" + userInfo.apikey + "/chain/list",
data: {
page: -1
},
dataType: "json",
success: function(data) {
disableAllElement(false);
if (data.success) {
$deployChain.empty();
for (var i in data.chains) {
var chain = data.chains[i];
$deployChain.append("<option value='" + chain.id + "'>" + chain.name + "</option>");
}
} else {
ui.dialog.error(data.message);
}
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
disableAllElement(false);
ui.dialog.error(errorThrown);
}
});
}
this.init = function(id) {
$deployChain = $("#deploy_contract_chain");
$instanceName = $("#deploy_contract_instance_name");
$deployFunction = $("#deploy_contract_function");
$functionListDropdown = $("#deploy_function_dropdown");
$functionList = $("#deploy_function_dropdown ul");
$deployArgument = $("#deploy_contract_argument");
$deploySubmit = $("#deploy_contract_submit");
$deployCancel = $("#deploy_contract_cancel");

loadChain();
//从本地存储中获取到函数名和参数
var deploy = storage.get("deploy", id);
$functionList.empty();
for (var i in deploy) {
$("<li data-args='" + _.escape(JSON.stringify(deploy[i].args)) + "'>" +
"<a>" + deploy[i].func + "</a>" +
"</li>").click(function() {
$deployFunction.val($(this).find("a").text());
$deployArgument.val(JSON.stringify($(this).data("args")));
}).appendTo($functionList);
}
$deployFunction.on("focus blur", function(evt) {
if ($functionList.children().length > 0) {
if (evt.type == "focus") {
$functionListDropdown.show();
} else if (evt.type == "blur") {
setTimeout(function() {
$functionListDropdown.hide();
}, 200);
}
}
});
$deploySubmit.on("click", function() {
if (!$deployChain.val()) {
ui.dialog.warning("Please select a chain.");
$deployChain.focus();
return;
} else if ($instanceName.val() == "") {
ui.dialog.warning("Please input the instance name.");
$instanceName.focus();
return;
} else if ($deployFunction.val() == "") {
ui.dialog.warning("Please input the function name.");
$deployFunction.focus();
return;
} else if ($deployArgument.val() == "") {
ui.dialog.warning("Please input the function arguments.");
$deployArgument.focus();
return;
}
var deployArgs = common.parseJSON($deployArgument.val());
if (!deployArgs) {
ui.dialog.warning("Please input valid function arguments.");
$deployArgument.focus();
return;
}
var $spinner = $("<i class='uk-icon-spinner uk-icon-spin'></i>");
disableAllElement(true);
$(this).append($spinner);
$.ajax({
type: "POST",
url: "/api/contract/" + id + "/deploy",
data: {
chain: $deployChain.val(),
name: $instanceName.val(),
func: $deployFunction.val(),
args: $deployArgument.val()
},
dataType: "json",
success: function(data) {
$spinner.remove();
disableAllElement(false);
if (data.success) {
//本地存储用户输入的函数名和参数
storage.set("deploy", id, {
func: $deployFunction.val(),
args: deployArgs
});
$deployContractDialog.hide();
ui.dialog.success("Deploy successfully.", 3000);
setTimeout(function() {
$(location).attr("href", "/dashboard/chain/" + $deployChain.val());
}, 1000);
} else {
ui.dialog.error(data.message);
}
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
$spinner.remove();
disableAllElement(false);
ui.dialog.error(errorThrown);
}
});
});
$deployCancel.on("click", function() {
$deployContractDialog.hide();
});
}
}
deploycontract.prototype = {
show: function(id) {
var _self = this;
$deploydialog = $(deploydialog);
$deploydialog.on({
"show.uk.modal": function() {
_self.init(id);
},
"hide.uk.modal": function() {
$(this).remove();
}
});
$("body").append($deploydialog);
$deployContractDialog = UIkit.modal($deploydialog);
$deployContractDialog.options.center = true;
$deployContractDialog.show();
}
};
return deploycontract;
});
Loading

0 comments on commit 64b7566

Please sign in to comment.