Skip to content

Commit

Permalink
Merge pull request #3444 from ckan/3444-datatables-view
Browse files Browse the repository at this point in the history
DataTables view
  • Loading branch information
wardi committed Jun 7, 2017
2 parents 977afe7 + d9900ec commit 16c1100
Show file tree
Hide file tree
Showing 82 changed files with 97,409 additions and 1 deletion.
5 changes: 4 additions & 1 deletion ckanext/datastore/helpers.py
Expand Up @@ -123,7 +123,10 @@ def datastore_dictionary(resource_id):
try:
return [
f for f in get_action('datastore_search')(
None, {u'resource_id': resource_id, u'limit': 0})['fields']
None, {
u'resource_id': resource_id,
u'limit': 0,
u'include_total': False})['fields']
if not f['id'].startswith(u'_')]
except (ObjectNotFound, NotAuthorized):
return []
Empty file.
88 changes: 88 additions & 0 deletions ckanext/datatablesview/controller.py
@@ -0,0 +1,88 @@
# encoding: utf-8

import json

from ckan.plugins.toolkit import BaseController, request, get_action


class DataTablesController(BaseController):
def ajax(self, resource_view_id):
resource_view = get_action(u'resource_view_show')(
None, {u'id': resource_view_id})

draw = int(request.params['draw'])
search_text = unicode(request.params['search[value]'])
offset = int(request.params['start'])
limit = int(request.params['length'])
view_filters = resource_view.get(u'filters', {})
user_filters = unicode(request.params['filters'])
filters = merge_filters(view_filters, user_filters)

datastore_search = get_action(u'datastore_search')
unfiltered_response = datastore_search(None, {
u"resource_id": resource_view[u'resource_id'],
u"limit": 0,
u"filters": view_filters,
})

cols = [f['id'] for f in unfiltered_response['fields']]
if u'show_fields' in resource_view:
cols = [c for c in cols if c in resource_view['show_fields']]

sort_list = []
i = 0
while True:
if u'order[%d][column]' % i not in request.params:
break
sort_by_num = int(request.params[u'order[%d][column]' % i])
sort_order = (
u'desc' if request.params[u'order[%d][dir]' % i] == u'desc'
else u'asc')
sort_list.append(cols[sort_by_num] + u' ' + sort_order)
i += 1

response = datastore_search(None, {
u"q": search_text,
u"resource_id": resource_view[u'resource_id'],
u"offset": offset,
u"limit": limit,
u"sort": u', '.join(sort_list),
u"filters": filters,
})

return json.dumps({
u'draw': draw,
u'iTotalRecords': unfiltered_response.get(u'total', 0),
u'iTotalDisplayRecords': response.get(u'total', 0),
u'aaData': [
[unicode(row.get(colname, u'')) for colname in cols]
for row in response['records']
],
})


def merge_filters(view_filters, user_filters_str):
u'''
view filters are built as part of the view, user filters
are selected by the user interacting with the view. Any filters
selected by user may only tighten filters set in the view,
others are ignored.
>>> merge_filters({
... u'Department': [u'BTDT'], u'OnTime_Status': [u'ONTIME']},
... u'CASE_STATUS:Open|CASE_STATUS:Closed|Department:INFO')
{u'Department': [u'BTDT'],
u'OnTime_Status': [u'ONTIME'],
u'CASE_STATUS': [u'Open', u'Closed']}
'''
filters = dict(view_filters)
if not user_filters_str:
return filters
user_filters = {}
for k_v in user_filters_str.split(u'|'):
k, sep, v = k_v.partition(u':')
if k not in view_filters or v in view_filters[k]:
user_filters.setdefault(k, []).append(v)
for k in user_filters:
filters[k] = user_filters[k]
return filters
60 changes: 60 additions & 0 deletions ckanext/datatablesview/plugin.py
@@ -0,0 +1,60 @@
# encoding: utf-8

from logging import getLogger

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

default = toolkit.get_validator(u'default')
boolean_validator = toolkit.get_validator(u'boolean_validator')


class DataTablesView(p.SingletonPlugin):
'''
DataTables table view plugin
'''
p.implements(p.IConfigurer, inherit=True)
p.implements(p.IResourceView, inherit=True)
p.implements(p.IRoutes, inherit=True)

def update_config(self, config):
'''
Set up the resource library, public directory and
template directory for the view
'''
toolkit.add_template_directory(config, u'templates')
toolkit.add_resource(u'public', u'ckanext-datatablesview')

def can_view(self, data_dict):
resource = data_dict['resource']
return resource.get(u'datastore_active')

def view_template(self, context, data_dict):
return u'datatables/datatables_view.html'

def form_template(self, context, data_dict):
return u'datatables/datatables_form.html'

def info(self):
return {
u'name': u'datatables_view',
u'title': u'Table',
u'filterable': True,
u'icon': u'table',
u'requires_datastore': True,
u'default_title': p.toolkit._(u'Table'),
u'schema': {
u'responsive': [default(False), boolean_validator],
u'show_fields': [],
u'filterable': [default(True), boolean_validator],
}
}

def before_map(self, m):
m.connect(
u'/datatables/ajax/{resource_view_id}',
controller=u'ckanext.datatablesview.controller'
u':DataTablesController',
action=u'ajax')
return m
7 changes: 7 additions & 0 deletions ckanext/datatablesview/public/datatablesview.js
@@ -0,0 +1,7 @@
this.ckan.module('datatables_view', function (jQuery) {
return {
initialize: function() {
jQuery('#dtprv').DataTable({});
}
}
});
25 changes: 25 additions & 0 deletions ckanext/datatablesview/public/resource.config
@@ -0,0 +1,25 @@
[groups]

main =
vendor/Bootstrap-3.3.7/css/bootstrap.css
vendor/DataTables-1.10.15/css/dataTables.bootstrap.css
vendor/Buttons-1.3.1/css/buttons.bootstrap.css
vendor/FixedColumns-3.2.2/css/fixedColumns.bootstrap.css
vendor/FixedHeader-3.1.2/css/fixedHeader.bootstrap.css
vendor/KeyTable-2.2.1/css/keyTable.bootstrap.css
vendor/Responsive-2.1.1/css/responsive.bootstrap.css
vendor/Select-1.2.2/css/select.bootstrap.css

vendor/Bootstrap-3.3.7/js/bootstrap.js
vendor/DataTables-1.10.15/js/jquery.dataTables.js
vendor/DataTables-1.10.15/js/dataTables.bootstrap.js
vendor/Buttons-1.3.1/js/dataTables.buttons.js
vendor/Buttons-1.3.1/js/buttons.bootstrap.js
vendor/Buttons-1.3.1/js/buttons.colVis.js
vendor/FixedColumns-3.2.2/js/dataTables.fixedColumns.js
vendor/FixedHeader-3.1.2/js/dataTables.fixedHeader.js
vendor/KeyTable-2.2.1/js/dataTables.keyTable.js
vendor/Responsive-2.1.1/js/dataTables.responsive.js
vendor/Select-1.2.2/js/dataTables.select.js

datatablesview.js

0 comments on commit 16c1100

Please sign in to comment.