Merge branch 'master' into gh-pages
This commit is contained in:
@@ -17,20 +17,24 @@
|
|||||||
</head>
|
</head>
|
||||||
<body class="bod">
|
<body class="bod">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<form class="webstore-load">
|
<div class="menu-overlay" style="display: none; z-index: 101; "> </div>
|
||||||
<label for="source">Source</label>
|
|
||||||
<input type="text" name="source" size="50" />
|
|
||||||
<input type="submit" name="" value="Update" />
|
|
||||||
</form>
|
|
||||||
<!-- <div class="menu-overlay" style="display: none; z-index: 101; "> </div>
|
|
||||||
<ul class="menu">
|
<ul class="menu">
|
||||||
</ul>
|
</ul>
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<a href="http://github.com/maxogden/recline"><img id="couchLogo" src="images/couch.png"/></a>
|
<div class="project-title">
|
||||||
<div class="project-title"></div>
|
<a href="http://github.com/okfn/recline">Recline DataExplorer</a>
|
||||||
<div class="project-actions"></div>
|
/ Demo
|
||||||
|
</div>
|
||||||
|
<div class="project-actions">
|
||||||
|
<form class="webstore-load">
|
||||||
|
<label for="source">Source</label>
|
||||||
|
<input type="text" name="source" size="50" />
|
||||||
|
<input type="submit" name="" value="Update" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
<div class="project-controls"></div>
|
<div class="project-controls"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<!--
|
||||||
<div class="main_content">
|
<div class="main_content">
|
||||||
<div class="left-panel"></div>
|
<div class="left-panel"></div>
|
||||||
<div class="right-panel"></div>
|
<div class="right-panel"></div>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
$(function() {
|
$(function() {
|
||||||
// do not like all these window globals ...
|
// do not like all these window globals ...
|
||||||
|
// window.$container = $('.container .right-panel');
|
||||||
window.$container = $('.container');
|
window.$container = $('.container');
|
||||||
var dataset = demoDataset();
|
var dataset = demoDataset();
|
||||||
window.dataExplorer = new recline.DataExplorer({
|
window.dataExplorer = new recline.DataExplorer({
|
||||||
|
|||||||
@@ -63,7 +63,6 @@ table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
input, select {
|
input, select {
|
||||||
vertical-align: middle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@@ -428,7 +427,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
}
|
}
|
||||||
|
|
||||||
.project-controls, .project-actions {
|
.project-controls, .project-actions {
|
||||||
margin: 3px 2px 0px 0px;
|
margin: 0px 2px 0px 0px;
|
||||||
display: block;
|
display: block;
|
||||||
float: right;
|
float: right;
|
||||||
font-size: 1.3em;
|
font-size: 1.3em;
|
||||||
@@ -573,19 +572,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-container {
|
|
||||||
display: block;
|
|
||||||
border-top: 1px solid #BCF;
|
|
||||||
overflow: auto;
|
|
||||||
position: absolute;
|
|
||||||
top: 73px;
|
|
||||||
bottom: 0px;
|
|
||||||
left: 5px;
|
|
||||||
right: 0px;
|
|
||||||
background: white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.data-table {
|
.data-table {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -1195,4 +1181,4 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
background: -webkit-gradient(linear, left top, left bottom, from(#e3e3e3), to(#f9f9f9));
|
background: -webkit-gradient(linear, left top, left bottom, from(#e3e3e3), to(#f9f9f9));
|
||||||
background: -moz-linear-gradient(top, #e3e3e3, #f9f9f9);
|
background: -moz-linear-gradient(top, #e3e3e3, #f9f9f9);
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e3e3e3', endColorstr='#f9f9f9');
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e3e3e3', endColorstr='#f9f9f9');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
.data-graph-container .graph {
|
.data-graph-container .graph {
|
||||||
width: 650px;
|
position: absolute;
|
||||||
height: 400px;
|
left: 0;
|
||||||
float: left;
|
right: 220px;
|
||||||
|
bottom: 0;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-graph-container .editor {
|
.data-graph-container .editor {
|
||||||
z-index: 1;
|
|
||||||
background-color: #efefef;
|
background-color: #efefef;
|
||||||
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
left: auto;
|
left: auto;
|
||||||
width: 198px;
|
width: 198px;
|
||||||
|
|||||||
@@ -209,4 +209,33 @@ span.tooltip-status {
|
|||||||
font-weight:bold;
|
font-weight:bold;
|
||||||
color:red;
|
color:red;
|
||||||
text-align:center;
|
text-align:center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* rgrp added mods */
|
||||||
|
|
||||||
|
.data-explorer .nav {
|
||||||
|
border-top: 15px solid #BCF;
|
||||||
|
border-left: 5px solid #BCF;
|
||||||
|
display: block;
|
||||||
|
overflow: auto;
|
||||||
|
position: absolute;
|
||||||
|
top: 35px;
|
||||||
|
bottom: 0px;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
background: white;
|
||||||
|
padding-top: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-view-container {
|
||||||
|
display: block;
|
||||||
|
border-top: 1px solid #BCF;
|
||||||
|
border-left: 5px solid #BCF;
|
||||||
|
overflow: auto;
|
||||||
|
position: absolute;
|
||||||
|
top: 83px;
|
||||||
|
bottom: 0px;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|||||||
17
src/util.js
17
src/util.js
@@ -53,10 +53,11 @@ var util = function() {
|
|||||||
|
|
||||||
function observeExit(elem, callback) {
|
function observeExit(elem, callback) {
|
||||||
var cancelButton = elem.find('.cancelButton');
|
var cancelButton = elem.find('.cancelButton');
|
||||||
app.emitter.on('esc', function() {
|
// TODO: remove (commented out as part of Backbon-i-fication
|
||||||
cancelButton.click();
|
// app.emitter.on('esc', function() {
|
||||||
app.emitter.clear('esc');
|
// cancelButton.click();
|
||||||
});
|
// app.emitter.clear('esc');
|
||||||
|
// });
|
||||||
cancelButton.click(callback);
|
cancelButton.click(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +69,8 @@ var util = function() {
|
|||||||
function hide( thing ) {
|
function hide( thing ) {
|
||||||
$('.' + thing ).hide();
|
$('.' + thing ).hide();
|
||||||
$('.' + thing + '-overlay').hide();
|
$('.' + thing + '-overlay').hide();
|
||||||
if (thing === "dialog") app.emitter.clear('esc'); // todo more elegant solution
|
// TODO: remove or replace (commented out as part of Backbon-i-fication
|
||||||
|
// if (thing === "dialog") app.emitter.clear('esc'); // todo more elegant solution
|
||||||
}
|
}
|
||||||
|
|
||||||
function position( thing, elem, offset ) {
|
function position( thing, elem, offset ) {
|
||||||
@@ -98,7 +100,8 @@ var util = function() {
|
|||||||
} else {
|
} else {
|
||||||
targetDom.html( html );
|
targetDom.html( html );
|
||||||
}
|
}
|
||||||
if (template in app.after) app.after[template]();
|
// TODO: remove (commented out as part of Backbon-i-fication
|
||||||
|
// if (template in app.after) app.after[template]();
|
||||||
}
|
}
|
||||||
|
|
||||||
function notify( message, options ) {
|
function notify( message, options ) {
|
||||||
@@ -377,4 +380,4 @@ var util = function() {
|
|||||||
selectedTreePath: selectedTreePath,
|
selectedTreePath: selectedTreePath,
|
||||||
renderTree: renderTree
|
renderTree: renderTree
|
||||||
};
|
};
|
||||||
}();
|
}();
|
||||||
|
|||||||
141
src/view.js
141
src/view.js
@@ -12,6 +12,7 @@ recline.DataExplorer = Backbone.View.extend({
|
|||||||
<label for="nav-graph">Graph</label> \
|
<label for="nav-graph">Graph</label> \
|
||||||
</span> \
|
</span> \
|
||||||
</div> \
|
</div> \
|
||||||
|
<div class="data-view-container"></div> \
|
||||||
',
|
',
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
@@ -21,6 +22,7 @@ recline.DataExplorer = Backbone.View.extend({
|
|||||||
initialize: function() {
|
initialize: function() {
|
||||||
this.el = $(this.el);
|
this.el = $(this.el);
|
||||||
this.render();
|
this.render();
|
||||||
|
this.$dataViewContainer = this.el.find('.data-view-container');
|
||||||
var self = this;
|
var self = this;
|
||||||
// retrieve basic data like headers etc
|
// retrieve basic data like headers etc
|
||||||
// note this.model and dataset returned are the same
|
// note this.model and dataset returned are the same
|
||||||
@@ -33,8 +35,8 @@ recline.DataExplorer = Backbone.View.extend({
|
|||||||
model: dataset
|
model: dataset
|
||||||
});
|
});
|
||||||
self.flotGraph.el.hide();
|
self.flotGraph.el.hide();
|
||||||
self.el.append(self.dataTable.el)
|
self.$dataViewContainer.append(self.dataTable.el)
|
||||||
self.el.append(self.flotGraph.el);
|
self.$dataViewContainer.append(self.flotGraph.el);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -61,23 +63,140 @@ recline.DataExplorer = Backbone.View.extend({
|
|||||||
});
|
});
|
||||||
|
|
||||||
recline.DataTable = Backbone.View.extend({
|
recline.DataTable = Backbone.View.extend({
|
||||||
|
|
||||||
tagName: "div",
|
tagName: "div",
|
||||||
className: "data-table-container",
|
className: "data-table-container",
|
||||||
|
|
||||||
// template: TODO ???
|
|
||||||
|
|
||||||
events: {
|
|
||||||
},
|
|
||||||
|
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
this.el = $(this.el);
|
this.el = $(this.el);
|
||||||
var that = this;
|
var self = this;
|
||||||
this.model.getRows().then(function(rows) {
|
this.model.getRows().then(function(rows) {
|
||||||
that._currentRows = rows;
|
self._currentRows = rows;
|
||||||
that.render()
|
self.render()
|
||||||
|
});
|
||||||
|
this.state = {};
|
||||||
|
// this is nasty. Due to fact that .menu element is not inside this view but is elsewhere in DOM
|
||||||
|
$('.menu li a').live('click', function(e) {
|
||||||
|
// self.onMenuClick(e).apply(self);
|
||||||
|
self.onMenuClick(e);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
// see initialize
|
||||||
|
// 'click .menu li': 'onMenuClick',
|
||||||
|
'click .column-header-menu': 'onColumnHeaderClick',
|
||||||
|
'click .row-header-menu': 'onRowHeaderClick',
|
||||||
|
'click .data-table-cell-edit': 'onEditClick',
|
||||||
|
// cell editor
|
||||||
|
'click .data-table-cell-editor .okButton': 'onEditorOK',
|
||||||
|
'click .data-table-cell-editor .cancelButton': 'onEditorCancel'
|
||||||
|
},
|
||||||
|
|
||||||
|
showDialog: function(template, data) {
|
||||||
|
if (!data) data = {};
|
||||||
|
util.show('dialog');
|
||||||
|
util.render(template, 'dialog-content', data);
|
||||||
|
util.observeExit($('.dialog-content'), function() {
|
||||||
|
util.hide('dialog');
|
||||||
|
})
|
||||||
|
$('.dialog').draggable({ handle: '.dialog-header', cursor: 'move' });
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// ======================================================
|
||||||
|
// Column and row menus
|
||||||
|
|
||||||
|
onColumnHeaderClick: function(e) {
|
||||||
|
this.state.currentColumn = $(e.target).siblings().text();
|
||||||
|
util.position('menu', e);
|
||||||
|
util.render('columnActions', 'menu');
|
||||||
|
},
|
||||||
|
|
||||||
|
onRowHeaderClick: function(e) {
|
||||||
|
this.state.currentRow = $(e.target).parents('tr:first').attr('data-id');
|
||||||
|
util.position('menu', e);
|
||||||
|
util.render('rowActions', 'menu');
|
||||||
|
},
|
||||||
|
|
||||||
|
onMenuClick: function(e) {
|
||||||
|
var self = this;
|
||||||
|
e.preventDefault();
|
||||||
|
var actions = {
|
||||||
|
bulkEdit: function() { self.showDialog('bulkEdit', {name: self.state.currentColumn}) },
|
||||||
|
transform: function() { showDialog('transform') },
|
||||||
|
csv: function() { window.location.href = app.csvUrl },
|
||||||
|
json: function() { window.location.href = "_rewrite/api/json" },
|
||||||
|
urlImport: function() { showDialog('urlImport') },
|
||||||
|
pasteImport: function() { showDialog('pasteImport') },
|
||||||
|
uploadImport: function() { showDialog('uploadImport') },
|
||||||
|
deleteColumn: function() {
|
||||||
|
var msg = "Are you sure? This will delete '" + self.state.currentColumn + "' from all documents.";
|
||||||
|
// TODO:
|
||||||
|
alert('This function needs to be re-implemented');
|
||||||
|
return;
|
||||||
|
if (confirm(msg)) costco.deleteColumn(self.state.currentColumn);
|
||||||
|
},
|
||||||
|
deleteRow: function() {
|
||||||
|
// TODO:
|
||||||
|
alert('This function needs to be re-implemented');
|
||||||
|
return;
|
||||||
|
var doc = _.find(app.cache, function(doc) { return doc._id === app.currentRow });
|
||||||
|
doc._deleted = true;
|
||||||
|
costco.uploadDocs([doc]).then(
|
||||||
|
function(updatedDocs) {
|
||||||
|
util.notify("Row deleted successfully");
|
||||||
|
recline.initializeTable(app.offset);
|
||||||
|
},
|
||||||
|
function(err) { util.notify("Errorz! " + err) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
util.hide('menu');
|
||||||
|
actions[$(e.target).attr('data-action')]();
|
||||||
|
},
|
||||||
|
|
||||||
|
// ======================================================
|
||||||
|
// Cell Editor
|
||||||
|
|
||||||
|
onEditClick: function(e) {
|
||||||
|
var editing = this.el.find('.data-table-cell-editor-editor');
|
||||||
|
if (editing.length > 0) {
|
||||||
|
editing.parents('.data-table-cell-value').html(editing.text()).siblings('.data-table-cell-edit').removeClass("hidden");
|
||||||
|
}
|
||||||
|
$(e.target).addClass("hidden");
|
||||||
|
var cell = $(e.target).siblings('.data-table-cell-value');
|
||||||
|
cell.data("previousContents", cell.text());
|
||||||
|
util.render('cellEditor', cell, {value: cell.text()});
|
||||||
|
},
|
||||||
|
|
||||||
|
onEditorOK: function(e) {
|
||||||
|
var cell = $(e.target);
|
||||||
|
var rowId = cell.parents('tr').attr('data-id');
|
||||||
|
var header = cell.parents('td').attr('data-header');
|
||||||
|
var newValue = cell.parents('.data-table-cell-editor').find('.data-table-cell-editor-editor)').val();
|
||||||
|
// TODO:
|
||||||
|
alert('Update: ' + header + ' with value ' + newValue + '(But no save as not yet operational');
|
||||||
|
return;
|
||||||
|
var doc = _.find(app.cache, function(cacheDoc) {
|
||||||
|
return cacheDoc._id === rowId;
|
||||||
|
});
|
||||||
|
doc[header] = newValue;
|
||||||
|
util.notify("Updating row...", {persist: true, loader: true});
|
||||||
|
costco.updateDoc(doc).then(function(response) {
|
||||||
|
util.notify("Row updated successfully");
|
||||||
|
recline.initializeTable();
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
onEditorCancel: function(e) {
|
||||||
|
var cell = $(e.target).parents('.data-table-cell-value');
|
||||||
|
cell.html(cell.data('previousContents')).siblings('.data-table-cell-edit').removeClass("hidden");
|
||||||
|
},
|
||||||
|
|
||||||
|
// ======================================================
|
||||||
|
// Core Templating
|
||||||
|
|
||||||
toTemplateJSON: function() {
|
toTemplateJSON: function() {
|
||||||
var modelData = this.model.toJSON()
|
var modelData = this.model.toJSON()
|
||||||
modelData.rows = _.map(this._currentRows, function(row) {
|
modelData.rows = _.map(this._currentRows, function(row) {
|
||||||
|
|||||||
Reference in New Issue
Block a user