[TikiWiki-commits] [Git][tikiwiki/tiki][28.x] [BP][FIX] Skip parameter filtering for plugin aliases to preserve user arguments

"Baraka Kinywa \(@bkinywa24\) via TikiWiki-cvs" <[email protected]>
Newsgroups gmane.comp.cms.tiki.cvs
Message-ID <68d8422941719_2ce1a498428135@gitlab-sidekiq-low-urgency-cpu-bound-v2-5cc58485fb-r729b.mail>

Baraka Kinywa pushed to branch 28.x at Tiki Wiki CMS Groupware / Tiki


Commits:
0edf7dab by Aksanti Bahiga at 2025-09-27T22:52:50+03:00
[BP][FIX] Skip parameter filtering for plugin aliases to preserve user arguments
---
* [BP][FIX] Skip parameter filtering for plugin aliases to preserve user arguments
---
* [FIX] Skip parameter filtering for plugin aliases to preserve user arguments
---
* [FIX] Add validation

* [FIX] Add validation

* [FIX] Skip parameter filtering for plugin aliases to preserve user arguments

See merge request tikiwiki/tiki!8366

See merge request tikiwiki/tiki!8657

See merge request tikiwiki/tiki!8668

- - - - -


2 changed files:

- lib/jquery_tiki/tiki-admin.js
- templates/admin/include_textarea.tpl


Changes:

=====================================
lib/jquery_tiki/tiki-admin.js
=====================================
@@ -77,7 +77,7 @@
         $(".add-param", $pluginAliasAdmin).on("click", function () {
             var $fieldset = $(this).closest("fieldset");
             // for composed args/params (fieldset) the template comes after the one for a new param,
-                // so we need closestDescendent, not :first
+            // so we need closestDescendent, not :first
             var $template = $fieldset.closestDescendent(".param.d-none");
             // If no proper template found, use the first visible param as fallback
             if ($template.length === 0) {
@@ -86,32 +86,40 @@
             }
             var $clone = $template.clone(true),
                 index = $fieldset.find(".param:visible").length;
-            $clone
-                .find("input")
-                .each(function () {
-                    const $input = $(this);
-                    const name = $input.attr("name");
-                    if (name && name.includes("__NEW__")) {
-                        const newName = name.replace("__NEW__", index);
-                        $input.attr("name", newName);
-                    } else if (name) {
-                        // For fallback cloning, update the index in existing names
-                        const newName = name.replace(/\[(\d+)\]/, `[${index}]`);
-                        $input.attr("name", newName);
-                    }
-                    $input.val("");
-                });
-
+            $clone.find("input").each(function () {
+                const $input = $(this);
+                const name = $input.attr("name");
+                const id = $input.attr("id");
+                // Update id if present
+                if (id && id.includes("__NEW__")) {
+                    const newId = id.replace("__NEW__", index);
+                    $input.attr("id", newId);
+                } else if (id) {
+                    // For fallback cloning, update the index in existing ids
+                    const newId = id.replace(/\[(\d+)\]/g, `[${index}]`);
+                    $input.attr("id", newId);
+                }
+                // Update name if present
+                if (name && name.includes("__NEW__")) {
+                    const newName = name.replace("__NEW__", index);
+                    $input.attr("name", newName);
+                } else if (name) {
+                    // For fallback cloning, update the index in existing names
+                    const newName = name.replace(/\[(\d+)\]/g, `[${index}]`);
+                    $input.attr("name", newName);
+                }
+                $input.val("");
+                if($input.data("required")){
+                    $input.attr("required", true);
+                }
+            });
             $clone.find(".d-none").addBack().removeClass("d-none");
 
             const plugin = $("#implementation").data("plugin");
 
             if (plugin) {
-                // get the param names
-                const params = $.map(plugin.params, function (element, index) {
-                    return index;
-                });
-
+                    const params = Object.keys
+                    (plugin.params || {});
                 if (window.elementPlus?.autocomplete) {
                     // get the input element
                     const inputElement = $clone.find("input.sparam-default");
@@ -160,12 +168,58 @@
                     });
                 }
             }
-
-            $template.parent().append($clone); //  .tiki_popover() doesn't work as the title has been removeed on page
-            // load... FIXME?;
+            // Attach validation to the new field added
+            $clone.find(".sparam-name").each(function () {
+                attachValidation($(this));
+            });
 
             return false;
         });
+       // Custom validation: each sparam must have documentation
+        $.validator.addMethod("hasAssociatedDocumentation", function (value, element) {
+            const paramName = value.trim(); // use the field value directly
+            if (!paramName) return true;
+            // Look for any doc input whose value matches the param name
+            const documentationField = $(`#pluginalias_doc input`).filter(function () {
+                return $(this).val().trim() === paramName;
+            });
+            return documentationField.length > 0;
+        }, "* This argument must have an associated documentation.");
+
+        var $pluginAliasForm = $pluginAliasAdmin.closest('form.admin');
+        // Adding validation with jquery validate
+        $pluginAliasForm.validate({
+            errorClass: "invalid-feedback",
+        });
+
+        // Helper to attach validation to a field
+        function attachValidation($field) {
+            $field.rules("add", {
+                hasAssociatedDocumentation: true
+            });
+        }
+
+        // On page load, attach to existing sparam-name fields
+        $pluginAliasForm.find(".sparam-name").each(function() {
+            attachValidation($(this));
+        });
+
+        // Handle submit properly
+        $pluginAliasForm.on("submit", function (e) {
+            if (!$pluginAliasForm.valid()) {
+                e.preventDefault(); // block submit if invalid
+                // add a scroll to the first error
+                const $firstError = $pluginAliasForm.find(".invalid-feedback").first();
+                if ($firstError.length) {
+                    $("html, body").animate(
+                        {
+                            scrollTop: $firstError.offset().top - 100,
+                        },
+                        500
+                    );
+                }
+            }
+        });
 
         $($pluginAliasAdmin).on("click", ".delete-param", function (e) {
             e.preventDefault();
@@ -173,17 +227,6 @@
         });
 
         setTimeout(function () {
-            /*
-            if (jqueryTiki.validate) {
-                $pluginAliasAdmin.closest("form").validate({
-                    rules: {
-                        plugin_alias: "required",
-                        implementation: "required"
-                    }
-                });
-            }
-*/
-
             $("#plugin_alias").on("change", function () {
                 const $this = $(this),
                     $pluginName = $("#plugin_name");
@@ -435,13 +478,16 @@
         updateVisible();
     });
 
-    $(".input-pref_filters").on("change", function () {
-        const pref_filters_values = $("input[name='pref_filters[]']:checked")
-            .map(function () {
+    $('.input-pref_filters').on("change", function () {
+        const pref_filters_values = $("input[name='pref_filters[]']:checked").map(function () {
                 return $(this).val();
-            })
-            .get();
-        $("#preffilter-loader").removeClass("d-none");
+            }).get();
+
+        // Synchronize page-level toggle with navbar checkboxes
+         const advancedChecked = pref_filters_values.includes('advanced');
+        $('.preffilter-toggle').prop("checked", advancedChecked);
+
+        $("#preffilter-loader").removeClass('d-none');
         $.ajax("tiki-admin.php", {
             type: "POST",
             data: { pref_filters: pref_filters_values },
@@ -462,3 +508,4 @@
     });
 
 })(jQuery);
+


=====================================
templates/admin/include_textarea.tpl
=====================================
@@ -431,7 +431,7 @@
                                 {elseif $token eq '__NEW__'}
                                     <div class="mb-3 row d-none param">
                                         <div class="col-sm-6">
-                                            <input class="form-control sparam-name" type="text" name="sparams[__NEW__][token]" value="" placeholder="{tr}Name{/tr}">
+                                            <input class="form-control sparam-name d-none" type="text" name="sparams[__NEW__][token]" value="" placeholder="{tr}Name{/tr}" data-required="true">
                                         </div>
                                         <div class="col-sm-5">
                                             <input class="form-control sparam-default" type="text" name="sparams[__NEW__][default]" value="" placeholder="{tr}Default Value{/tr}">
@@ -458,7 +458,7 @@
                                             {tr}Parameter{/tr}
                                         </label>
                                         <div class="col-sm-7">
-                                            <input class="form-control" type="text" name="input[{$token|escape}][token]" id="input[{$token|escape}][token]" value="{if $token neq '__NEW__'}{$token|escape}{/if}">
+                                            <input class="form-control {if $token eq '__NEW__'} d-none{/if}" type="text" name="input[{$token|escape}][token]" id="input[{$token|escape}][token]" value="{if $token neq '__NEW__'}{$token|escape}{/if}" data-required="true">
                                         </div>
                                         <div class="col-sm-1">
                                             {icon name='delete' class='text-danger delete-param tips btn btn-link' title="{tr}Delete this parameter's documentation{/tr}"}
@@ -469,7 +469,7 @@
                                             {tr}Name{/tr}
                                         </label>
                                         <div class="col-sm-8">
-                                            <input class="form-control" type="text" name="input[{$token|escape}][name]" id="input[{$token|escape}][name]" value="{$detail.name|escape}">
+                                            <input class="form-control {if $token eq '__NEW__'} d-none{/if}" type="text" name="input[{$token|escape}][name]" id="input[{$token|escape}][name]" value="{$detail.name|escape}" data-required="true">
                                         </div>
                                     </div>
                                     <div class="mb-3 row">
@@ -543,7 +543,7 @@
                                                 {tr}Parameter{/tr}
                                             </label>
                                             <div class="col-sm-5">
-                                                <input class="form-control {if $token eq '__NEW__'} d-none{/if}" type="text" name="bodyparam[{$token|escape}][token]" id="bodyparam[{$token|escape}][token]" value="{if $token neq '__NEW__'}{$token|escape}{/if}">
+                                                <input class="form-control {if $token eq '__NEW__'} d-none{/if}" type="text" name="bodyparam[{$token|escape}][token]" id="bodyparam[{$token|escape}][token]" value="{if $token neq '__NEW__'}{$token|escape}{/if}" data-required="true">
                                             </div>
                                             <div class="col-sm-1">
                                                 {icon name='delete' class='text-danger delete-param tips btn btn-link' title="{tr}Delete this body parameter{/tr}"}



View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/0edf7dab30fa0a3cfe53d71f5c50520738a1db87

-- 
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/0edf7dab30fa0a3cfe53d71f5c50520738a1db87
You're receiving this email because of your account on gitlab.com.

_______________________________________________
TikiWiki-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-cvs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.