From d43207d9a01ecf0af62097571ca6d7987902bde1 Mon Sep 17 00:00:00 2001 From: Ian Ward Date: Sun, 30 Jun 2024 20:47:43 -0400 Subject: [PATCH 1/2] dataset completeness example --- ckanext/scheming/ckan_formpages.yaml | 7 +++++++ ckanext/scheming/validation.py | 29 ++++++++++++++++++++-------- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/ckanext/scheming/ckan_formpages.yaml b/ckanext/scheming/ckan_formpages.yaml index 4ec88909..c2ace29c 100644 --- a/ckanext/scheming/ckan_formpages.yaml +++ b/ckanext/scheming/ckan_formpages.yaml @@ -3,6 +3,7 @@ dataset_type: formpages about: The default CKAN dataset schema with form split across multiple pages about_url: http://github.com/ckan/ckanext-scheming +draft_fields_required: false dataset_fields: @@ -54,6 +55,8 @@ dataset_fields: label: Version validators: ignore_missing unicode_safe package_version_validator form_placeholder: '1.0' + required: true + validators: scheming_required unicode_safe package_version_validator - start_form_page: title: Contact Info @@ -63,6 +66,8 @@ dataset_fields: label: Author form_placeholder: Joe Bloggs display_property: dc:creator + required: true + validators: scheming_required unicode_safe - field_name: author_email label: Author Email @@ -95,6 +100,8 @@ resource_fields: - field_name: name label: Name form_placeholder: eg. January 2011 Gold Prices + required: true + validators: scheming_required unicode_safe - field_name: description label: Description diff --git a/ckanext/scheming/validation.py b/ckanext/scheming/validation.py index d91dd13d..e8cb006b 100644 --- a/ckanext/scheming/validation.py +++ b/ckanext/scheming/validation.py @@ -22,10 +22,6 @@ import ckanext.scheming.helpers as sh from ckanext.scheming.errors import SchemingException -OneOf = get_validator('OneOf') -ignore_missing = get_validator('ignore_missing') -not_empty = get_validator('not_empty') - all_validators = {} @@ -65,6 +61,7 @@ def scheming_choices(field, schema): """ Require that one of the field choices values is passed. """ + OneOf = get_validator('OneOf') if 'choices' in field: return OneOf([c['value'] for c in field['choices']]) @@ -84,11 +81,27 @@ def validator(value): @register_validator def scheming_required(field, schema): """ - not_empty if field['required'] else ignore_missing + return a validator based on field['required'] + and schema['draft_fields_required'] setting """ - if field.get('required'): - return not_empty - return ignore_missing + if not field.get('required'): + return get_validator('ignore_missing') + if not schema.get('draft_fields_required', True): + return get_validator('scheming_draft_fields_not_required') + return get_validator('not_empty') + + +@register_validator +def scheming_draft_fields_not_required(key, data, errors, context): + """ + call ignore_missing if state is draft, otherwise not_empty + """ + state = data.get(('state',), '') + if state.startswith('draft'): + v = get_validator('ignore_missing') + else: + v = get_validator('not_empty') + v(key, data, errors, context) @scheming_validator From e83cea9249e78c425eda485724ac58d44311a045 Mon Sep 17 00:00:00 2001 From: Ian Ward Date: Sun, 24 Nov 2024 20:54:15 -0500 Subject: [PATCH 2/2] scheming_missing_required_fields helper and error icons --- ckanext/scheming/ckan_formpages.yaml | 2 ++ ckanext/scheming/helpers.py | 18 ++++++++++++++++++ ckanext/scheming/plugins.py | 6 ++++++ .../package/snippets/package_form.html | 11 +++++++++++ .../package/snippets/resource_form.html | 11 +++++++++++ 5 files changed, 48 insertions(+) diff --git a/ckanext/scheming/ckan_formpages.yaml b/ckanext/scheming/ckan_formpages.yaml index c2ace29c..76622f1a 100644 --- a/ckanext/scheming/ckan_formpages.yaml +++ b/ckanext/scheming/ckan_formpages.yaml @@ -25,6 +25,8 @@ dataset_fields: label: Description form_snippet: markdown.html form_placeholder: eg. Some useful notes about the data + required: true + validators: scheming_required unicode_safe - field_name: owner_org label: Organization diff --git a/ckanext/scheming/helpers.py b/ckanext/scheming/helpers.py index 25ba3969..274e85f9 100644 --- a/ckanext/scheming/helpers.py +++ b/ckanext/scheming/helpers.py @@ -445,3 +445,21 @@ def scheming_flatten_subfield(subfield, data): for k in record: flat[prefix + k] = record[k] return flat + + +@helper +def scheming_missing_required_fields(pages, data=None, package_id=None): + if package_id: + try: + data = LocalCKAN().action.package_show(id=package_id) + except (NotFound, NotAuthorized): + pass + if data is None: + data = {} + missing = [] + for p in pages: + missing.append([ + f['field_name'] for f in p['fields'] + if f.get('required') and not data.get(f['field_name']) + ]) + return missing diff --git a/ckanext/scheming/plugins.py b/ckanext/scheming/plugins.py index 0980a684..23c21948 100644 --- a/ckanext/scheming/plugins.py +++ b/ckanext/scheming/plugins.py @@ -223,6 +223,12 @@ def resource_form(self): def package_types(self): return list(self._schemas) + def resource_validation_dependencies(self, package_type): + # Compatibility with https://github.com/ckan/ckan/pull/8421 + schema = self._schemas.get(package_type, {}) + dfr = schema.get('draft_fields_required', True) + return [] if dfr else ['state'] + def validate(self, context, data_dict, schema, action): """ Validate and convert for package_create, package_update and diff --git a/ckanext/scheming/templates/scheming/package/snippets/package_form.html b/ckanext/scheming/templates/scheming/package/snippets/package_form.html index 6d96ce03..ff5ed4e6 100644 --- a/ckanext/scheming/templates/scheming/package/snippets/package_form.html +++ b/ckanext/scheming/templates/scheming/package/snippets/package_form.html @@ -4,6 +4,7 @@ {%- set pages = h.scheming_get_dataset_form_pages(dataset_type) -%} {%- if pages -%} {%- set active_page = data.get('_form_page', 1) | int -%} + {%- set draft_missing_required = h.scheming_missing_required_fields(pages, data) -%}
    {%- for p in pages -%}
  1. {{ h.scheming_language_text(p.title) }}{% else %}{{ h.scheming_language_text(p.title) }}{% endif %} + {%- set mreq = draft_missing_required[loop.index0] -%} + {% if mreq %} + + + + {% endif %}
  2. {%- endfor -%} diff --git a/ckanext/scheming/templates/scheming/package/snippets/resource_form.html b/ckanext/scheming/templates/scheming/package/snippets/resource_form.html index 88d231b0..f517844d 100644 --- a/ckanext/scheming/templates/scheming/package/snippets/resource_form.html +++ b/ckanext/scheming/templates/scheming/package/snippets/resource_form.html @@ -2,6 +2,7 @@ {% block stages %} {%- set pages = h.scheming_get_dataset_form_pages(dataset_type) -%} + {%- set draft_missing_required = h.scheming_missing_required_fields(pages, package_id=pkg_name) -%} {%- if pages and stage -%}
      {%- for p in pages -%} @@ -14,6 +15,16 @@ id=pkg_name, page=loop.index) }}">{{ h.scheming_language_text(p.title) }} + {%- set mreq = draft_missing_required[loop.index0] -%} + {% if mreq %} + + + + {% endif %} {%- endfor -%}