From bbe459527f280e5f611bd34228a069025cfeb829 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Mercader?= Date: Fri, 13 May 2011 14:17:58 +0100 Subject: [PATCH] [forms] Major refactoring of the harvest forms. Forms no longer use the DGU form API, and are handled similarly to the new ones on CKAN core (logic, schema, validators...). The UI is also more consistent with the CKAN one. --- ckanext/harvest/controllers/view.py | 215 ++++++++---------- ckanext/harvest/lib/__init__.py | 112 +++++---- ckanext/harvest/logic/__init__.py | 7 + ckanext/harvest/logic/schema.py | 33 +++ ckanext/harvest/logic/validators.py | 74 ++++++ ckanext/harvest/model/__init__.py | 6 +- ckanext/harvest/plugin.py | 34 +-- .../templates/ckanext/harvest/create.html | 28 --- .../{ckanext/harvest => }/index.html | 10 +- ckanext/harvest/templates/source/edit.html | 23 ++ ckanext/harvest/templates/source/new.html | 22 ++ .../templates/source/new_source_form.html | 47 ++++ .../harvest/show.html => source/read.html} | 2 +- 13 files changed, 395 insertions(+), 218 deletions(-) create mode 100644 ckanext/harvest/logic/__init__.py create mode 100644 ckanext/harvest/logic/schema.py create mode 100644 ckanext/harvest/logic/validators.py delete mode 100644 ckanext/harvest/templates/ckanext/harvest/create.html rename ckanext/harvest/templates/{ckanext/harvest => }/index.html (82%) create mode 100644 ckanext/harvest/templates/source/edit.html create mode 100644 ckanext/harvest/templates/source/new.html create mode 100644 ckanext/harvest/templates/source/new_source_form.html rename ckanext/harvest/templates/{ckanext/harvest/show.html => source/read.html} (98%) diff --git a/ckanext/harvest/controllers/view.py b/ckanext/harvest/controllers/view.py index 69b6319..a2b0d6c 100644 --- a/ckanext/harvest/controllers/view.py +++ b/ckanext/harvest/controllers/view.py @@ -1,21 +1,21 @@ -import urllib2 - from pylons.i18n import _ import ckan.lib.helpers as h, json from ckan.lib.base import BaseController, c, g, request, \ response, session, render, config, abort, redirect -from ckan.model import Package - -from ckanext.harvest.lib import * +from ckan.lib.navl.dictization_functions import DataError +from ckan.logic import NotFound, ValidationError +from ckanext.harvest.logic.schema import harvest_source_form_schema +from ckanext.harvest.lib import create_harvest_source, edit_harvest_source, \ + get_harvest_source, get_harvest_sources, \ + create_harvest_job, get_registered_harvesters_types + +import logging +log = logging.getLogger(__name__) class ViewController(BaseController): - api_url = config.get('ckan.api_url', 'http://localhost:5000').rstrip('/')+'/api/2/rest' - form_api_url = config.get('ckan.api_url', 'http://localhost:5000').rstrip('/')+'/api/2/form' - api_key = config.get('ckan.harvest.api_key') - def __before__(self, action, **env): super(ViewController, self).__before__(action, **env) # All calls to this controller must be with a sysadmin key @@ -24,138 +24,123 @@ class ViewController(BaseController): status = 401 abort(status, response_msg) - def _do_request(self,url,data = None): - - http_request = urllib2.Request( - url = url, - headers = {'Authorization' : self.api_key} - ) - - if data: - http_request.add_data(data) - - try: - return urllib2.urlopen(http_request) - except urllib2.HTTPError as e: - raise - def index(self): # Request all harvest sources c.sources = get_harvest_sources() - return render('ckanext/harvest/index.html') + return render('index.html') - def create(self): + def new(self,data = None,errors = None, error_summary = None): - # This is the DGU form API, so we don't use self.api_url - form_url = self.form_api_url + '/harvestsource/create' - if request.method == 'GET': + if ('save' in request.params) and not data: + return self._save_new() + + data = data or {} + errors = errors or {} + error_summary = error_summary or {} + #TODO: Use new description interface to build the types select and descriptions + vars = {'data': data, 'errors': errors, 'error_summary': error_summary, 'types': get_registered_harvesters_types()} + + c.form = render('source/new_source_form.html', extra_vars=vars) + return render('source/new.html') + + def _save_new(self): + try: + data_dict = dict(request.params) + self._check_data_dict(data_dict) + + source = create_harvest_source(data_dict) + + # Create a harvest job for the new source + create_harvest_job(source['id']) + + h.flash_success(_('New harvest source added successfully.' + 'A new harvest job for the source has also been created.')) + redirect(h.url_for('harvest')) + except DataError,e: + abort(400, 'Integrity Error') + except ValidationError,e: + errors = e.error_dict + error_summary = e.error_summary if 'error_summary' in e else None + return self.new(data_dict, errors, error_summary) + + def edit(self, id, data = None,errors = None, error_summary = None): + + if ('save' in request.params) and not data: + return self._save_edit(id) + + if not data: try: - # Request the fields - c.form = self._do_request(form_url).read() - c.mode = 'create' - except urllib2.HTTPError as e: - msg = 'An error occurred: [%s %s]' % (str(e.getcode()),e.msg) - h.flash_error(msg) - return render('ckanext/harvest/create.html') - if request.method == 'POST': - # Build an object like the one expected by the DGU form API - data = { - 'form_data': - {'HarvestSource--url': request.POST['HarvestSource--url'], - 'HarvestSource--description': request.POST['HarvestSource--description'], - 'HarvestSource--type': request.POST['HarvestSource--type'], - }, - 'user_id':'', - 'publisher_id':'' - } - data = json.dumps(data) - try: - rq = self._do_request(form_url,data) + old_data = get_harvest_source(id) + except NotFound: + abort(404, _('Harvest Source not found')) - h.flash_success('Harvesting source added successfully') - redirect(h.url_for('harvest')) + data = data or old_data + errors = errors or {} + error_summary = error_summary or {} + #TODO: Use new description interface to build the types select and descriptions + vars = {'data': data, 'errors': errors, 'error_summary': error_summary, 'types': get_registered_harvesters_types()} + + c.form = render('source/new_source_form.html', extra_vars=vars) + return render('source/edit.html') - except urllib2.HTTPError as e: - msg = 'An error occurred: [%s %s]' % (str(e.getcode()),e.msg) - # The form API returns just a 500, so we are not exactly sure of what - # happened, but most probably it was a duplicate entry - if e.getcode() == 500: - msg = msg + ' Does the source already exist?' - elif e.getcode() == 400: - err_msg = e.read() - if ' - - - ${title} - - - - - -
-
-

${title}

-
- ${Markup(c.form)} - -
-
-
- - diff --git a/ckanext/harvest/templates/ckanext/harvest/index.html b/ckanext/harvest/templates/index.html similarity index 82% rename from ckanext/harvest/templates/ckanext/harvest/index.html rename to ckanext/harvest/templates/index.html index 52ffb5a..e59ee50 100644 --- a/ckanext/harvest/templates/ckanext/harvest/index.html +++ b/ckanext/harvest/templates/index.html @@ -12,7 +12,7 @@

Harvesting Sources

- Add a harvesting source + Add a harvesting source @@ -31,9 +31,9 @@ - ${h.link_to('view', 'harvest/' + source.id)} - ${h.link_to('edit', 'harvest/' + source.id + '/edit')} - ${h.link_to('refresh', 'harvest/' + source.id + '/refresh')} + ${h.link_to('view', 'harvest/%s' % source.id)} + ${h.link_to('edit', 'harvest/edit/%s' % source.id)} + ${h.link_to('refresh', 'harvest/refresh/%s' % source.id)} ${source.url} ${source.type} ${source.active} @@ -59,5 +59,5 @@
- + diff --git a/ckanext/harvest/templates/source/edit.html b/ckanext/harvest/templates/source/edit.html new file mode 100644 index 0000000..96465b5 --- /dev/null +++ b/ckanext/harvest/templates/source/edit.html @@ -0,0 +1,23 @@ + + + Edit - Harvest Source + + hide-sidebar + + + + +
+
+

Edit harvest source

+ + + ${h.literal(c.form)} + +
+
+ + diff --git a/ckanext/harvest/templates/source/new.html b/ckanext/harvest/templates/source/new.html new file mode 100644 index 0000000..16315fa --- /dev/null +++ b/ckanext/harvest/templates/source/new.html @@ -0,0 +1,22 @@ + + + New - Harvest Source + + hide-sidebar + + + + +
+
+

New harvest source

+ + ${h.literal(c.form)} + +
+
+ + diff --git a/ckanext/harvest/templates/source/new_source_form.html b/ckanext/harvest/templates/source/new_source_form.html new file mode 100644 index 0000000..f404dde --- /dev/null +++ b/ckanext/harvest/templates/source/new_source_form.html @@ -0,0 +1,47 @@ +
+ +
+

Errors in form

+

The form contains invalid entries:

+
    +
  • ${"%s: %s" % (key, error)}
  • +
+
+ +
+ Details +
+
+
+
${errors.get('url', '')}
+
This should include the http:// part of the URL
+
+
+ +
+
${errors.get('type', '')}
+
Which type of source does the URL above represent? + TODO: get these from the harvesters +
    +
  • A server's CSW interface
  • +
  • A Web Accessible Folder (WAF) displaying a list of GEMINI 2.1 documents
  • +
  • A single GEMINI 2.1 document
  • +
+
+
+
+
You can add your own notes here about what the URL above represents to remind you later.
+
+
+ + +
diff --git a/ckanext/harvest/templates/ckanext/harvest/show.html b/ckanext/harvest/templates/source/read.html similarity index 98% rename from ckanext/harvest/templates/ckanext/harvest/show.html rename to ckanext/harvest/templates/source/read.html index 76aefcd..665fff7 100644 --- a/ckanext/harvest/templates/ckanext/harvest/show.html +++ b/ckanext/harvest/templates/source/read.html @@ -89,5 +89,5 @@ - +