[ckan-changes] [okfn/ckan] 9de1a3: [2285] Allow the height to be smaller if possible
GitHub
noreply at github.com
Wed Apr 25 13:29:43 UTC 2012
Branch: refs/heads/feature-2285-embeddable-data-viewer
Home: https://github.com/okfn/ckan
Commit: 9de1a32e35e877aef8d1f8b4c6f7422c2a8fd9e9
https://github.com/okfn/ckan/commit/9de1a32e35e877aef8d1f8b4c6f7422c2a8fd9e9
Author: Ian Murray <ian.murray at okfn.org>
Date: 2012-04-24 (Tue, 24 Apr 2012)
Changed paths:
M ckan/templates/package/resource_embedded_dataviewer.html
Log Message:
-----------
[2285] Allow the height to be smaller if possible
diff --git a/ckan/templates/package/resource_embedded_dataviewer.html b/ckan/templates/package/resource_embedded_dataviewer.html
index 7504862..c862b05 100644
--- a/ckan/templates/package/resource_embedded_dataviewer.html
+++ b/ckan/templates/package/resource_embedded_dataviewer.html
@@ -43,19 +43,23 @@
#ckanext-datapreview {
width: ${c.width}px;
- height: ${c.height}px;
+ height: auto;
+ max-height: ${c.height}px;
}
.recline-grid-container {
- height: ${c.height}px;
+ height: auto;
+ max-height: ${c.height}px;
}
.recline-graph .graph {
- height: ${c.height}px;
+ height: auto;
+ max-height: ${c.height}px;
}
.recline-map .map {
- height: ${c.height}px;
+ height: auto;
+ max-height: ${c.height}px;
}
</style>
================================================================
Commit: a0982bcb1652bcf8afdb2f74a9d517a5c5aa2e1c
https://github.com/okfn/ckan/commit/a0982bcb1652bcf8afdb2f74a9d517a5c5aa2e1c
Author: Ian Murray <ian.murray at okfn.org>
Date: 2012-04-24 (Tue, 24 Apr 2012)
Changed paths:
M ckan/model/package.py
M ckan/templates/package/resource_read.html
Log Message:
-----------
[2285] Disable the Embed button if the resource is private
diff --git a/ckan/model/package.py b/ckan/model/package.py
index 4365963..bf5c70d 100644
--- a/ckan/model/package.py
+++ b/ckan/model/package.py
@@ -561,6 +561,13 @@ def metadata_modified(self):
timestamp_float = timegm(timestamp_without_usecs) + usecs
return datetime.datetime.utcfromtimestamp(timestamp_float)
+ @property
+ def is_private(self):
+ """
+ A package is private if belongs to any private groups
+ """
+ return bool(self.get_groups(capacity='private'))
+
def is_in_group(self, group):
return group in self.get_groups()
diff --git a/ckan/templates/package/resource_read.html b/ckan/templates/package/resource_read.html
index f9cbf4d..7508abb 100644
--- a/ckan/templates/package/resource_read.html
+++ b/ckan/templates/package/resource_read.html
@@ -170,7 +170,8 @@
<div class="resource-preview">
<div class="preview-header">
<h3>Preview</h3>
- <a style="display: none;" class="btn btn-primary" data-toggle="modal" href=".modal-data-viewer-embed-dialog">Embed</a>
+ <a py:if="c.pkg.is_private" title="Cannot embed as resource is private." style="display: none;" class="btn disabled" data-toggle="modal" href=".modal-data-viewer-embed-dialog">Embed</a>
+ <a py:if="not c.pkg.is_private" style="display: none;" class="btn btn-primary" data-toggle="modal" href=".modal-data-viewer-embed-dialog">Embed</a>
</div>
<div id="ckanext-datapreview"></div>
</div>
================================================================
Commit: 7211ddede488b8daafcc9e74230701611ae4182e
https://github.com/okfn/ckan/commit/7211ddede488b8daafcc9e74230701611ae4182e
Author: Ian Murray <ian.murray at okfn.org>
Date: 2012-04-24 (Tue, 24 Apr 2012)
Changed paths:
M ckan/controllers/package.py
M ckan/public/scripts/application.js
Log Message:
-----------
[2285] Some tidying up
diff --git a/ckan/controllers/package.py b/ckan/controllers/package.py
index ea23594..79db466 100644
--- a/ckan/controllers/package.py
+++ b/ckan/controllers/package.py
@@ -742,21 +742,13 @@ def resource_embedded_dataviewer(self, id, resource_id):
'user': c.user or c.author}
try:
- resource = get_action('resource_show')(context, {'id': resource_id})
- package = get_action('package_show')(context, {'id': id})
-
- # These are just required whilst still basing this off the resource_read
c.resource = get_action('resource_show')(context, {'id': resource_id})
c.package = get_action('package_show')(context, {'id': id})
- c.pkg = context['package']
c.resource_json = json.dumps(c.resource)
- c.pkg_dict = c.package
# double check that the resource belongs to the specified package
- if not resource['id'] in [ r['id'] for r in package['resources'] ]:
+ if not c.resource['id'] in [ r['id'] for r in c.package['resources'] ]:
raise NotFound
-
- c.resource_json = json.dumps(resource)
except NotFound:
abort(404, _('Resource not found'))
@@ -769,7 +761,7 @@ def resource_embedded_dataviewer(self, id, resource_id):
recline_state = self._parse_recline_state(state_version, raw_state)
if recline_state is None:
abort(400, ('"state" parameter must be a valid recline state (version %d)' % state_version))
-
+
c.recline_state = json.dumps(recline_state)
c.width = max(int(request.params.get('width', 500)), 100)
diff --git a/ckan/public/scripts/application.js b/ckan/public/scripts/application.js
index 97af2f3..5774652 100644
--- a/ckan/public/scripts/application.js
+++ b/ckan/public/scripts/application.js
@@ -47,7 +47,7 @@ CKAN.Utils = CKAN.Utils || {};
var isEmbededDataviewer = $('body.package.resource_embedded_dataviewer').length > 0;
if (isEmbededDataviewer) {
- CKAN.DataPreview.loadPreviewDialogWithState(preload_resource, reclineState);
+ CKAN.DataPreview.loadEmbeddedPreview(preload_resource, reclineState);
}
var isDatasetNew = $('body.package.new').length > 0;
@@ -1256,14 +1256,19 @@ CKAN.DataPreview = function ($, my) {
my.dialogId = 'ckanext-datapreview';
my.$dialog = $('#' + my.dialogId);
- // **Public: Loads a data preview, taking into account an initial state**
+ // **Public: Loads a data previewer for an embedded page**
//
- my.loadPreviewDialogWithState = function(resourceData, reclineState) {
+ // Uses the provided reclineState to restore the Dataset. Creates a single
+ // view for the Dataset (the one defined by reclineState.currentView). And
+ // then passes the constructed Dataset, the constructed View, and the
+ // reclineState into the DataExplorer constructor.
+ my.loadEmbeddedPreview = function(resourceData, reclineState) {
my.$dialog.html('<h4>Loading ... <img src="http://assets.okfn.org/images/icons/ajaxload-circle.gif" class="loading-spinner" /></h4>');
+ // Restore the Dataset from the given reclineState.
var dataset = recline.Model.Dataset.restore(reclineState);
- // Only load a single view
+ // Only create the view defined in reclineState.currentView.
// TODO: tidy this up.
var views = null;
if (reclineState.currentView === 'grid') {
@@ -1295,6 +1300,7 @@ CKAN.DataPreview = function ($, my) {
}];
}
+ // Finally, construct the DataExplorer. Again, passing in the reclineState.
var dataExplorer = new recline.View.DataExplorer({
el: my.$dialog,
model: dataset,
@@ -1305,6 +1311,10 @@ CKAN.DataPreview = function ($, my) {
Backbone.history.start();
};
+ // **Public: Creates a link to the embeddable page.
+ //
+ // For a given DataExplorer state, this function constructs and returns the
+ // url to the embeddable view of the current dataexplorer state.
my.makeEmbedLink = function(explorerState) {
var qs = recline.View.composeQueryString({
state: explorerState.toJSON(),
@@ -1358,17 +1368,32 @@ CKAN.DataPreview = function ($, my) {
}
});
+ // -----------------------------
+ // Setup the Embed modal dialog.
+ // -----------------------------
+
+ // embedLink holds the url to the embeddable view of the current DataExplorer state.
var embedLink = $('.embedLink');
+
+ // embedIframeText contains the '<iframe>' construction, which sources
+ // the above link.
var embedIframeText = $('.embedIframeText');
+ // iframeWidth and iframeHeight control the width and height parameters
+ // used to construct the iframe, and are also used in the link.
var iframeWidth = $('.iframe-width');
var iframeHeight = $('.iframe-height');
+ // Update the embedLink and embedIframeText to contain the updated link
+ // and update width and height parameters.
function updateLink() {
var link = my.makeEmbedLink(dataExplorer.state);
var width = iframeWidth.val();
var height = iframeHeight.val();
link += '&width='+width+'&height='+height;
+
+ // Escape '"' characters in {{link}} in order not to prematurely close
+ // the src attribute value.
embedIframeText.val($.mustache('<iframe width="{{width}}" height="{{height}}" src="{{link}}"></iframe>',
{
link: link.replace(/"/g, '"'),
@@ -1378,11 +1403,16 @@ CKAN.DataPreview = function ($, my) {
embedLink.attr('href', link);
}
+ // Bind changes to the DataExplorer, or the two width and height inputs
+ // to re-calculate the url.
dataExplorer.state.bind('change', updateLink);
iframeWidth.change(updateLink);
iframeHeight.change(updateLink);
+
+ // Initial population of embedLink and embedIframeText
updateLink();
+ // Finally, since we have a DataExplorer, we can show the embed button.
$('.preview-header .btn').show();
// will have to refactor if this can get called multiple times
================================================================
Commit: 3606add796f1873f4fb6e61361056d5150a377cb
https://github.com/okfn/ckan/commit/3606add796f1873f4fb6e61361056d5150a377cb
Author: Ian Murray <ian.murray at okfn.org>
Date: 2012-04-25 (Wed, 25 Apr 2012)
Changed paths:
M ckan/templates/_snippet/data-viewer-embed-branded-link.html
M ckan/templates/package/resource_embedded_dataviewer.html
Log Message:
-----------
[2285] Fixed mistakes with iframe height.
diff --git a/ckan/templates/_snippet/data-viewer-embed-branded-link.html b/ckan/templates/_snippet/data-viewer-embed-branded-link.html
index 68d3453..87eceb6 100644
--- a/ckan/templates/_snippet/data-viewer-embed-branded-link.html
+++ b/ckan/templates/_snippet/data-viewer-embed-branded-link.html
@@ -6,12 +6,14 @@
py:strip=""
>
-<p>Powered by <a href="${h.url_for(controller='package', action='resource_read', id=c.package.id, resource_id=c.resource.id)}">
-
-${g.site_title}
-<img width="64" src="${h.url_for_static(g.site_logo)}" alt="${g.site_title} Logo" title="${g.site_title} Logo" id="logo" />
-</a>
-</p>
+<div class="branded-link">
+ <p>Powered by <a href="${h.url_for(controller='package', action='resource_read', id=c.package.id, resource_id=c.resource.id)}">
+
+ ${g.site_title}
+ <img width="64" src="${h.url_for_static(g.site_logo)}" alt="${g.site_title} Logo" title="${g.site_title} Logo" id="logo" />
+ </a>
+ </p>
+</div>
</html>
diff --git a/ckan/templates/package/resource_embedded_dataviewer.html b/ckan/templates/package/resource_embedded_dataviewer.html
index c862b05..c03f4b9 100644
--- a/ckan/templates/package/resource_embedded_dataviewer.html
+++ b/ckan/templates/package/resource_embedded_dataviewer.html
@@ -42,24 +42,28 @@
}
#ckanext-datapreview {
- width: ${c.width}px;
- height: auto;
- max-height: ${c.height}px;
+ width: ${c.width-2}px;
+ height: ${c.height-115}px;
}
.recline-grid-container {
- height: auto;
- max-height: ${c.height}px;
+ height: ${c.height-115}px;
}
.recline-graph .graph {
- height: auto;
- max-height: ${c.height}px;
+ height: ${c.height-115}px;
}
.recline-map .map {
- height: auto;
- max-height: ${c.height}px;
+ height: ${c.height-115}px;
+ }
+
+ .branded-link {
+ height: 70px;
+ }
+
+ .alert-messages {
+ display: none;
}
</style>
================================================================
Commit: 98b3e240e470563ff59e1ec8717f48a56c48f4ef
https://github.com/okfn/ckan/commit/98b3e240e470563ff59e1ec8717f48a56c48f4ef
Author: Ian Murray <ian.murray at okfn.org>
Date: 2012-04-25 (Wed, 25 Apr 2012)
Changed paths:
M ckan/public/scripts/application.js
Log Message:
-----------
[2285] Escape the dataset url.
Strictly, everything should be escaped, but in order to have legible looking urls, it's enough
to just escape the dataset url, at least for now.
diff --git a/ckan/public/scripts/application.js b/ckan/public/scripts/application.js
index 5774652..462e774 100644
--- a/ckan/public/scripts/application.js
+++ b/ckan/public/scripts/application.js
@@ -1316,6 +1316,8 @@ CKAN.DataPreview = function ($, my) {
// For a given DataExplorer state, this function constructs and returns the
// url to the embeddable view of the current dataexplorer state.
my.makeEmbedLink = function(explorerState) {
+ var state = explorerState.toJSON();
+ state.dataset.url = escape(state.dataset.url);
var qs = recline.View.composeQueryString({
state: explorerState.toJSON(),
state_version: 1
================================================================
Commit: 8c267d296cfa09ff1e6f7572167021bff3f6a0c5
https://github.com/okfn/ckan/commit/8c267d296cfa09ff1e6f7572167021bff3f6a0c5
Author: Ian Murray <ian.murray at okfn.org>
Date: 2012-04-25 (Wed, 25 Apr 2012)
Changed paths:
M ckan/public/scripts/application.js
Log Message:
-----------
[2285] Bind to changes on the data explorer's views
diff --git a/ckan/public/scripts/application.js b/ckan/public/scripts/application.js
index 462e774..d78c3a9 100644
--- a/ckan/public/scripts/application.js
+++ b/ckan/public/scripts/application.js
@@ -1408,6 +1408,10 @@ CKAN.DataPreview = function ($, my) {
// Bind changes to the DataExplorer, or the two width and height inputs
// to re-calculate the url.
dataExplorer.state.bind('change', updateLink);
+ for (var i=0; i<dataExplorer.pageViews.length; i++) {
+ dataExplorer.pageViews[i].view.state.bind('change', updateLink);
+ }
+
iframeWidth.change(updateLink);
iframeHeight.change(updateLink);
================================================================
Commit: 0fc677d3c7af770d4caa93572681bc7455233e00
https://github.com/okfn/ckan/commit/0fc677d3c7af770d4caa93572681bc7455233e00
Author: Ian Murray <ian.murray at okfn.org>
Date: 2012-04-25 (Wed, 25 Apr 2012)
Changed paths:
M ckan/public/scripts/vendor/recline/recline.js
Log Message:
-----------
[2285] Pulled in latest changes in recline
diff --git a/ckan/public/scripts/vendor/recline/recline.js b/ckan/public/scripts/vendor/recline/recline.js
index 391296a..c1f9185 100644
--- a/ckan/public/scripts/vendor/recline/recline.js
+++ b/ckan/public/scripts/vendor/recline/recline.js
@@ -1404,7 +1404,7 @@ this.recline.View = this.recline.View || {};
//
// <pre>
// {
-// // geomField if specified will be used in preference to lat/lon
+// // geomField if specified will be used in preference to lat/lon
// geomField: {id of field containing geometry in the dataset}
// lonField: {id of field containing longitude in the dataset}
// latField: {id of field containing latitude in the dataset}
@@ -1462,6 +1462,11 @@ my.Map = Backbone.View.extend({
<div class="editor-buttons"> \
<button class="btn editor-update-map">Update</button> \
</div> \
+ <div class="editor-options" > \
+ <label class="checkbox"> \
+ <input type="checkbox" id="editor-auto-zoom" checked="checked" /> \
+ Auto zoom to features</label> \
+ </div> \
<input type="hidden" class="editor-id" value="map-1" /> \
</div> \
</form> \
@@ -1479,7 +1484,8 @@ my.Map = Backbone.View.extend({
// Define here events for UI elements
events: {
'click .editor-update-map': 'onEditorSubmit',
- 'change .editor-field-type': 'onFieldTypeChange'
+ 'change .editor-field-type': 'onFieldTypeChange',
+ 'change #editor-auto-zoom': 'onAutoZoomChange'
},
initialize: function(options) {
@@ -1498,15 +1504,27 @@ my.Map = Backbone.View.extend({
// Listen to changes in the documents
this.model.currentDocuments.bind('add', function(doc){self.redraw('add',doc)});
+ this.model.currentDocuments.bind('change', function(doc){
+ self.redraw('remove',doc);
+ self.redraw('add',doc);
+ });
this.model.currentDocuments.bind('remove', function(doc){self.redraw('remove',doc)});
this.model.currentDocuments.bind('reset', function(){self.redraw('reset')});
- // If the div was hidden, Leaflet needs to recalculate some sizes
- // to display properly
this.bind('view:show',function(){
- if (self.map) {
- self.map.invalidateSize();
+ // If the div was hidden, Leaflet needs to recalculate some sizes
+ // to display properly
+ if (self.map){
+ self.map.invalidateSize();
+ if (self._zoomPending && self.autoZoom) {
+ self._zoomToFeatures();
+ self._zoomPending = false;
}
+ }
+ self.visible = true;
+ });
+ this.bind('view:hide',function(){
+ self.visible = false;
});
var stateData = _.extend({
@@ -1518,6 +1536,7 @@ my.Map = Backbone.View.extend({
);
this.state = new recline.Model.ObjectState(stateData);
+ this.autoZoom = true;
this.mapReady = false;
this.render();
},
@@ -1583,6 +1602,13 @@ my.Map = Backbone.View.extend({
this.features.clearLayers();
this._add(this.model.currentDocuments.models);
}
+ if (action != 'reset' && this.autoZoom){
+ if (this.visible){
+ this._zoomToFeatures();
+ } else {
+ this._zoomPending = true;
+ }
+ }
}
},
@@ -1629,6 +1655,10 @@ my.Map = Backbone.View.extend({
}
},
+ onAutoZoomChange: function(e){
+ this.autoZoom = !this.autoZoom;
+ },
+
// Private: Add one or n features to the map
//
// For each document passed, a GeoJSON geometry will be extracted and added
@@ -1656,7 +1686,9 @@ my.Map = Backbone.View.extend({
// TODO: mustache?
html = ''
for (key in doc.attributes){
- html += '<div><strong>' + key + '</strong>: '+ doc.attributes[key] + '</div>'
+ if (!(self.state.get('geomField') && key == self.state.get('geomField'))){
+ html += '<div><strong>' + key + '</strong>: '+ doc.attributes[key] + '</div>';
+ }
}
feature.properties = {popupContent: html};
@@ -1707,19 +1739,22 @@ my.Map = Backbone.View.extend({
_getGeometryFromDocument: function(doc){
if (this.geomReady){
if (this.state.get('geomField')){
- // We assume that the contents of the field are a valid GeoJSON object
- return doc.attributes[this.state.get('geomField')];
+ var value = doc.get(this.state.get('geomField'));
+ if (typeof(value) === 'string'){
+ // We have a GeoJSON string representation
+ return $.parseJSON(value);
+ } else {
+ // We assume that the contents of the field are a valid GeoJSON object
+ return value;
+ }
} else if (this.state.get('lonField') && this.state.get('latField')){
// We'll create a GeoJSON like point object from the two lat/lon fields
var lon = doc.get(this.state.get('lonField'));
var lat = doc.get(this.state.get('latField'));
- if (lon && lat) {
+ if (!isNaN(parseFloat(lon)) && !isNaN(parseFloat(lat))) {
return {
type: 'Point',
- coordinates: [
- doc.attributes[this.state.get('lonField')],
- doc.attributes[this.state.get('latField')]
- ]
+ coordinates: [lon,lat]
};
}
}
@@ -1761,6 +1796,18 @@ my.Map = Backbone.View.extend({
return null;
},
+ // Private: Zoom to map to current features extent if any, or to the full
+ // extent if none.
+ //
+ _zoomToFeatures: function(){
+ var bounds = this.features.getBounds();
+ if (bounds){
+ this.map.fitBounds(bounds);
+ } else {
+ this.map.setView(new L.LatLng(0, 0), 2);
+ }
+ },
+
// Private: Sets up the Leaflet map control and the features layer.
//
// The map uses a base layer from [MapQuest](http://www.mapquest.com) based
@@ -1785,6 +1832,24 @@ my.Map = Backbone.View.extend({
}
});
+
+ // This will be available in the next Leaflet stable release.
+ // In the meantime we add it manually to our layer.
+ this.features.getBounds = function(){
+ var bounds = new L.LatLngBounds();
+ this._iterateLayers(function (layer) {
+ if (layer instanceof L.Marker){
+ bounds.extend(layer.getLatLng());
+ } else {
+ if (layer.getBounds){
+ bounds.extend(layer.getBounds().getNorthEast());
+ bounds.extend(layer.getBounds().getSouthWest());
+ }
+ }
+ }, this);
+ return (typeof bounds.getNorthEast() !== 'undefined') ? bounds : null;
+ }
+
this.map.addLayer(this.features);
this.map.setView(new L.LatLng(0, 0), 2);
@@ -3404,7 +3469,9 @@ this.recline.Backend = this.recline.Backend || {};
var options = options || {};
var trm = options.trim;
var separator = options.separator || ',';
-
+ var delimiter = options.delimiter || '"';
+
+
var cur = '', // The character we are currently processing.
inQuote = false,
fieldQuoted = false,
@@ -3451,8 +3518,8 @@ this.recline.Backend = this.recline.Backend || {};
field = '';
fieldQuoted = false;
} else {
- // If it's not a ", add it to the field buffer
- if (cur !== '"') {
+ // If it's not a delimiter, add it to the field buffer
+ if (cur !== delimiter) {
field += cur;
} else {
if (!inQuote) {
@@ -3460,9 +3527,9 @@ this.recline.Backend = this.recline.Backend || {};
inQuote = true;
fieldQuoted = true;
} else {
- // Next char is ", this is an escaped "
- if (s.charAt(i + 1) === '"') {
- field += '"';
+ // Next char is delimiter, this is an escaped delimiter
+ if (s.charAt(i + 1) === delimiter) {
+ field += delimiter;
// Skip the next char
i += 1;
} else {
================================================================
Commit: d9fd8dfa0d03610e9c2d8387b29dd2af4f7b258b
https://github.com/okfn/ckan/commit/d9fd8dfa0d03610e9c2d8387b29dd2af4f7b258b
Author: Ian Murray <ian.murray at okfn.org>
Date: 2012-04-25 (Wed, 25 Apr 2012)
Changed paths:
M ckan/public/scripts/application.js
M ckan/templates/package/resource_read.html
Log Message:
-----------
[2285] Cross-browser compatibible way of providing embed src lnk
diff --git a/ckan/public/scripts/application.js b/ckan/public/scripts/application.js
index d78c3a9..46456c2 100644
--- a/ckan/public/scripts/application.js
+++ b/ckan/public/scripts/application.js
@@ -1322,7 +1322,7 @@ CKAN.DataPreview = function ($, my) {
state: explorerState.toJSON(),
state_version: 1
});
- return window.location.origin + window.location.pathname + '/embed' + qs;
+ return embedPath + qs;
};
// **Public: Loads a data preview**
diff --git a/ckan/templates/package/resource_read.html b/ckan/templates/package/resource_read.html
index 7508abb..c99805a 100644
--- a/ckan/templates/package/resource_read.html
+++ b/ckan/templates/package/resource_read.html
@@ -76,6 +76,7 @@
</style>
<script type="text/javascript">
var preload_resource = ${h.literal(c.resource_json)};
+ var embedPath = "${g.site_url+h.url_for(controller='package', action='resource_embedded_dataviewer', id=c.package.id, resource_id=c.resource.id)}";
</script>
</py:def>
================================================================
Compare: https://github.com/okfn/ckan/compare/7e2d796...d9fd8df
More information about the ckan-changes
mailing list