diff --git a/ckanext/example_idatasetform/__init__.py b/ckanext/example_idatasetform/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ckanext/example_idatasetform/plugin.py b/ckanext/example_idatasetform/plugin.py new file mode 100644 index 00000000000..64f0efbe86d --- /dev/null +++ b/ckanext/example_idatasetform/plugin.py @@ -0,0 +1,163 @@ +import logging + +import ckan.plugins as plugins +import ckan.plugins.toolkit as tk +import ckan.lib.plugins as lib_plugins + + +class ExampleIDatasetFormPlugin(plugins.SingletonPlugin, + lib_plugins.DefaultDatasetForm): + '''An example IDatasetForm CKAN plugin. + + Uses a tag vocabulary to add a custom metadata field to datasets. + + ''' + plugins.implements(plugins.IConfigurer, inherit=False) + plugins.implements(plugins.IDatasetForm, inherit=False) + + # These record how many times methods that this plugin's methods are + # called, for testing purposes. + num_times_new_template_called = 0 + num_times_read_template_called = 0 + num_times_edit_template_called = 0 + num_times_comments_template_called = 0 + num_times_search_template_called = 0 + num_times_history_template_called = 0 + num_times_package_form_called = 0 + num_times_check_data_dict_called = 0 + + def create_country_codes(self): + '''Create country_codes vocab and tags, if they don't exist already. + + Note that you could also create the vocab and tags using CKAN's API, + and once they are created you can edit them (e.g. to add and remove + possible dataset country code values) using the API. + + ''' + user = tk.get_action('get_site_user')({'ignore_auth': True}, {}) + context = {'user': user['name']} + try: + data = {'id': 'country_codes'} + tk.get_action('vocabulary_show')(context, data) + logging.info("Example genre vocabulary already exists, skipping.") + except tk.ObjectNotFound: + logging.info("Creating vocab 'country_codes'") + data = {'name': 'country_codes'} + vocab = tk.get_action('vocabulary_create')(context, data) + for tag in (u'uk', u'ie', u'de', u'fr', u'es'): + logging.info( + "Adding tag {0} to vocab 'country_codes'".format(tag)) + data = {'name': tag, 'vocabulary_id': vocab['id']} + tk.get_action('tag_create')(context, data) + + def update_config(self, config): + # Add this plugin's templates dir to CKAN's extra_template_paths, so + # that CKAN will use this plugin's custom templates. + tk.add_template_directory(config, 'templates') + + def is_fallback(self): + # Return True to register this plugin as the default handler for + # package types not handled by any other IDatasetForm plugin. + return True + + def package_types(self): + # This plugin doesn't handle any special package types, it just + # registers itself as the default (above). + return [] + + def form_to_db_schema(self): + schema = super(ExampleIDatasetFormPlugin, self).form_to_db_schema() + + # Add our custom country_code metadata field to the schema. + schema.update({ + 'country_code': [tk.get_validator('ignore_missing'), + tk.get_converter('convert_to_tags')('country_codes')] + }) + + # Add our custom_test metadata field to the schema, this one will use + # convert_to_extras instead of convert_to_tags. + schema.update({ + 'custom_text': [tk.get_validator('ignore_missing'), + tk.get_converter('convert_to_extras')] + }) + + return schema + + def db_to_form_schema(self): + schema = super(ExampleIDatasetFormPlugin, self).db_to_form_schema() + + # Don't show vocab tags mixed in with normal 'free' tags + # (e.g. on dataset pages, or on the search page) + schema['tags']['__extras'].append(tk.get_converter('free_tags_only')) + + # Add our custom country_code metadata field to the schema. + schema.update({ + 'country_code': [ + tk.get_converter('convert_from_tags')('country_codes'), + tk.get_validator('ignore_missing')] + }) + + # Add our custom_text field to the dataset schema. + schema.update({ + 'custom_text': [tk.get_converter('convert_from_extras'), + tk.get_validator('ignore_missing')] + }) + + return schema + + def setup_template_variables(self, context, data_dict=None): + super(ExampleIDatasetFormPlugin, self).setup_template_variables( + context, data_dict) + + # Create the country_codes vocab and tags, if they don't already exist. + self.create_country_codes() + + # Add the list of available country codes, from the country_codes + # vocab, to the template context. + try: + tk.c.country_codes = tk.get_action('tag_list')( + context, {'vocabulary_id': 'country_codes'}) + except tk.ObjectNotFound: + tk.c.country_codes = None + + # These methods just record how many times they're called, for testing + # purposes. + # TODO: It might be better to test that custom templates returned by + # these methods are actually used, not just that the methods get + # called. + + def new_template(self): + ExampleIDatasetFormPlugin.num_times_new_template_called += 1 + return lib_plugins.DefaultDatasetForm.new_template(self) + + def read_template(self): + ExampleIDatasetFormPlugin.num_times_read_template_called += 1 + return lib_plugins.DefaultDatasetForm.read_template(self) + + def edit_template(self): + ExampleIDatasetFormPlugin.num_times_edit_template_called += 1 + return lib_plugins.DefaultDatasetForm.edit_template(self) + + def comments_template(self): + ExampleIDatasetFormPlugin.num_times_comments_template_called += 1 + return lib_plugins.DefaultDatasetForm.comments_template(self) + + def search_template(self): + ExampleIDatasetFormPlugin.num_times_search_template_called += 1 + return lib_plugins.DefaultDatasetForm.search_template(self) + + def history_template(self): + ExampleIDatasetFormPlugin.num_times_history_template_called += 1 + return lib_plugins.DefaultDatasetForm.history_template(self) + + def package_form(self): + ExampleIDatasetFormPlugin.num_times_package_form_called += 1 + return lib_plugins.DefaultDatasetForm.package_form(self) + + def check_data_dict(self, data_dict, schema=None): + ExampleIDatasetFormPlugin.num_times_check_data_dict_called += 1 + # Disable DefaultDatasetForm's check_data_dict(), because it breaks + # with the new three-stage dataset creation when using + # convert_to_extras. + #return lib_plugins.DefaultDatasetForm.check_data_dict(self, data_dict, + # schema) diff --git a/ckanext/example_idatasetform/templates/package/new_package_metadata.html b/ckanext/example_idatasetform/templates/package/new_package_metadata.html new file mode 100644 index 00000000000..dbe6af6871b --- /dev/null +++ b/ckanext/example_idatasetform/templates/package/new_package_metadata.html @@ -0,0 +1,6 @@ +{% ckan_extends %} + + +{% block form %}{{ h.snippet('package/snippets/package_metadata_form.html', data=data, errors=errors, include_metadata=false, pkg_name=pkg_name, country_codes=c.country_codes) }}{% endblock %} diff --git a/ckanext/example_idatasetform/templates/package/read.html b/ckanext/example_idatasetform/templates/package/read.html new file mode 100644 index 00000000000..19db768c789 --- /dev/null +++ b/ckanext/example_idatasetform/templates/package/read.html @@ -0,0 +1,13 @@ +{% ckan_extends %} + +{% block package_description %} + {{ super() }} + + + {% if pkg.get('country_code') %} +
+

Country Code: {{ pkg.country_code[0] }}

+
+ {% endif %} + +{% endblock %} diff --git a/ckanext/example_idatasetform/templates/package/snippets/package_form.html b/ckanext/example_idatasetform/templates/package/snippets/package_form.html new file mode 100644 index 00000000000..573f1333cbc --- /dev/null +++ b/ckanext/example_idatasetform/templates/package/snippets/package_form.html @@ -0,0 +1,8 @@ +{% ckan_extends %} + + +{% block metadata_fields %} + {% snippet 'package/snippets/package_metadata_fields.html', data=data, errors=errors, country_codes=c.country_codes %} +{% endblock %} diff --git a/ckanext/example_idatasetform/templates/package/snippets/package_metadata_fields.html b/ckanext/example_idatasetform/templates/package/snippets/package_metadata_fields.html new file mode 100644 index 00000000000..a5f82e2cc32 --- /dev/null +++ b/ckanext/example_idatasetform/templates/package/snippets/package_metadata_fields.html @@ -0,0 +1,42 @@ +{% import 'macros/form.html' as form %} + +{% set groups_available = h.groups_available() %} +{% if groups_available %} +
+ {% set groups = h.dict_list_reduce(data.groups, 'id') %} + +
+ +
+
+{% endif %} + +{{ form.input('author', label=_('Author'), id='field-author', placeholder=_('Joe Bloggs'), value=data.author, error=errors.author, classes=['control-medium']) }} + +{{ form.input('author_email', label=_('Author Email'), id='field-author-email', placeholder=_('joe@example.com'), value=data.author_email, error=errors.author_email, classes=['control-medium']) }} + +{{ form.input('maintainer', label=_('Maintainer'), id='field-maintainer', placeholder=_('Joe Bloggs'), value=data.maintainer, error=errors.maintainer, classes=['control-medium']) }} + +{{ form.input('maintainer_email', label=_('Maintainer Email'), id='field-maintainer-email', placeholder=_('joe@example.com'), value=data.maintainer_email, error=errors.maintainer_email, classes=['control-medium']) }} + + +
+ +
+ +{{ form.input('custom_text', label=_('Custom Text'), id='field-custom_text', placeholder=_('custom text'), value=data.custom_text, error=errors.custom_text, classes=['control-medium']) }} + +{# +{% block custom_fields %} + {% snippet 'snippets/custom_form_fields.html', extras=data.extras, errors=errors, limit=3 %} +{% endblock %} +#} diff --git a/ckanext/example_idatasetform/templates/package/snippets/package_metadata_form.html b/ckanext/example_idatasetform/templates/package/snippets/package_metadata_form.html new file mode 100644 index 00000000000..da95a2347bb --- /dev/null +++ b/ckanext/example_idatasetform/templates/package/snippets/package_metadata_form.html @@ -0,0 +1,21 @@ +{% import "macros/form.html" as form %} + +{% set data = data or {} %} +{% set errors = errors or {} %} + +
+ {{ h.snippet('package/snippets/stages.html', stages=['complete', 'complete', 'active'], pkg_name=pkg_name) }} + {{ form.errors(error_summary) }} + + + {% snippet 'package/snippets/package_metadata_fields.html', data=data, errors=errors, groups_available=groups_available, country_codes=country_codes %} + +
+ {# TODO: Go back to previous resource form #} + + +
+ +
diff --git a/setup.py b/setup.py index 8236fc66bb0..a446cba0b85 100644 --- a/setup.py +++ b/setup.py @@ -125,6 +125,7 @@ pdf_preview=ckanext.pdfpreview.plugin:PdfPreview recline_preview=ckanext.reclinepreview.plugin:ReclinePreview example_itemplatehelpers=ckanext.example_itemplatehelpers.plugin:ExampleITemplateHelpersPlugin + example_idatasetform=ckanext.example_idatasetform.plugin:ExampleIDatasetFormPlugin [ckan.system_plugins] domain_object_mods = ckan.model.modification:DomainObjectModificationExtension