Skip to content

Commit

Permalink
[#1251] Updating Recline views for new IResourceView
Browse files Browse the repository at this point in the history
interface.

The only view options that are currently supported
are row offset and limit (so the graph in
particular is not usable at the moment).
  • Loading branch information
johnglover committed Nov 6, 2013
1 parent 294ed98 commit 1080ac0
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 124 deletions.
80 changes: 64 additions & 16 deletions ckanext/reclinepreview/plugin.py
@@ -1,36 +1,84 @@
from logging import getLogger

from ckan.common import json
import ckan.plugins as p
import ckan.plugins.toolkit as toolkit

log = getLogger(__name__)
ignore_missing = p.toolkit.get_validator('ignore_missing')
natural_number_validator = p.toolkit.get_validator('natural_number_validator')


class ReclinePreview(p.SingletonPlugin):
"""This extension previews resources using recline
This extension implements two interfaces
- ``IConfigurer`` allows to modify the configuration
- ``IResourcePreview`` allows to add previews
"""
class ReclineView(p.SingletonPlugin):
'''
This base class for the Recline view extensions.
'''
p.implements(p.IConfigurer, inherit=True)
p.implements(p.IResourcePreview, inherit=True)
p.implements(p.IResourceView, inherit=True)

# schema fields that apply to all Recline views
schema = {'offset': [ignore_missing, natural_number_validator],
'limit': [ignore_missing, natural_number_validator]}

def update_config(self, config):
''' Set up the resource library, public directory and
'''
Set up the resource library, public directory and
template directory for the preview
'''
toolkit.add_public_directory(config, 'theme/public')
toolkit.add_template_directory(config, 'theme/templates')
toolkit.add_resource('theme/public', 'ckanext-reclinepreview')

def can_preview(self, data_dict):
# if the resource is in the datastore then we can preview it with recline
def can_view(self, data_dict):
if data_dict['resource'].get('datastore_active'):
return True
format_lower = data_dict['resource']['format'].lower()
return format_lower in ['csv', 'xls', 'tsv']
return False

def setup_template_variables(self, context, data_dict):
return {'resource_json': json.dumps(data_dict['resource']),
'resource_view_json': json.dumps(data_dict['resource_view'])}

def view_template(self, context, data_dict):
return 'recline_view.html'


class ReclineGrid(ReclineView):
'''
This extension views resources using a Recline grid.
'''

def info(self):
return {'name': 'recline_grid',
'title': 'Grid',
'schema': self.schema}

def form_template(self, context, data_dict):
return 'recline_grid_form.html'


class ReclineGraph(ReclineView):
'''
This extension views resources using a Recline graph.
'''

def info(self):
return {'name': 'recline_graph',
'title': 'Graph',
'schema': self.schema}

def form_template(self, context, data_dict):
return 'recline_graph_form.html'


class ReclineMap(ReclineView):
'''
This extension views resources using a Recline map.
'''

def info(self):
return {'name': 'recline_map',
'title': 'Map',
'schema': self.schema}

def preview_template(self, context, data_dict):
return 'recline.html'
def form_template(self, context, data_dict):
return 'recline_map_form.html'
146 changes: 41 additions & 105 deletions ckanext/reclinepreview/theme/public/preview_recline.js
Expand Up @@ -3,10 +3,10 @@ this.ckan.module('reclinepreview', function (jQuery, _) {
return {
options: {
i18n: {
errorLoadingPreview: "Could not load preview",
errorLoadingPreview: "Could not load view",
errorDataProxy: "DataProxy returned an error",
errorDataStore: "DataStore returned an error",
previewNotAvailableForDataType: "Preview not available for data type: "
previewNotAvailableForDataType: "View not available for data type: "
},
site_url: ""
},
Expand All @@ -19,35 +19,17 @@ this.ckan.module('reclinepreview', function (jQuery, _) {
},

_onReady: function() {
this.loadPreviewDialog(preload_resource);
this.loadView(preload_resource, preload_resource_view);
},

// **Public: Loads a data preview**
//
// Fetches the preview data object from the link provided and loads the
// parsed data from the webstore displaying it in the most appropriate
// manner.
//
// link - Preview button.
//
// Returns nothing.
loadPreviewDialog: function (resourceData) {
loadView: function (resourceData, reclineView) {
var self = this;

function showError(msg){
msg = msg || _('error loading preview');
window.parent.ckan.pubsub.publish('data-viewer-error', msg);
}

recline.Backend.DataProxy.timeout = 10000;
// will no be necessary any more with https://github.com/okfn/recline/pull/345
recline.Backend.DataProxy.dataproxy_url = '//jsonpdataproxy.appspot.com';

// 2 situations
// a) something was posted to the datastore - need to check for this
// b) csv or xls (but not datastore)
resourceData.formatNormalized = this.normalizeFormat(resourceData.format);

resourceData.url = this.normalizeUrl(resourceData.url);
if (resourceData.formatNormalized === '') {
var tmp = resourceData.url.split('/');
Expand All @@ -62,96 +44,50 @@ this.ckan.module('reclinepreview', function (jQuery, _) {

var errorMsg, dataset;

if (resourceData.datastore_active) {
resourceData.backend = 'ckan';
// Set endpoint of the resource to the datastore api (so it can locate
// CKAN DataStore)
resourceData.endpoint = jQuery('body').data('site-root') + 'api';
dataset = new recline.Model.Dataset(resourceData);
errorMsg = this.options.i18n.errorLoadingPreview + ': ' + this.options.i18n.errorDataStore;
dataset.fetch()
.done(function(dataset){
self.initializeDataExplorer(dataset);
})
.fail(function(error){
if (error.message) errorMsg += ' (' + error.message + ')';
showError(errorMsg);
});
resourceData.backend = 'ckan';
resourceData.endpoint = jQuery('body').data('site-root') + 'api';

} else if (resourceData.formatNormalized in {'csv': '', 'xls': ''}) {
// set format as this is used by Recline in setting format for DataProxy
resourceData.format = resourceData.formatNormalized;
resourceData.backend = 'dataproxy';
dataset = new recline.Model.Dataset(resourceData);
errorMsg = this.options.i18n.errorLoadingPreview + ': ' +this.options.i18n.errorDataProxy;
dataset.fetch()
.done(function(dataset){
dataset.bind('query:fail', function (error) {
jQuery('.data-view-container', self.el).hide();
jQuery('.header', self.el).hide();
});
dataset = new recline.Model.Dataset(resourceData);
dataset.query({
"from": reclineView.offset || 0,
"size": reclineView.limit || 100
});

self.initializeDataExplorer(dataset);
})
.fail(function(error){
if (error.message) errorMsg += ' (' + error.message + ')';
showError(errorMsg);
});
}
errorMsg = this.options.i18n.errorLoadingPreview + ': ' + this.options.i18n.errorDataStore;
dataset.fetch()
.done(function(dataset){
self.initializeView(dataset, reclineView);
})
.fail(function(error){
if (error.message) errorMsg += ' (' + error.message + ')';
showError(errorMsg);
});
},

initializeDataExplorer: function (dataset) {
var views = [
{
id: 'grid',
label: 'Grid',
view: new recline.View.SlickGrid({
model: dataset
})
},
{
id: 'graph',
label: 'Graph',
view: new recline.View.Graph({
model: dataset
})
},
{
id: 'map',
label: 'Map',
view: new recline.View.Map({
model: dataset
})
}
];

var sidebarViews = [
{
id: 'valueFilter',
label: 'Filters',
view: new recline.View.ValueFilter({
model: dataset
})
}
];
initializeView: function (dataset, reclineView) {
var view;

var dataExplorer = new recline.View.MultiView({
el: this.el,
model: dataset,
views: views,
sidebarViews: sidebarViews,
config: {
readOnly: true
}
});
if(reclineView.view_type === "recline_graph") {
view = new recline.View.Graph({
model: dataset,
el: this.el
});
} else if(reclineView.view_type == "recline_map") {
view = new recline.View.Map({
model: dataset,
el: this.el
});
} else {
view = new recline.View.SlickGrid({
model: dataset,
el: this.el
});
}

view.visible = true;
view.render();
},
normalizeFormat: function (format) {
var out = format.toLowerCase();
out = out.split('/');
out = out[out.length-1];
return out;
},

normalizeUrl: function (url) {
if (url.indexOf('https') === 0) {
return 'http' + url.slice(5);
Expand Down
@@ -0,0 +1,4 @@
{% import 'macros/form.html' as form %}

{{ form.input('offset', id='field-offset', label=_('Row offset'), placeholder=_('eg: 0'), value=data.offset, error=errors.offset, classes=['control-medium']) }}
{{ form.input('limit', id='field-limit', label=_('Number of rows'), placeholder=_('eg: 100'), value=data.limit, error=errors.limit, classes=['control-medium']) }}
4 changes: 4 additions & 0 deletions ckanext/reclinepreview/theme/templates/recline_grid_form.html
@@ -0,0 +1,4 @@
{% import 'macros/form.html' as form %}

{{ form.input('offset', id='field-offset', label=_('Row offset'), placeholder=_('eg: 0'), value=data.offset, error=errors.offset, classes=['control-medium']) }}
{{ form.input('limit', id='field-limit', label=_('Number of rows'), placeholder=_('eg: 100'), value=data.limit, error=errors.limit, classes=['control-medium']) }}
5 changes: 5 additions & 0 deletions ckanext/reclinepreview/theme/templates/recline_map_form.html
@@ -0,0 +1,5 @@
{% import 'macros/form.html' as form %}

{{ form.input('offset', id='field-offset', label=_('Row offset'), placeholder=_('eg: 0'), value=data.offset, error=errors.offset, classes=['control-medium']) }}
{{ form.input('limit', id='field-limit', label=_('Number of rows'), placeholder=_('eg: 100'), value=data.limit, error=errors.limit, classes=['control-medium']) }}

@@ -1,4 +1,4 @@
{% extends "dataviewer/base.html" %}
{% extends "base.html" %}

{% block page %}
<div data-module="reclinepreview" data-module-site_url="{{ h.dump_json(h.url('/', locale='default', qualified=true)) }}">
Expand All @@ -9,4 +9,14 @@ <h4 class="loading-dialog">
</div>

{% resource 'ckanext-reclinepreview/main' %}
{% endblock %}
{% endblock %}

{% block scripts %}
<script>
var preload_resource = {{ h.literal(resource_json) }};
var preload_resource_view = {{ h.literal(resource_view_json) }};
</script>
{% endblock %}

{% block styles %}{% endblock %}
{% block custom_styles %}{% endblock %}
4 changes: 3 additions & 1 deletion setup.py
Expand Up @@ -120,7 +120,9 @@
resource_proxy=ckanext.resourceproxy.plugin:ResourceProxy
text_preview=ckanext.textpreview.plugin:TextPreview
pdf_preview=ckanext.pdfpreview.plugin:PdfPreview
recline_preview=ckanext.reclinepreview.plugin:ReclinePreview
recline_grid=ckanext.reclinepreview.plugin:ReclineGrid
recline_graph=ckanext.reclinepreview.plugin:ReclineGraph
recline_map=ckanext.reclinepreview.plugin:ReclineMap
example_itemplatehelpers=ckanext.example_itemplatehelpers.plugin:ExampleITemplateHelpersPlugin
example_idatasetform=ckanext.example_idatasetform.plugin:ExampleIDatasetFormPlugin
example_iauthfunctions_v1=ckanext.example_iauthfunctions.plugin_v1:ExampleIAuthFunctionsPlugin
Expand Down

0 comments on commit 1080ac0

Please sign in to comment.