Skip to content

Commit

Permalink
feat(dev): frontend resource format;
Browse files Browse the repository at this point in the history
- Started frontend code for resource format.
- Changed autocomplete to basic selectable select2 element.
- Moved some code to reusable helper.
- Added API util endpoint.
  • Loading branch information
JVickery-TBS committed Jul 27, 2023
1 parent 983194d commit 84b82c6
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 58 deletions.
27 changes: 26 additions & 1 deletion ckanext/canada/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from ckan.controllers.package import PackageController
from ckan.logic import parse_params, NotFound

from ckanext.canada.helpers import normalize_strip_accents, canada_date_str_to_datetime
from ckanext.canada.helpers import normalize_strip_accents, canada_date_str_to_datetime, canada_guess_mimetype
from ckanext.canada.urlsafe import url_part_escape, url_part_unescape
from pylons.i18n import _
from pylons import config, session
Expand Down Expand Up @@ -738,6 +738,31 @@ def action(self, logic_function, ver=None):
return self._finish_ok(return_dict)


def guess_resource_format(self, ver=None):
try:
request_data = self._get_request_data(try_url_params=False)
except ValueError as e:
log.info('Bad API request data: %s', e)
return self._finish_bad_request(_('JSON Error: %s') % e)
if not isinstance(request_data, dict):
# this occurs if request_data is blank
log.info('Bad API request data - not dict: %r', request_data)
return self._finish_bad_request(_('Bad request data: %s') %
'Request data JSON decoded to %r but '
'it needs to be a dictionary.' % request_data)
if not request_data.get('url', None):
log.info('Bad API request data - missing url key: %r', request_data)
return self._finish_bad_request(_('Bad request data: %s') %
'Request data %r missing url key.' % request_data)
mimetype = canada_guess_mimetype(request_data.get('url', None))
return_dict = {
'success': True,
'result': mimetype
}
#TODO: convert mimetype to scheming value?
return self._finish_ok(return_dict)


def _log_api_access(context, data_dict):
if 'package' not in context:
if 'resource_id' not in data_dict:
Expand Down
22 changes: 22 additions & 0 deletions ckanext/canada/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import geomet.wkt as wkt
import json as json
from markupsafe import Markup, escape
from six.moves.urllib.parse import urlparse
import mimetypes

ORG_MAY_PUBLISH_OPTION = 'canada.publish_datasets_organization_name'
ORG_MAY_PUBLISH_DEFAULT_NAME = 'tb-ct'
Expand Down Expand Up @@ -545,3 +547,23 @@ def get_user_email(user_id):

except NotFound as e:
return ""


def canada_guess_mimetype(url):
"""
Returns mimetype based on url.
"""
mimetype, encoding = mimetypes.guess_type(url)
if mimetype:
return mimetype
else:
# if we cannot guess the mimetype, check if
# it is an actual web address
# and we can set the mimetype to text/html.
# Uploaded files have only the filename as url,
# so check scheme to determine if it's
# an actual web address
parsed = urlparse(url)
if parsed.scheme:
return 'text/html'
return None
21 changes: 21 additions & 0 deletions ckanext/canada/internal/static/registry_resource_edit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
window.addEventListener('load', function(){
$(document).ready(function() {

let formatField = $('#field-format');
if ( formatField.length > 0 ){

$(formatField).select2({});
$(formatField).parent()
.children('#s2id_field-format')
.addClass('conrtol-medium')
.removeClass('form-control')
.css({'display': 'block'});

}

let urlField = $('#field-image-url');
let uploadField = $('#field-image-upload');
// TODO: onchange above fields to clear the select2 field and call guess_resource_format endpoint

});
});
7 changes: 7 additions & 0 deletions ckanext/canada/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,13 @@ def before_map(self, map):
controller='ckanext.canada.controller:CanadaDatastoreController',
action='delete_datastore_table',
)
map.connect(
'/api{ver:/3|}/util/guess_resource_format',
ver='/3',
action='guess_resource_format',
controller='ckanext.canada.controller:CanadaApiController',
conditions={'method':['POST']},
)

return map

Expand Down
5 changes: 1 addition & 4 deletions ckanext/canada/schemas/presets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3224,12 +3224,9 @@ presets:
en: "eg. CSV, XML or JSON"
fr: "par exemple CSV, XML ou JSON"
validators: canada_guess_resource_format scheming_required clean_format unicode_safe canada_non_related_required canada_resource_format_replacements scheming_choices
form_attrs:
data-module: "autocomplete"
data-module-source: "/api/2/util/resource/format_autocomplete?incomplete=?"
required: true
form_panel: resource
form_snippet: select2.html
form_snippet: select.html
choices:
- value: AAC
mimetype: audio/mp4
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@
{% endif %}
{% endblock %}

{% block scripts %}
<script type="text/javascript" src="{{ h.url_for_static('/registry_resource_edit.js') }}" ></script>
{{ super() }}
{% endblock %}

{% block custom_styles %}
{{ super() }}
<link rel="stylesheet" href="{{ h.url_for_static('base/vendor/select2/select2.css') }}" />
<link rel="stylesheet" href="{{ h.url_for_static('base/vendor/select2/select2-bootstrap.css') }}" />
{% endblock %}
{% endblock %}

This file was deleted.

39 changes: 13 additions & 26 deletions ckanext/canada/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@
import unicodedata

from six import text_type
from six.moves.urllib.parse import urlparse
import mimetypes

from pylons.i18n import _
from ckan.lib.navl.validators import StopOnError
from ckan.authz import is_sysadmin
from ckan import model

from ckanext.canada.helpers import may_publish_datasets
from ckanext.canada.helpers import may_publish_datasets, canada_guess_mimetype
import geojson
from geomet import wkt
import json
Expand Down Expand Up @@ -396,26 +394,6 @@ def canada_resource_format_replacements(value, context):
return value


def _canada_guess_mimetype(key, data):
url = data.get(key[:-1] + ('url',), '')
if not url:
return

mimetype, encoding = mimetypes.guess_type(url)
if mimetype:
data[key] = mimetype
else:
# if we cannot guess the mimetype, check if
# it is an actual web address
# and we can set the mimetype to HTML.
# Uploaded files have only the filename as url,
# so check scheme to determine if it's
# an actual web address
parsed = urlparse(url)
if parsed.scheme:
data[key] = 'HTML'


def canada_guess_resource_format(key, data, errors, context):
"""
Guesses the resource format based on the url if missing.
Expand All @@ -427,16 +405,25 @@ def canada_guess_resource_format(key, data, errors, context):
# we will guess all url types, unlike Core
# which only checks uploaded files.
if not value or value is missing:
_canada_guess_mimetype(key, data)
url = data.get(key[:-1] + ('url',), '')
if not url:
return
mimetype = canada_guess_mimetype(url)
if mimetype:
data[key] = mimetype

# if there is a resource id, then it is an update.
# we can check if the url field value has changed.
resource_id = data.get(key[:-1] + ('id',))
if resource_id:
old_url = context.get('old_resource_url', None)
new_url = data.get(key[:-1] + ('url',), '')
if old_url and old_url != new_url:
_canada_guess_mimetype(key, data)
if not new_url:
return
if old_url != new_url:
mimetype = canada_guess_mimetype(new_url)
if mimetype:
data[key] = mimetype


def canada_resource_schema_validator(value, context):
Expand Down

0 comments on commit 84b82c6

Please sign in to comment.