better error messages, more robust csv uploading
This commit is contained in:
6
app.js
6
app.js
@@ -115,12 +115,6 @@ ddoc.lists = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ddoc.validate_doc_update = function (newDoc, oldDoc, userCtx) {
|
|
||||||
if (newDoc._deleted === true && userCtx.roles.indexOf('_admin') === -1) {
|
|
||||||
throw "Only admin can delete documents on this database.";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
couchapp.loadAttachments(ddoc, path.join(__dirname, 'attachments'));
|
couchapp.loadAttachments(ddoc, path.join(__dirname, 'attachments'));
|
||||||
|
|
||||||
module.exports = ddoc;
|
module.exports = ddoc;
|
||||||
@@ -6,16 +6,8 @@
|
|||||||
<link rel="stylesheet" href="style/reset.css" media="screen">
|
<link rel="stylesheet" href="style/reset.css" media="screen">
|
||||||
<link rel="stylesheet" href="style/data-table.css" media="screen">
|
<link rel="stylesheet" href="style/data-table.css" media="screen">
|
||||||
<link rel="stylesheet" href="style/style.css" media="screen">
|
<link rel="stylesheet" href="style/style.css" media="screen">
|
||||||
<script type="text/javascript" src="script/lib/jquery-1.6.1.min.js"></script>
|
|
||||||
<!-- only using jqueryui for draggable -- a lighter solution would be nice -->
|
<!-- only using jqueryui for draggable -- a lighter solution would be nice -->
|
||||||
<script type="text/javascript" src="script/lib/jquery-ui-1.8.14.custom.min.js"></script>
|
<script type="text/javascript" src="script/deps-min.js"></script>
|
||||||
<script type="text/javascript" src="script/lib/jquery.mustache.js"></script>
|
|
||||||
<script type="text/javascript" src="script/lib/jquery.couch2.js"></script>
|
|
||||||
<script type="text/javascript" src="script/lib/jquery.hotkeys.js"></script>
|
|
||||||
<script type="text/javascript" src="script/lib/sammy-0.6.3.min.js"></script>
|
|
||||||
<script type="text/javascript" src="script/lib/underscore.js"></script>
|
|
||||||
<script type="text/javascript" src="script/lib/microevent.js"></script>
|
|
||||||
<script type="text/javascript" src="script/lib/traverse.js"></script>
|
|
||||||
<script type="text/javascript" src="script/util.js"></script>
|
<script type="text/javascript" src="script/util.js"></script>
|
||||||
<script type="text/javascript" src="script/costco.js"></script>
|
<script type="text/javascript" src="script/costco.js"></script>
|
||||||
<script type="text/javascript" src="script/recline.js"></script>
|
<script type="text/javascript" src="script/recline.js"></script>
|
||||||
@@ -32,7 +24,10 @@
|
|||||||
<div class="project-actions"></div>
|
<div class="project-actions"></div>
|
||||||
<div class="project-controls"></div>
|
<div class="project-controls"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="main_content"></div>
|
<div class="main_content">
|
||||||
|
<div class="left-panel"></div>
|
||||||
|
<div class="right-panel"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="notification-container">
|
<div id="notification-container">
|
||||||
@@ -94,43 +89,40 @@
|
|||||||
<script type='text/mustache' class="generatingTemplate"><div class="loading">Loading...</div></script>
|
<script type='text/mustache' class="generatingTemplate"><div class="loading">Loading...</div></script>
|
||||||
|
|
||||||
<script type='text/mustache' class="tableContainerTemplate">
|
<script type='text/mustache' class="tableContainerTemplate">
|
||||||
<div id="right-panel">
|
<div id="tool-panel">
|
||||||
<div id="tool-panel">
|
<div id="summary-bar">
|
||||||
<div id="summary-bar">
|
<span id="docCount"></span>
|
||||||
<span id="docCount"></span>
|
</div>
|
||||||
|
<div id="download">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="view-panel">
|
||||||
|
<div class="viewpanel-header">
|
||||||
|
<div class="viewpanel-pagesize">
|
||||||
|
<span>
|
||||||
|
Show:
|
||||||
|
</span>
|
||||||
|
<a href="javascript:{}" class="viewPanel-pagingControls-page action">5</a>
|
||||||
|
<a href="javascript:{}" class="viewPanel-pagingControls-page selected">10</a>
|
||||||
|
<a href="javascript:{}" class="viewPanel-pagingControls-page action">25</a>
|
||||||
|
<a href="javascript:{}" class="viewPanel-pagingControls-page action">50</a>
|
||||||
|
<span>
|
||||||
|
rows
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div id="download">
|
<div class="viewpanel-sorting">
|
||||||
|
</div>
|
||||||
|
<div class="viewpanel-paging">
|
||||||
|
<a href="javascript:{}" class="first inaction">« first</a>
|
||||||
|
<a href="javascript:{}" class="previous inaction">‹ previous</a>
|
||||||
|
<span class="viewpanel-pagingcount">
|
||||||
|
1 - 10
|
||||||
|
</span>
|
||||||
|
<a href="javascript:{}" class="next action">next ›</a>
|
||||||
|
<a href="javascript:{}" class="last action">last »</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="view-panel">
|
<div class="data-table-container">
|
||||||
<div class="viewpanel-header">
|
|
||||||
<div class="viewpanel-pagesize">
|
|
||||||
<span>
|
|
||||||
Show:
|
|
||||||
</span>
|
|
||||||
<a href="javascript:{}" class="viewPanel-pagingControls-page action">5</a>
|
|
||||||
<a href="javascript:{}" class="viewPanel-pagingControls-page selected">10</a>
|
|
||||||
<a href="javascript:{}" class="viewPanel-pagingControls-page action">25</a>
|
|
||||||
<a href="javascript:{}" class="viewPanel-pagingControls-page action">50</a>
|
|
||||||
<span>
|
|
||||||
rows
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="viewpanel-sorting">
|
|
||||||
</div>
|
|
||||||
<div class="viewpanel-paging">
|
|
||||||
<a href="javascript:{}" class="first inaction">« first</a>
|
|
||||||
<a href="javascript:{}" class="previous inaction">‹ previous</a>
|
|
||||||
<span class="viewpanel-pagingcount">
|
|
||||||
1 - 10
|
|
||||||
</span>
|
|
||||||
<a href="javascript:{}" class="next action">next ›</a>
|
|
||||||
<a href="javascript:{}" class="last action">last »</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="data-table-container">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
@@ -304,7 +296,7 @@
|
|||||||
Paste in an array of JSON objects representing the documents that you would like to insert into the database.
|
Paste in an array of JSON objects representing the documents that you would like to insert into the database.
|
||||||
</p>
|
</p>
|
||||||
<p class="info">
|
<p class="info">
|
||||||
<code>[{woo: "pizza"}, {tasty: "muffins"}]</code>
|
<code>[{"woo": "pizza"}, {"tasty": "muffins"}]</code>
|
||||||
</p>
|
</p>
|
||||||
<div class="menu-container data-table-cell-editor">
|
<div class="menu-container data-table-cell-editor">
|
||||||
<textarea class="data-table-cell-copypaste-editor" bind="textarea">{{value}}</textarea>
|
<textarea class="data-table-cell-copypaste-editor" bind="textarea">{{value}}</textarea>
|
||||||
|
|||||||
@@ -47,10 +47,10 @@ onmessage = function(message) {
|
|||||||
var req = new XMLHttpRequest();
|
var req = new XMLHttpRequest();
|
||||||
|
|
||||||
req.onprogress = req.upload.onprogress = function(e) {
|
req.onprogress = req.upload.onprogress = function(e) {
|
||||||
if(e.lengthComputable) postMessage(JSON.stringify({ percent: (e.loaded / e.total) * 100 }));
|
if(e.lengthComputable) postMessage({ percent: (e.loaded / e.total) * 100 });
|
||||||
};
|
};
|
||||||
|
|
||||||
req.onreadystatechange = function() { if (req.readyState == 4) postMessage(JSON.stringify( {done: true} )) };
|
req.onreadystatechange = function() { if (req.readyState == 4) postMessage({done: true, response: req.responseText}) };
|
||||||
req.open('POST', message.data.url);
|
req.open('POST', message.data.url);
|
||||||
req.setRequestHeader('Content-Type', 'application/json');
|
req.setRequestHeader('Content-Type', 'application/json');
|
||||||
req.send(JSON.stringify({docs: docs}));
|
req.send(JSON.stringify({docs: docs}));
|
||||||
|
|||||||
@@ -90,7 +90,14 @@ var costco = function() {
|
|||||||
if(!docs.length) dfd.resolve("Failed: No docs specified");
|
if(!docs.length) dfd.resolve("Failed: No docs specified");
|
||||||
couch.request({url: app.baseURL + "api/_bulk_docs", type: "POST", data: JSON.stringify({docs: docs})})
|
couch.request({url: app.baseURL + "api/_bulk_docs", type: "POST", data: JSON.stringify({docs: docs})})
|
||||||
.then(
|
.then(
|
||||||
function(resp) {ensureCommit().then(function() { dfd.resolve(resp) })},
|
function(resp) {ensureCommit().then(function() {
|
||||||
|
var error = couch.responseError(resp);
|
||||||
|
if (error) {
|
||||||
|
dfd.reject(error);
|
||||||
|
} else {
|
||||||
|
dfd.resolve(resp);
|
||||||
|
}
|
||||||
|
})},
|
||||||
function(err) { dfd.reject(err.responseText) }
|
function(err) { dfd.reject(err.responseText) }
|
||||||
);
|
);
|
||||||
return dfd.promise();
|
return dfd.promise();
|
||||||
@@ -119,25 +126,29 @@ var costco = function() {
|
|||||||
data: event.target.result
|
data: event.target.result
|
||||||
};
|
};
|
||||||
var worker = new Worker('script/costco-csv-worker.js');
|
var worker = new Worker('script/costco-csv-worker.js');
|
||||||
worker.onmessage = function(message) {
|
worker.onmessage = function(event) {
|
||||||
message = JSON.parse(message.data);
|
var message = event.data;
|
||||||
console.log(message)
|
if (message.done) {
|
||||||
|
var error = couch.responseError(JSON.parse(message.response))
|
||||||
if (message.done) {
|
console.log('e',error)
|
||||||
util.hide('dialog');
|
if (error) {
|
||||||
util.notify("Data uploaded successfully!");
|
app.emitter.emit(error, 'error');
|
||||||
recline.initializeTable(app.offset);
|
} else {
|
||||||
} else if (message.percent) {
|
util.notify("Data uploaded successfully!");
|
||||||
if (message.percent === 100) {
|
recline.initializeTable(app.offset);
|
||||||
util.notify("Waiting for CouchDB...", {persist: true, loader: true})
|
}
|
||||||
} else {
|
util.hide('dialog');
|
||||||
util.notify("Uploading... " + message.percent + "%");
|
} else if (message.percent) {
|
||||||
}
|
if (message.percent === 100) {
|
||||||
} else {
|
util.notify("Waiting for CouchDB...", {persist: true, loader: true})
|
||||||
util.notify(JSON.stringify(message));
|
} else {
|
||||||
}
|
util.notify("Uploading... " + message.percent + "%");
|
||||||
};
|
}
|
||||||
worker.postMessage(payload);
|
} else {
|
||||||
|
util.notify(JSON.stringify(message));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
worker.postMessage(payload);
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
util.notify('File not selected. Please try again');
|
util.notify('File not selected. Please try again');
|
||||||
|
|||||||
19
attachments/script/deps-min.js
vendored
Normal file
19
attachments/script/deps-min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -10,9 +10,32 @@
|
|||||||
url: "/"
|
url: "/"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
couch.errors = {
|
||||||
|
forbidden: "You aren't allowed to do that."
|
||||||
|
}
|
||||||
|
|
||||||
|
couch.responseError = function(response) {
|
||||||
|
if(_.isArray(response) && (response.length > 0) ) response = response[0];
|
||||||
|
if (response.error) return couch.errors[response.error];
|
||||||
|
}
|
||||||
|
|
||||||
couch.request = function(opts) {
|
couch.request = function(opts) {
|
||||||
var ajaxOpts = $.extend({}, defaults, opts);
|
var ajaxOpts = $.extend({}, defaults, opts)
|
||||||
return $.ajax(ajaxOpts).promise();
|
, dfd = $.Deferred()
|
||||||
|
;
|
||||||
|
|
||||||
|
$.ajax(ajaxOpts).then(
|
||||||
|
function(successResponse) {
|
||||||
|
var error = couch.responseError(successResponse);
|
||||||
|
if (error) app.emitter.emit(error, 'error');
|
||||||
|
dfd.resolve(successResponse);
|
||||||
|
},
|
||||||
|
function(errorResponse) {
|
||||||
|
app.emitter.emit("Fatal XHR Error", 'error');
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return dfd.promise();
|
||||||
}
|
}
|
||||||
|
|
||||||
couch.get = function(url) {
|
couch.get = function(url) {
|
||||||
|
|||||||
@@ -122,7 +122,12 @@ var recline = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getPageSize() {
|
function getPageSize() {
|
||||||
return parseInt($(".viewpanel-pagesize .selected").text());
|
var pagination = $(".viewpanel-pagesize .selected");
|
||||||
|
if (pagination.length > 0) {
|
||||||
|
return parseInt(pagination.text())
|
||||||
|
} else {
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchRows(id, skip) {
|
function fetchRows(id, skip) {
|
||||||
@@ -158,9 +163,9 @@ var recline = function() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDbInfo() {
|
function getDbInfo(url) {
|
||||||
var dfd = $.Deferred();
|
var dfd = $.Deferred();
|
||||||
return couch.request({url: app.baseURL + "api"}).then(function(dbInfo) {
|
return couch.request({url: url}).then(function(dbInfo) {
|
||||||
app.dbInfo = dbInfo;
|
app.dbInfo = dbInfo;
|
||||||
|
|
||||||
$.extend(app.dbInfo, {
|
$.extend(app.dbInfo, {
|
||||||
@@ -176,18 +181,15 @@ var recline = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function bootstrap() {
|
function bootstrap(id) {
|
||||||
util.registerEmitter();
|
app.dbPath = app.baseURL + "api/";
|
||||||
|
|
||||||
util.listenFor(['esc', 'return']);
|
util.listenFor(['esc', 'return']);
|
||||||
|
|
||||||
getDbInfo().then(function( dbInfo ) {
|
getDbInfo(app.dbPath).then(function( dbInfo ) {
|
||||||
|
util.render('title', 'project-title', dbInfo);
|
||||||
util.render('tableContainer', app.container);
|
|
||||||
util.render('title', 'project-title', app.dbInfo);
|
|
||||||
util.render( 'generating', 'project-actions' );
|
util.render( 'generating', 'project-actions' );
|
||||||
|
|
||||||
updateDocCount(app.dbInfo.doc_count);
|
|
||||||
|
|
||||||
couch.session().then(function(session) {
|
couch.session().then(function(session) {
|
||||||
if ( session.userCtx.name ) {
|
if ( session.userCtx.name ) {
|
||||||
var text = "Sign out";
|
var text = "Sign out";
|
||||||
@@ -202,19 +204,21 @@ var recline = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function initializeTable(offset) {
|
function initializeTable(offset) {
|
||||||
|
util.render( 'tableContainer', 'right-panel' );
|
||||||
showDialog('busy');
|
showDialog('busy');
|
||||||
couch.request({url: app.baseURL + 'api/headers'}).then(function ( headers ) {
|
couch.request({url: app.dbPath + 'headers'}).then(function ( headers ) {
|
||||||
util.hide('dialog');
|
util.hide('dialog');
|
||||||
getDbInfo().then(function(dbInfo) {
|
getDbInfo(app.dbPath).then(function(dbInfo) {
|
||||||
updateDocCount(dbInfo.doc_count);
|
updateDocCount(dbInfo.doc_count);
|
||||||
});
|
});
|
||||||
app.headers = headers;
|
app.headers = headers;
|
||||||
app.csvUrl = app.baseURL + 'api/csv?headers=' + escape(JSON.stringify(headers));
|
app.csvUrl = app.dbPath + 'csv?headers=' + escape(JSON.stringify(headers));
|
||||||
util.render( 'actions', 'project-actions', $.extend({}, app.dbInfo, {url: app.csvUrl}) );
|
util.render( 'actions', 'project-actions', $.extend({}, app.dbInfo, {url: app.csvUrl}) );
|
||||||
fetchRows(false, offset);
|
fetchRows(false, offset);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
formatDiskSize: formatDiskSize,
|
formatDiskSize: formatDiskSize,
|
||||||
handleMenuClick: handleMenuClick,
|
handleMenuClick: handleMenuClick,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
var app = {
|
var app = {
|
||||||
baseURL: util.getBaseURL(document.location.pathname),
|
baseURL: util.getBaseURL(document.location.pathname),
|
||||||
container: 'main_content'
|
container: 'main_content',
|
||||||
|
emitter: util.registerEmitter()
|
||||||
};
|
};
|
||||||
|
|
||||||
app.handler = function(route) {
|
app.handler = function(route) {
|
||||||
@@ -227,7 +228,6 @@ app.after = {
|
|||||||
},
|
},
|
||||||
function (err) {
|
function (err) {
|
||||||
util.hide('dialog');
|
util.hide('dialog');
|
||||||
util.notify("Error uploading: " + err.responseText);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -246,6 +246,10 @@ app.sammy = $.sammy(function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
|
app.emitter.on('error', function(error) {
|
||||||
|
util.notify("Server error: " + error);
|
||||||
|
})
|
||||||
|
|
||||||
util.traverse = require('traverse');
|
util.traverse = require('traverse');
|
||||||
app.sammy.run();
|
app.sammy.run();
|
||||||
})
|
})
|
||||||
@@ -32,7 +32,7 @@ var util = function() {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
MicroEvent.mixin(Emitter);
|
MicroEvent.mixin(Emitter);
|
||||||
app.emitter = new Emitter();
|
return new Emitter();
|
||||||
}
|
}
|
||||||
|
|
||||||
function listenFor(keys) {
|
function listenFor(keys) {
|
||||||
|
|||||||
@@ -450,7 +450,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#left-panel {
|
.left-panel {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
@@ -459,14 +459,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
background: #e3e9ff;
|
background: #e3e9ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
#left-panel .ui-tabs .ui-tabs-panel {
|
.left-panel .ui-tabs .ui-tabs-panel {
|
||||||
border-left: none;
|
border-left: none;
|
||||||
border-right: none;
|
border-right: none;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#right-panel {
|
.right-panel {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 40px;
|
top: 40px;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
|
|||||||
Reference in New Issue
Block a user