Skip to content

Commit

Permalink
[2285] First, very rough stab at making the data viewer embeddable.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ian Murray committed Apr 20, 2012
1 parent 440d830 commit bc2fd64
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 2 deletions.
1 change: 1 addition & 0 deletions ckan/config/routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ def make_map():
m.connect('/dataset/{id}.{format}', action='read')
m.connect('/dataset/{id}', action='read')
m.connect('/dataset/{id}/resource/{resource_id}', action='resource_read')
m.connect('/dataset/{id}/resource/{resource_id}/embed', action='resource_embeded_dataviewer')

# group
map.redirect('/groups', '/group')
Expand Down
48 changes: 48 additions & 0 deletions ckan/controllers/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -734,3 +734,51 @@ def resource_read(self, id, resource_id):
qualified=True)
return render('package/resource_read.html')

def resource_embeded_dataviewer(self, id, resource_id):
"""
Embeded page for a read-only resource dataview.
"""
context = {'model': model, 'session': model.Session,
'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'] ]:
raise NotFound

c.resource_json = json.dumps(resource)

except NotFound:
abort(404, _('Resource not found'))
except NotAuthorized:
abort(401, _('Unauthorized to read resource %s') % id)

# Construct the recline state
state_version = int(request.params.get('state_version', '1'))
raw_state = request.params.get('state', '')
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)

return render('package/resource_embeded_dataviewer.html')

def _parse_recline_state(self, state_version, raw_state):
if state_version != 1: # Only support one version at the moment
return None

try:
return json.loads(raw_state)
except ValueError:
return None
40 changes: 38 additions & 2 deletions ckan/public/scripts/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ CKAN.Utils = CKAN.Utils || {};
if (isResourceView) {
CKAN.DataPreview.loadPreviewDialog(preload_resource);
}

var isEmbededDataviewer = $('body.package.resource_embeded_dataviewer').length > 0;
if (isEmbededDataviewer) {
CKAN.DataPreview.loadPreviewDialogWithState(preload_resource, reclineState);
}

var isDatasetNew = $('body.package.new').length > 0;
if (isDatasetNew) {
// Set up magic URL slug editor
Expand Down Expand Up @@ -1250,6 +1256,29 @@ CKAN.DataPreview = function ($, my) {
my.dialogId = 'ckanext-datapreview';
my.$dialog = $('#' + my.dialogId);

// **Public: Loads a data preview, taking into account an initial state**
//
my.loadPreviewDialogWithState = function(resourceData, reclineState) {
my.$dialog.html('<h4>Loading ... <img src="http://assets.okfn.org/images/icons/ajaxload-circle.gif" class="loading-spinner" /></h4>');

var dataset = recline.Model.Dataset.restore(reclineState);
var dataExplorer = new recline.View.DataExplorer({
el: my.$dialog,
model: dataset,
state: reclineState
});

Backbone.history.start();
};

my.makePermalink = function(explorerState) {
var qs = recline.View.composeQueryString({
state: explorerState.toJSON(),
state_version: 1
});
return window.location.origin + window.location.pathname + '/embed' + qs;
};

// **Public: Loads a data preview**
//
// Fetches the preview data object from the link provided and loads the
Expand All @@ -1267,14 +1296,14 @@ CKAN.DataPreview = function ($, my) {
{
id: 'grid',
label: 'Grid',
view: new recline.View.DataGrid({
view: new recline.View.Grid({
model: dataset
})
},
{
id: 'graph',
label: 'Graph',
view: new recline.View.FlotGraph({
view: new recline.View.Graph({
model: dataset
})
},
Expand All @@ -1294,6 +1323,13 @@ CKAN.DataPreview = function ($, my) {
readOnly: true
}
});

var permalink = $('.permalink');
dataExplorer.state.bind('change', function() {
permalink.attr('href', my.makePermalink(dataExplorer.state));
});
permalink.attr('href', my.makePermalink(dataExplorer.state));

// will have to refactor if this can get called multiple times
Backbone.history.start();
}
Expand Down
82 changes: 82 additions & 0 deletions ckan/templates/package/resource_embeded_dataviewer.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:i18n="http://genshi.edgewall.org/i18n"
xmlns:py="http://genshi.edgewall.org/"
xmlns:xi="http://www.w3.org/2001/XInclude"
py:strip="">

<py:def function="optional_head">
<!-- data preview -->
<link rel="stylesheet" href="${h.url_for_static('/scripts/vendor/leaflet/0.3.1/leaflet.css')}" />
<!--[if lte IE 8]>
<link rel="stylesheet" href="${h.url_for_static('/scripts/vendor/leaflet/0.3.1/leaflet.ie.css')}" />
<![endif]-->
<link rel="stylesheet" href="${h.url_for_static('/scripts/vendor/recline/css/data-explorer.css')}" />
<link rel="stylesheet" href="${h.url_for_static('/scripts/vendor/recline/css/graph-flot.css')}" />
<link rel="stylesheet" href="${h.url_for_static('/scripts/vendor/recline/css/map.css')}" />
<style type="text/css">
.recline-query-editor form, .recline-query-editor .text-query {
height: 28px;
}

.recline-query-editor .pagination ul {
margin: 0;
padding: 0;
}

/* needed for Chrome but not FF */
.header .recline-query-editor .add-on {
margin-left: -27px;
}

/* needed for FF but not chrome */
.header .recline-query-editor .input-prepend {
vertical-align: top;
}
</style>
<!-- /data preview -->
<style type="text/css">
.resource-actions {
margin-right: 0;
}
.resource-actions .btn {
position: relative;
bottom: 3px;
padding: 8px 10px;
}
.resource-actions .download {
display: inline;
}
.resource-actions .download img {
margin: 0px 4px -4px 0;
}
</style>
<script type="text/javascript">
var preload_resource = ${h.literal(c.resource_json)};
var reclineState = ${h.literal(c.recline_state)};
</script>
</py:def>

<py:def function="page_title">
${h.dataset_display_name(c.package)} /
${h.resource_display_name(c.resource)} - Dataset - Resource
</py:def>

<div py:match="content">
<div class="resource-preview">
<h3>Preview</h3>
<a class="permalink" href="">Permalink</a>
<div id="ckanext-datapreview"></div>
</div>
</div>

<py:def function="optional_footer">
<!-- data preview -->
<script type="text/javascript" src="${h.url_for_static('/scripts/vendor/jquery.mustache/jquery.mustache.js')}"></script>
<script type="text/javascript" src="${h.url_for_static('/scripts/vendor/flot/0.7/jquery.flot.js')}"></script>
<script type="text/javascript" src="${h.url_for_static('/scripts/vendor/flot/0.7/jquery.flot.js')}"></script>
<script type="text/javascript" src="${h.url_for_static('/scripts/vendor/leaflet/0.3.1/leaflet.js')}"></script>
<script src="${h.url_for_static('/scripts/vendor/recline/recline.js')}"></script>
</py:def>

<xi:include href="../layout_base.html" />
</html>
1 change: 1 addition & 0 deletions ckan/templates/package/resource_read.html
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@

<div class="resource-preview">
<h3>Preview</h3>
<a class="permalink" href="">Permalink</a>
<div id="ckanext-datapreview"></div>
</div>

Expand Down

0 comments on commit bc2fd64

Please sign in to comment.