mirror of
https://github.com/zhigang1992/deployd.git
synced 2026-05-12 19:59:03 +08:00
Merge branch '0.7' of https://github.com/deployd/deployd into 0.7
This commit is contained in:
10
bin/dpd
10
bin/dpd
@@ -328,8 +328,14 @@ program
|
||||
d.package(tar, function (err) {
|
||||
if(err) return console.error(err);
|
||||
console.log('pushing...');
|
||||
d.publish('http://deploy.deploydapp.com:3003', tar, key, function (err) {
|
||||
if(err) return console.error('failed to push:', err.message || 'could not push app to ' + DPDAPP_URL);
|
||||
d.publish('http://cloud.deployd.com', tar, key, function (err) {
|
||||
if(err) {
|
||||
if (err.statusCode === 401) {
|
||||
d.setConfig('sid', undefined);
|
||||
d.setConfig('user', undefined);
|
||||
}
|
||||
return console.error('failed to push:', err.message || 'could not push app to ' + DPDAPP_URL);
|
||||
}
|
||||
console.log('deployd app to http://' + d.subdomain + '.deploydapp.com!');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,8 +15,8 @@ var path = require('path')
|
||||
function Deployment(appPath, user, subdomain) {
|
||||
var remote = this.remote = 'deploydapp.com';
|
||||
|
||||
this.api = "http://api.deploydapp.com:3000";
|
||||
this.deployUrl = "http://deploy.deploydapp.com:3003";
|
||||
this.api = "http://api.deployd.com";
|
||||
this.deployUrl = "http://cloud.deployd.com";
|
||||
|
||||
this.path = path.resolve(appPath);
|
||||
|
||||
@@ -100,7 +100,12 @@ Deployment.prototype.publish = function (url, tar, key, callback) {
|
||||
|
||||
function done(err, res, body) {
|
||||
if(err) return callback(err);
|
||||
if(res.statusCode >= 400) return callback(new Error(body));
|
||||
|
||||
if(res.statusCode >= 400) {
|
||||
var error = new Error(body);
|
||||
error.statusCode = res.statusCode;
|
||||
return callback(error);
|
||||
}
|
||||
callback(null, deployment.getConfig(deployment.configKey()));
|
||||
}
|
||||
|
||||
@@ -119,12 +124,7 @@ Deployment.prototype.publish = function (url, tar, key, callback) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if(res.statusCode !== 200) {
|
||||
deployment.setConfig('sid', undefined);
|
||||
deployment.setConfig('user', undefined);
|
||||
delete deployment.sid;
|
||||
delete deployment.user;
|
||||
} else {
|
||||
if(res.statusCode === 200) {
|
||||
|
||||
try {
|
||||
body = JSON.parse(body);
|
||||
@@ -227,6 +227,7 @@ Deployment.prototype.getCurrentUser = function(fn) {
|
||||
jar: false
|
||||
}, function(err, res, user) {
|
||||
if (err) return fn(err);
|
||||
if (res.statusCode === 404) return fn(new Error("Could not connect"));
|
||||
if (user) user = JSON.parse(user);
|
||||
if (!user) return fn(new Error("Not authenticated"));
|
||||
fn(null, user);
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
<div id="deployments">
|
||||
<div class="well hide" id="deployments-connection-error">
|
||||
<h3>Deployments</h3>
|
||||
<div class="">
|
||||
<p>Could not connect to <a target="_blank" href="http://cloud.deployd.com">cloud.deployd.com</a></p>
|
||||
<a href="">Refresh</a>
|
||||
<div class="modal hide" id="deployments-connection-error">
|
||||
<div class="modal-header">
|
||||
<h3>Deployments</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Could not connect to <a target="_blank" href="http://cloud.deployd.com">cloud.deployd.com</a>.</p>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="" class="btn">Refresh</a>
|
||||
<a href="/dashboard" class="cancel-btn">cancel</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="well hide" id="inner-deployments">
|
||||
@@ -16,36 +22,40 @@
|
||||
|
||||
<div class="clearfix"></div>
|
||||
|
||||
|
||||
|
||||
<div id="deployments-empty" class="hide">
|
||||
|
||||
<hr />
|
||||
|
||||
<p>Create your first Deployment to host your app on <a href="http://cloud.deployd.com">cloud.deployd.com</a>:</p>
|
||||
</div>
|
||||
|
||||
<div id="deployment-list-container">
|
||||
|
||||
<ul class="component-list" id="deployment-list">
|
||||
</ul>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="form-placeholder">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="form-inline" id="deploy-new-form">
|
||||
<input type="text" class="input-large deployment-name" placeholder="new-deployment" />
|
||||
<span class="help-inline">.deploydapp.com</span>
|
||||
</div>
|
||||
|
||||
<button class="pull-right btn btn-success">
|
||||
<i class="icon-plus icon-white"></i>
|
||||
Add and Deploy
|
||||
</button>
|
||||
<br />
|
||||
<div id="deployments-empty" class="modal hide">
|
||||
<div class="modal-header clearfix">
|
||||
<h3>
|
||||
Create a Deployment
|
||||
<div class="header-link pull-right">
|
||||
<span class="username">USERNAME</span>
|
||||
| <a href="#" class="logout-btn">log out</a>
|
||||
</div>
|
||||
</h3>
|
||||
|
||||
<select id="existing-deployment-dropdown" class="empty hide">
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Create your first Deployment to host your app on <a href="http://cloud.deployd.com">cloud.deployd.com</a>:</p>
|
||||
<hr />
|
||||
<div class="form-placeholder">
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="modal-footer">
|
||||
<a href="#" class="cancel-btn logout-btn">log out</a>
|
||||
<a href="/dashboard" class="cancel-btn">cancel</a>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -86,10 +96,36 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="form-inline hide" id="deploy-new-form">
|
||||
<input type="text" class="input-large deployment-name" placeholder="new-deployment" />
|
||||
<span class="help-inline">.deploydapp.com</span>
|
||||
|
||||
<button class="pull-right btn btn-success">
|
||||
<i class="icon-plus icon-white"></i>
|
||||
Add and Deploy
|
||||
</button>
|
||||
<br />
|
||||
|
||||
<div id="existing-deployment-dropdown-btn" class="hide btn-group pull-right" style="margin-top: 10px">
|
||||
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="icon-plus"></i>
|
||||
Add Existing Deployment
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu" id="existing-deployment-dropdown">
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
||||
<!-- <select id="existing-deployment-dropdown" class="empty hide">
|
||||
</select> -->
|
||||
</form>
|
||||
|
||||
<script type="text/html" id="deployment-template">
|
||||
<li id="deployment-<%= deployment.appId %>" class="component-item <%= deployment.deploying ? 'deploying' : '' %>" data-index="<%= index %>">
|
||||
<div class="component-item-header">
|
||||
<span class="code deploymentname"><%= deployment.name %> <i class="icon-white icon-external-link open-icon"></i></span>
|
||||
<span class="code deploymentname"><%= deployment.name %> <% if (!deployment.deploying) { %><i class="icon-white icon-external-link open-icon"></i><% } %></span>
|
||||
<% if (deployment.deploying) { %>
|
||||
<div class="pull-right deploy-status">
|
||||
<span class="deploy-status-text">Deploying...</span>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
var dpdDeployments = dpd('__deployments');
|
||||
var deploymentTemplate = _.template($('#deployment-template').html());
|
||||
var $modal = $('#deployAuthModal').modal({
|
||||
backdrop: 'static',
|
||||
backdrop: false,
|
||||
keyboard: false,
|
||||
show: false
|
||||
});
|
||||
@@ -27,7 +27,7 @@
|
||||
$('#deployment-list').on('click', '.deploy-btn', onClickDeployBtn);
|
||||
$('#deployment-list').on('click', '.remove-btn', onClickRemoveBtn);
|
||||
|
||||
$('#inner-deployments h3 .logout-btn').click(function() {
|
||||
$('#deployments h3 .logout-btn').click(function() {
|
||||
onClickLogoutBtn();
|
||||
return false;
|
||||
});
|
||||
@@ -38,7 +38,7 @@
|
||||
deployNew();
|
||||
return false;
|
||||
});
|
||||
$('#existing-deployment-dropdown').change(onSelectExistingDeployment);
|
||||
$('#existing-deployment-dropdown').on('click', 'li a', onSelectExistingDeployment);
|
||||
|
||||
function loadDeployments() {
|
||||
dpdDeployments.get(function(deployments, error) {
|
||||
@@ -114,6 +114,7 @@
|
||||
Object.keys(result).forEach(function(k) {
|
||||
deployment[k] = result[k];
|
||||
});
|
||||
deployment.id = result.appId;
|
||||
deployment.__deployed = true;
|
||||
}
|
||||
|
||||
@@ -152,6 +153,7 @@
|
||||
function onClickDeployment(e) {
|
||||
if ($(e.target).is('a')) return true;
|
||||
var deployment = getDeployment(e.currentTarget);
|
||||
if (deployment.deploying) return true;
|
||||
var href = "http://" + deployment.name + ".deploydapp.com";
|
||||
window.open(href, "_blank");
|
||||
window.focus();
|
||||
@@ -194,16 +196,12 @@
|
||||
}
|
||||
|
||||
function onSelectExistingDeployment(e) {
|
||||
var $dropdown = $(this);
|
||||
var name = $dropdown.val();
|
||||
if (name === "__") return true;
|
||||
var $link = $(this);
|
||||
var name = $link.attr('data-value');
|
||||
|
||||
$dropdown.attr('disabled', true);
|
||||
deployNew(name);
|
||||
|
||||
deployNew(name, function() {
|
||||
$dropdown.removeAttr('disabled');
|
||||
$dropdown.val("__");
|
||||
});
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
function onClickLogoutBtn() {
|
||||
@@ -213,14 +211,13 @@
|
||||
}
|
||||
|
||||
function showLogin(error) {
|
||||
renderDeployments();
|
||||
if (scope.user) {
|
||||
$modal.modal('hide');
|
||||
$('#inner-deployments').show();
|
||||
$('#deployments h3 .username').text(scope.user.username);
|
||||
$('#deploy-new-form .deployment-name').focus();
|
||||
} else {
|
||||
$modal.modal('show');
|
||||
$('#inner-deployments').hide();
|
||||
if (error) {
|
||||
$('#auth-error').show();
|
||||
} else {
|
||||
@@ -231,53 +228,62 @@
|
||||
}
|
||||
|
||||
function renderDeployments() {
|
||||
if (scope.deployments === null || scope.deployments.length) {
|
||||
$('#deployments-empty').hide();
|
||||
$('#deployment-list-container').show();
|
||||
if (scope.user) {
|
||||
if (scope.deployments === null || scope.deployments.length) {
|
||||
$('#deployments-empty').hide();
|
||||
$('#inner-deployments').show();
|
||||
$('#deploy-new-form').appendTo('#inner-deployments .form-placeholder').show();
|
||||
} else {
|
||||
$('#deployments-empty').show();
|
||||
$('#inner-deployments').hide();
|
||||
$('#deploy-new-form').appendTo('#deployments-empty .form-placeholder').show();
|
||||
var $input = $('#deploy-new-form .deployment-name');
|
||||
if (!$input.val()) $input.val(Context.appName);
|
||||
}
|
||||
|
||||
if (scope.deployments) {
|
||||
$('#deployment-list').empty();
|
||||
|
||||
// clean up orphaned tooltips
|
||||
$('body > .tooltip').each(function() {
|
||||
var $tooltip = $(this);
|
||||
$tooltip.fadeOut(function() {
|
||||
$tooltip.remove();
|
||||
});
|
||||
});
|
||||
|
||||
scope.deployments.forEach(function(d, i) {
|
||||
$('#deployment-list').append(deploymentTemplate({
|
||||
deployment: d,
|
||||
index: i
|
||||
}));
|
||||
|
||||
if (d.__deployed) {
|
||||
showDeploymentTooltip(d);
|
||||
d.__deployed = false;
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
} else {
|
||||
$('#deployments-empty').show();
|
||||
$('#deployment-list-container').hide();
|
||||
var $input = $('#deploy-new-form .deployment-name');
|
||||
if (!$input.val()) $input.val(Context.appName);
|
||||
}
|
||||
|
||||
if (scope.deployments) {
|
||||
$('#deployment-list').empty();
|
||||
|
||||
// clean up orphaned tooltips
|
||||
$('body > .tooltip').each(function() {
|
||||
var $tooltip = $(this);
|
||||
$tooltip.fadeOut(function() {
|
||||
$tooltip.remove();
|
||||
});
|
||||
});
|
||||
|
||||
scope.deployments.forEach(function(d, i) {
|
||||
$('#deployment-list').append(deploymentTemplate({
|
||||
deployment: d,
|
||||
index: i
|
||||
}));
|
||||
|
||||
if (d.__deployed) {
|
||||
showDeploymentTooltip(d);
|
||||
d.__deployed = false;
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
$('#deployments-empty').hide();
|
||||
$('#deployments-empty').hide();
|
||||
}
|
||||
}
|
||||
|
||||
function renderOnlineDeployments() {
|
||||
var $dropdownBtn = $('#existing-deployment-dropdown-btn');
|
||||
var $dropdown = $('#existing-deployment-dropdown');
|
||||
if (scope.onlineDeployments && scope.onlineDeployments.length) {
|
||||
$dropdown.show().empty();
|
||||
$dropdown.append('<option value="__">or add an existing deployment...</option>');
|
||||
$dropdownBtn.show();
|
||||
$dropdown.empty();
|
||||
// $dropdown.append('<option value="__">or add an existing deployment...</option>');
|
||||
scope.onlineDeployments.forEach(function(o) {
|
||||
$dropdown.append('<option value="' + o.name + '">' + o.name + "</option>");
|
||||
$dropdown.append('<li><a href="#" data-value="' + o.name + '">' + o.name + "</a></li>");
|
||||
});
|
||||
} else {
|
||||
$dropdown.hide();
|
||||
$dropdownBtn.hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,10 @@
|
||||
width: 585px;
|
||||
max-width: 585px;
|
||||
|
||||
#deploy-new-form {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
hr {
|
||||
border-bottom: none;
|
||||
border-width: 1px;
|
||||
@@ -45,9 +49,16 @@
|
||||
|
||||
#deployments-empty {
|
||||
|
||||
.well {
|
||||
padding: 20px;
|
||||
color: #fff;
|
||||
overflow: visible;
|
||||
|
||||
.modal-body {
|
||||
overflow-y: visible;
|
||||
}
|
||||
|
||||
|
||||
|
||||
hr {
|
||||
border-top-color: #ccc;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -101,18 +112,27 @@
|
||||
}
|
||||
}
|
||||
|
||||
#existing-deployment-dropdown {
|
||||
|
||||
|
||||
/*#existing-deployment-dropdown {
|
||||
margin-top: 10px;
|
||||
color: #999;
|
||||
|
||||
option {
|
||||
&:first-child {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
#deployments-empty #existing-deployment-dropdown {
|
||||
option {
|
||||
color: @black;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#inner-deployments #existing-deployment-dropdown {
|
||||
option {
|
||||
color: white;
|
||||
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
#deployAuthModal {
|
||||
@@ -141,7 +161,9 @@
|
||||
color: @textColor !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal {
|
||||
.cancel-btn {
|
||||
display: inline-block;
|
||||
margin-left: 8px;
|
||||
|
||||
@@ -34,15 +34,20 @@ body {
|
||||
color: white;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
font-size: 11pt;
|
||||
font-size: 16px;
|
||||
line-height: 38px;
|
||||
|
||||
> i {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
&:hover, &.active {
|
||||
background: rgba(255,255,255, 0.1);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.caret {
|
||||
opacity: 1;
|
||||
border-top-color: white;
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
@@ -4071,15 +4071,19 @@ body {
|
||||
color: white;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
font-size: 11pt;
|
||||
font-size: 16px;
|
||||
line-height: 38px;
|
||||
}
|
||||
#header .header-link > i {
|
||||
margin-top: 2px;
|
||||
}
|
||||
#header .header-link:hover,
|
||||
#header .header-link.active {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
text-decoration: none;
|
||||
}
|
||||
#header .header-link .caret {
|
||||
opacity: 1;
|
||||
border-top-color: white;
|
||||
margin-top: 18px;
|
||||
}
|
||||
@@ -4267,15 +4271,43 @@ body {
|
||||
#deployments {
|
||||
width: 585px;
|
||||
max-width: 585px;
|
||||
/*#existing-deployment-dropdown {
|
||||
margin-top: 10px;
|
||||
color: #999;
|
||||
|
||||
}
|
||||
|
||||
#deployments-empty #existing-deployment-dropdown {
|
||||
option {
|
||||
color: @black;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#inner-deployments #existing-deployment-dropdown {
|
||||
option {
|
||||
color: white;
|
||||
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
#deployments #deploy-new-form {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
#deployments hr {
|
||||
border-bottom: none;
|
||||
border-width: 1px;
|
||||
border-top-color: #555555;
|
||||
}
|
||||
#deployments #deployments-empty .well {
|
||||
padding: 20px;
|
||||
color: #fff;
|
||||
#deployments #deployments-empty {
|
||||
overflow: visible;
|
||||
}
|
||||
#deployments #deployments-empty .modal-body {
|
||||
overflow-y: visible;
|
||||
}
|
||||
#deployments #deployments-empty hr {
|
||||
border-top-color: #ccc;
|
||||
}
|
||||
#deployments .component-item.deploying .component-item-header {
|
||||
box-shadow: inset 0 0 10px 0px #429e96;
|
||||
@@ -4313,16 +4345,6 @@ body {
|
||||
#deployments .component-item-header:hover .open-icon {
|
||||
visibility: visible;
|
||||
}
|
||||
#deployments #existing-deployment-dropdown {
|
||||
margin-top: 10px;
|
||||
color: #999;
|
||||
}
|
||||
#deployments #existing-deployment-dropdown option {
|
||||
color: white;
|
||||
}
|
||||
#deployments #existing-deployment-dropdown option:first-child {
|
||||
color: #999;
|
||||
}
|
||||
#deployAuthModal .row {
|
||||
margin-top: 20px;
|
||||
}
|
||||
@@ -4338,7 +4360,7 @@ body {
|
||||
#deployAuthModal .form-vertical label {
|
||||
color: #666666 !important;
|
||||
}
|
||||
#deployAuthModal .cancel-btn {
|
||||
.modal .cancel-btn {
|
||||
display: inline-block;
|
||||
margin-left: 8px;
|
||||
vertical-align: middle;
|
||||
@@ -5109,7 +5131,9 @@ select {
|
||||
#dialog input,
|
||||
.modal input,
|
||||
#dialog textarea,
|
||||
.modal textarea {
|
||||
.modal textarea,
|
||||
#dialog select,
|
||||
.modal select {
|
||||
background-color: #ffffff;
|
||||
color: #666666;
|
||||
}
|
||||
@@ -5726,6 +5750,8 @@ table input[type=number] {
|
||||
}
|
||||
.modal-header h3 {
|
||||
color: #363535;
|
||||
line-height: 22px;
|
||||
margin: 2px 0 2px 0;
|
||||
}
|
||||
#api table {
|
||||
margin-bottom: 0;
|
||||
|
||||
@@ -100,7 +100,7 @@ background-color: darken(@black, 10%);
|
||||
|
||||
input, textarea, select {background: darken(@black, 10%); color: @white; border: solid 1px @black;}
|
||||
#dialog, .modal {
|
||||
input, textarea {
|
||||
input, textarea, select {
|
||||
background-color: #ffffff;
|
||||
color: @textColor;
|
||||
}
|
||||
@@ -788,7 +788,11 @@ table input {
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
h3 {color: @black;}
|
||||
h3 {
|
||||
color: @black;
|
||||
line-height: 22px;
|
||||
margin: 2px 0 2px 0;
|
||||
}
|
||||
}
|
||||
|
||||
#api {
|
||||
|
||||
@@ -4,6 +4,8 @@ var util = require('util')
|
||||
, path = require('path')
|
||||
, q = require('q')
|
||||
, qutil = require('../util/qutil')
|
||||
, Keys = require('../keys')
|
||||
, keys = new Keys()
|
||||
, Deployment = require('../client/deploy').Deployment;
|
||||
|
||||
function InternalDeployments() {
|
||||
@@ -119,9 +121,23 @@ InternalDeployments.prototype.deploy = function(ctx, next) {
|
||||
|
||||
var d = new Deployment('.', null, subdomain);
|
||||
|
||||
var keyGenQ = q.nfcall(function(fn) {
|
||||
keys.getLocal(function (err, key) {
|
||||
if(err) return fn(err);
|
||||
if(key) {
|
||||
fn(null, key);
|
||||
} else {
|
||||
keys.create(function(err, key) {
|
||||
if(err) return fn(err);
|
||||
fn(null, key);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var authQ = qutil.cinvoke(d, 'authenticate');
|
||||
|
||||
var packageQ = authQ.then(function(ok) {
|
||||
var packageQ = q.spread([authQ, keyGenQ], function(ok) {
|
||||
if (ok) {
|
||||
return q.ninvoke(d, 'package', self.packageFile);
|
||||
} else {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div data-bind="scrollbarWidth: view.scrollWidth"></div>
|
||||
<div id="data" class="well full-page">
|
||||
<div id="data" class="well">
|
||||
<h3>Data</h3>
|
||||
|
||||
<div id="no-property-warning" class="alert alert-info hide">
|
||||
@@ -7,7 +7,7 @@
|
||||
<a href="../properties">Add some now</a> before editing data.
|
||||
</div>
|
||||
|
||||
<div id="table-container" data-bind="scrollY: view.scrollY, scrollX: view.scrollX, screenDimensions: view.dimensions, reflow: view.init">
|
||||
<div id="table-container" data-bind="scrollY: view.scrollY, scrollX: view.scrollX, screenDimensions: view.dimensions, reflow: view.init, style: {height: view.dimensions().height + 'px'}">
|
||||
|
||||
<div id="editor-modal" class="modal hide" data-bind="if: propertiesLoaded, bootstrapModal: edit.editingModal">
|
||||
<div class="modal-header">
|
||||
@@ -29,7 +29,7 @@
|
||||
<div class="mini-edit" data-bind="style: {top: view.selectedCellPos().top + 'px', left: view.selectedCellPos().left + 'px'}, if: edit.editingInline, click: view.noOp, clickBubble: false">
|
||||
<!-- ko if: selectedProp().type === 'string' -->
|
||||
<a href="#" title="Edit in modal" data-bind="click: edit.openModal"><i class="icon-edit icon-white"></i></a>
|
||||
<input type="text" data-bind="hasfocus: edit.focusInput, select: 'selectEditor', value: edit.editValue, valueUpdate: 'afterkeydown', typeahead: edit.typeahead" />
|
||||
<input type="text" class="inline-editor-input" data-bind="hasfocus: edit.focusInput, select: 'selectEditor', customValue: edit.editValue, valueUpdate: 'afterkeydown', typeahead: edit.typeahead" />
|
||||
<!-- /ko -->
|
||||
<!-- ko if: selectedProp().type === 'number' -->
|
||||
<input type="text" class="number" data-bind="hasfocus: edit.focusInput, select: 'selectEditor', numberValue: edit.editValue, valueUpdate: 'afterkeydown'" />
|
||||
|
||||
@@ -207,7 +207,7 @@
|
||||
var val = vm.selectedRow()[vm.selectedProp().name]();
|
||||
|
||||
if (type === 'string') {
|
||||
return !val || val.indexOf('\n') === -1;
|
||||
return !val || val.toString().indexOf('\n') === -1;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -159,22 +159,28 @@ ko.bindingHandlers.screenDimensions = {
|
||||
function calculateScreenDimensions(element) {
|
||||
var $element = $(element)
|
||||
, $window = $(window)
|
||||
, top = $element.offset().top - $window.scrollTop()
|
||||
, windowHeight = $window.height()
|
||||
, windowWidth = $window.width()
|
||||
, staticTop = $element.offset().top
|
||||
, top = staticTop - $window.scrollTop()
|
||||
, left = $element.offset().left - $window.scrollLeft()
|
||||
, height = $element.height()
|
||||
, height = windowHeight - staticTop - 60 // 60 is bottom padding - probably shouldn't be hardcoded
|
||||
, width = $element.width()
|
||||
, bottom = top + height
|
||||
, right = left + width
|
||||
, bottomRelative = $(window).height() - bottom
|
||||
, rightRelative = $(window).width() - right;
|
||||
, bottomRelative = windowHeight - bottom
|
||||
, rightRelative = windowWidth - right;
|
||||
|
||||
return {
|
||||
top: top
|
||||
staticTop: staticTop
|
||||
, top: top
|
||||
, left: left
|
||||
, bottom: bottom
|
||||
, right: right
|
||||
, height: height
|
||||
, width: width
|
||||
, windowHeight: windowHeight
|
||||
, windowWidth: windowWidth
|
||||
, bottomRelative: bottomRelative
|
||||
, rightRelative: rightRelative
|
||||
};
|
||||
@@ -220,13 +226,46 @@ ko.bindingHandlers.element = {
|
||||
}
|
||||
};
|
||||
|
||||
// I don't know why I have to do this; seems like Knock's built-in version is bugged
|
||||
ko.bindingHandlers.customValue = {
|
||||
init: function(element, valueAccessor, allBindingsAccessor, vm) {
|
||||
var prop = valueAccessor()
|
||||
, allBindings = allBindingsAccessor()
|
||||
, updateMode = allBindings.valueUpdate || 'blur';
|
||||
|
||||
if (typeof prop === 'function') {
|
||||
|
||||
if (updateMode === 'afterkeydown') {
|
||||
|
||||
$(element).on('keydown', function(e) {
|
||||
setTimeout(function() {
|
||||
prop($(element).val());
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
|
||||
$(element).blur(function() {
|
||||
prop($(element).val());
|
||||
});
|
||||
}
|
||||
}, update: function(element, valueAccessor) {
|
||||
var newVal = ko.utils.unwrapObservable(valueAccessor());
|
||||
|
||||
if (newVal !== $(element).val()) {
|
||||
$(element).val(newVal);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ko.bindingHandlers.numberValue = {
|
||||
init: function(element, valueAccessor, allBindingsAccessor, vm) {
|
||||
var prop = valueAccessor()
|
||||
, allBindings = allBindingsAccessor()
|
||||
, updateMode = allBindings.valueUpdate || 'blur';
|
||||
|
||||
$(element).val(ko.utils.unwrapObservable(prop));
|
||||
if (parseFloat($(element).val()) !== ko.utils.unwrapObservable(prop)) {
|
||||
$(element).val(ko.utils.unwrapObservable(prop));
|
||||
}
|
||||
|
||||
if (typeof prop === 'function') {
|
||||
|
||||
@@ -234,7 +273,7 @@ ko.bindingHandlers.numberValue = {
|
||||
|
||||
$(element).on('keydown', function(e) {
|
||||
var num = parseFloat($(element).val());
|
||||
if (isNaN(num)) return;
|
||||
if (isNaN(num)) return true;
|
||||
|
||||
if (e.which == 38) { // up
|
||||
prop(num + 1);
|
||||
@@ -266,7 +305,7 @@ ko.bindingHandlers.numberValue = {
|
||||
|
||||
function setNumberProp(element, prop) {
|
||||
var num = parseFloat($(element).val());
|
||||
if (!isNaN(num)) prop(num);
|
||||
if (!isNaN(num) && prop() != num) prop(num);
|
||||
}
|
||||
|
||||
ko.bindingHandlers.select = {
|
||||
@@ -323,10 +362,10 @@ ko.bindingHandlers.aceEditor = {
|
||||
$(element).data('aceEditor', editor);
|
||||
|
||||
editor.getSession().on('change', function(e) {
|
||||
var newVal = editor.getValue();
|
||||
if (newVal !== val()) {
|
||||
val(newVal);
|
||||
}
|
||||
var newVal = editor.getValue();
|
||||
if (newVal !== val() && $(element).is(':visible')) {
|
||||
val(newVal);
|
||||
}
|
||||
});
|
||||
}, update: function(element, valueAccessor) {
|
||||
var editor = $(element).data('aceEditor')
|
||||
@@ -338,7 +377,6 @@ ko.bindingHandlers.aceEditor = {
|
||||
val = val.toString();
|
||||
}
|
||||
|
||||
|
||||
if (val !== editor.getValue()) {
|
||||
editor.setValue(val);
|
||||
}
|
||||
@@ -358,6 +396,21 @@ ko.bindingHandlers.aceEditorResize = {
|
||||
}
|
||||
};
|
||||
|
||||
// ko.bindingHandlers.customHasFocus = {
|
||||
// update: function(element, valueAccessor) {
|
||||
// var $el = $(element)
|
||||
// , val = ko.utils.unwrapObservable(valueAccessor());
|
||||
|
||||
// setTimeout(function() {
|
||||
// if (val && !$el.is(':focus')) {
|
||||
// $el.focus();
|
||||
// } else if (!val && $el.is(':focus')) {
|
||||
// $el.blur();
|
||||
// }
|
||||
// }, 5);
|
||||
// }
|
||||
// };
|
||||
|
||||
ko.bindingHandlers.aceEditorFocus = {
|
||||
update: function(element, valueAccessor) {
|
||||
var editor = $(element).data('aceEditor')
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
background: rgba(0, 0, 0, 0);
|
||||
z-index: 100;
|
||||
}
|
||||
#inline-editor #inline-editor-table-overlay {
|
||||
@@ -65,11 +65,6 @@
|
||||
}
|
||||
#table-container {
|
||||
position: relative;
|
||||
box-flex: 1;
|
||||
-moz-box-flex: 1;
|
||||
-webkit-box-flex: 1;
|
||||
-ms-box-flex: 1;
|
||||
-o-box-flex: 1;
|
||||
height: 0px;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
right: 0;
|
||||
left: 0;
|
||||
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
background: rgba(0, 0, 0, 0);
|
||||
z-index: 100;
|
||||
|
||||
#inline-editor-table-overlay {
|
||||
@@ -78,7 +78,7 @@
|
||||
|
||||
#table-container {
|
||||
position: relative;
|
||||
.box-flex(1);
|
||||
// .box-flex(1);
|
||||
height: 0px;
|
||||
|
||||
overflow: scroll;
|
||||
|
||||
@@ -580,9 +580,13 @@ Collection.prototype.save = function (ctx, fn) {
|
||||
}
|
||||
if(err) return done(err);
|
||||
|
||||
// copy previous obj
|
||||
Object.keys(obj).forEach(function (key) {
|
||||
prev[key] = obj[key];
|
||||
});
|
||||
|
||||
// merge changes
|
||||
Object.keys(item).forEach(function (key) {
|
||||
prev[key] = obj[key];
|
||||
obj[key] = item[key];
|
||||
});
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ var Server = require('./server')
|
||||
, Monitor = require('./monitor')
|
||||
, commands = {};
|
||||
|
||||
require('longjohn');
|
||||
//require('longjohn');
|
||||
|
||||
/**
|
||||
* Commands exposed to parent process.
|
||||
|
||||
Reference in New Issue
Block a user