+
${esc(suggestionData.label)}
+ ${suggestionData.is_error ? `
+
+
+ The suggestion could not be generated correctly:
+
` : ''}
+ ${suggestionData.is_select && !suggestionData.is_valid && !suggestionData.is_error ? `
+
+
+ This value is not a valid choice for this field.
+
` : ''}
+
${esc(suggestionData.value)}
+ ${!suggestionData.is_error ? `
+
+
+
+
+
+ ${esc(suggestionData.formula)}
+
` : ''}
+
+
`;
+ $popoverDiv.html(popoverContentHtml);
+ this._attachActionHandlers($popoverDiv, suggestionData.field_name);
+ },
+ _attachBaseEventHandlers: function(el, $popoverDiv, fieldName) {
+ var self = this;
+ $(el).on('click', function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ if ($popoverDiv.is(':empty') && !$popoverDiv.html().trim()) { return; } // Check if truly empty
+ $('.custom-suggestion-popover').not($popoverDiv).hide();
+ var buttonPos = $(el).offset();
+ var windowWidth = $(window).width();
+ var popoverCalculatedWidth = Math.min(380, windowWidth - 40);
+ var leftPos = buttonPos.left;
+ if (buttonPos.left + popoverCalculatedWidth > windowWidth - 20) {
+ leftPos = Math.max(20, windowWidth - popoverCalculatedWidth - 20);
+ }
+ var topPos = buttonPos.top + $(el).outerHeight() + 10;
+ if (topPos < $(window).scrollTop()){ topPos = $(window).scrollTop() + 10; }
+ $popoverDiv.css({ position: 'absolute', top: topPos, left: leftPos, width: popoverCalculatedWidth + 'px', zIndex: 1050 }).toggle();
+ });
+ },
+ _attachActionHandlers: function($popoverDiv, fieldName) {
+ var self = this;
+ $(document).off('click.schemingSuggestionsGlobal.' + fieldName).on('click.schemingSuggestionsGlobal.' + fieldName, function(e) {
+ if (!$(e.target).closest($popoverDiv).length && !$(e.target).closest('button[data-field-name="'+fieldName+'"]').length) {
+ $popoverDiv.hide();
+ }
+ });
+ $popoverDiv.off('click.formulaToggle').on('click.formulaToggle', '.formula-toggle-btn', function(e) {
+ e.preventDefault(); e.stopPropagation();
+ var $formulaSection = $(this).closest('.suggestion-popover-content').find('.suggestion-formula');
+ var $toggleIcon = $(this).find('.formula-toggle-icon');
+ var $toggleText = $(this).find('.formula-toggle-text');
+ $formulaSection.slideToggle(200, function() {
+ if ($formulaSection.is(':visible')) {
+ $toggleIcon.html('▲'); $toggleText.text('Hide formula'); $(this).closest('.formula-toggle').addClass('formula-toggle-active');
+ } else {
+ $toggleIcon.html('▼'); $toggleText.text('Show formula'); $(this).closest('.formula-toggle').removeClass('formula-toggle-active');
+ }
+ });
+ });
+ $popoverDiv.off('click.copyFormula').on('click.copyFormula', '.copy-formula-btn', function(e) {
+ e.preventDefault(); e.stopPropagation();
+ var formula = $(this).data('formula');
+ var $copyBtn = $(this);
+ navigator.clipboard.writeText(formula).then(function() {
+ var $iconContainer = $copyBtn.find('svg').parent();
+ var originalIcon = $iconContainer.html();
+ $iconContainer.html('
{%- if is_preformulated -%}
- Automated field: This field is automatically populated and cannot be edited manually.
+ Automated field: This field is automatically populated.
{%- endif -%}
{%- snippet 'scheming/form_snippets/help_text.html', field=field -%}
diff --git a/ckanext/scheming/templates/scheming/form_snippets/text.html b/ckanext/scheming/templates/scheming/form_snippets/text.html
index faff95e54..92b8331bd 100644
--- a/ckanext/scheming/templates/scheming/form_snippets/text.html
+++ b/ckanext/scheming/templates/scheming/form_snippets/text.html
@@ -1,40 +1,54 @@
{% import 'macros/form.html' as form %}
{% include 'scheming/snippets/suggestions_asset.html' %}
+{# Check if this is a preformulated field (i.e., has a 'formula') #}
{% set is_preformulated = h.is_preformulated_field(field) %}
+{# Create a custom label with suggestion button(s) and icons #}
{% set suggestion = h.scheming_field_suggestion(field) %}
{% set label_text = h.scheming_language_text(field.label) %}
-{% set label_with_suggestion %}
-
{{ label_text }}
- {%- if suggestion -%}
- {%- snippet 'scheming/snippets/suggestion_button.html', field=field, data=data -%}
- {%- endif -%}
- {%- if is_preformulated -%}
-
-
-
- {%- endif -%}
+{% set label_with_extras %}
+
{{ label_text }}:
+ {%- if suggestion -%}
+ {%- snippet 'scheming/snippets/suggestion_button.html', field=field, data=data -%}
+ {%- endif -%}
+ {%- if is_preformulated -%}
+
+
+
+ {%- endif -%}
{% endset %}
+{% set field_classes = field.classes if 'classes' in field else ['control-medium'] %}
+
+{# Prepare attributes for the form macro #}
+{% set current_attrs = {} %}
+{% if supports_ai_suggestion %}
+ {% set _ = current_attrs.update({'data-field-supports-ai-suggestion': 'true'}) %}
+{% endif %}
+{% if is_preformulated %} {# is_preformulated means it has a 'formula' #}
+ {% set _ = current_attrs.update({'data-is-formula-field': 'true'}) %}
+{% endif %}
+{# Always add data-scheming-field-name for easier targeting by JS #}
+{% set _ = current_attrs.update({'data-scheming-field-name': field.field_name}) %}
+
+
{% call form.input(
field.field_name,
id='field-' + field.field_name,
- label=label_with_suggestion|safe,
+ label=label_with_extras|safe,
placeholder=h.scheming_language_text(field.form_placeholder),
value=data[field.field_name],
error=errors[field.field_name],
- classes=field.classes if 'classes' in field else ['control-medium'],
- attrs=dict({"class": "form-control"}, **(field.get('form_attrs', {}))),
+ classes=field_classes,
+ attrs=current_attrs,
is_required=h.scheming_field_required(field)
)
%}
">
-
+ data-field-name="{{ field.field_name }}"
+ data-field-schema="{{ field_schema_for_js_json_string|e }}"
+ style="display:none;" {# JS will .show() it #}
+ >
+
-{% endif %}
\ No newline at end of file
+{% endif %}
From 1ddfdf79f1558a6fe8c920a37af4db1679105a7e Mon Sep 17 00:00:00 2001
From: Mohammed Minhajuddin
Date: Wed, 28 May 2025 04:44:32 -0400
Subject: [PATCH 5/6] fix for the form_control class on text boxes
---
.../scheming/form_snippets/text.html | 19 +++----------------
1 file changed, 3 insertions(+), 16 deletions(-)
diff --git a/ckanext/scheming/templates/scheming/form_snippets/text.html b/ckanext/scheming/templates/scheming/form_snippets/text.html
index 92b8331bd..c78b75fe9 100644
--- a/ckanext/scheming/templates/scheming/form_snippets/text.html
+++ b/ckanext/scheming/templates/scheming/form_snippets/text.html
@@ -19,19 +19,6 @@
{%- endif -%}
{% endset %}
-{% set field_classes = field.classes if 'classes' in field else ['control-medium'] %}
-
-{# Prepare attributes for the form macro #}
-{% set current_attrs = {} %}
-{% if supports_ai_suggestion %}
- {% set _ = current_attrs.update({'data-field-supports-ai-suggestion': 'true'}) %}
-{% endif %}
-{% if is_preformulated %} {# is_preformulated means it has a 'formula' #}
- {% set _ = current_attrs.update({'data-is-formula-field': 'true'}) %}
-{% endif %}
-{# Always add data-scheming-field-name for easier targeting by JS #}
-{% set _ = current_attrs.update({'data-scheming-field-name': field.field_name}) %}
-
{% call form.input(
field.field_name,
@@ -40,8 +27,8 @@
placeholder=h.scheming_language_text(field.form_placeholder),
value=data[field.field_name],
error=errors[field.field_name],
- classes=field_classes,
- attrs=current_attrs,
+ classes=field.classes if 'classes' in field else ['control-medium'],
+ attrs=dict({"class": "form-control"}, **(field.get('form_attrs', {}))),
is_required=h.scheming_field_required(field)
)
%}
@@ -53,4 +40,4 @@
{%- endif -%}
{%- snippet 'scheming/form_snippets/help_text.html', field=field -%}
-{% endcall %}
\ No newline at end of file
+{% endcall %}
From 497771f481b942f259cd9135e6bace0044e6ac90 Mon Sep 17 00:00:00 2001
From: Mohammed Minhajuddin