[TikiWiki-commits] [Git][tikiwiki/tiki][master] [FIX][UX] Tiki Tracker File Field: Improved file modal search refresh, filtering, and selection UX

"luci \(@luciash\) via TikiWiki-cvs" <[email protected]>
Newsgroups gmane.comp.cms.tiki.cvs
Message-ID <68e6c12f5b921_2ce02cc808e5@gitlab-sidekiq-low-urgency-cpu-bound-v2-54547678f4-5mjkg.mail>

luci pushed to branch master at Tiki Wiki CMS Groupware / Tiki


Commits:
90d496bf by Doddy MATABARO at 2025-10-08T19:45:10+00:00
[FIX][UX] Tiki Tracker File Field: Improved file modal search refresh, filtering, and selection UX
---
* [FIX][UX] File gallery list: remove UL left padding so divider aligns with container; add horizontal padding on rows

* [ENH][UX] Replaced 'Current Selection' UI with inline checkboxes and select all checkbox

* [FIX][UX] Tiki Tracker File Field: Improved file modal search refresh, filtering, and selection UX

See merge request tikiwiki/tiki!7613

- - - - -


4 changed files:

- lib/core/Services/File/Controller.php
- lib/jquery_tiki/files.js
- templates/file/browse.tpl
- templates/file/list_gallery.tpl


Changes:

=====================================
lib/core/Services/File/Controller.php
=====================================
@@ -410,7 +410,7 @@ class Services_File_Controller
         ]);
 
         if ($search = $input->search->text()) {
-            $query->filterContent($search);
+            $query->filterContent($search, 'title,filename');
         }
 
         if ($typeFilter = $input->type->text()) {


=====================================
lib/jquery_tiki/files.js
=====================================
@@ -520,65 +520,6 @@
         });
     }
 
-    function browserRemoveFile(link)
-    {
-        var list = $(link).closest('ul');
-        $(link).closest('li').remove();
-
-        list.closest('.file-browser').trigger('selection-update');
-    }
-
-    function browserAddFile(link)
-    {
-        var content = $(link).closest('.media-body').clone(true),
-            icon = $(link).closest('.media, .panel').find('.media-object, .panel-body a').children('img').clone(true).width('16px'),
-            nav = $(link).closest('.file-browser').find('.selection ul'),
-            item = $('<li>'),
-            a = $('<a>').text($(link).text()),
-            id = $(link).data('object'),
-            limit = nav.closest('form').data('limit'),
-            current = nav.find('input[type=hidden]').filter(function () {
-                return parseInt($(this).val(), 10) === id;
-            });
-
-        if (current.length > 0) {
-            // Already in the list
-            browserRemoveFile(current[0]);
-            return;
-        }
-
-        if (limit === 1) {
-            nav.empty();
-        } else if (limit && nav.children('li').length >= limit) {
-            alert(nav.closest('form').data('limit-reached-message'));
-            return;
-        }
-
-        a
-            .prepend(' ')
-            .prepend(icon);
-        item.append(a);
-        nav.append(item);
-
-        item.append($('<input type="hidden" name="file[]">')
-            .attr('value', id));
-
-        nav.closest('.file-browser').trigger('selection-update');
-    }
-
-    $(document).on('selection-update', '.file-browser', function (e) {
-        var selection = $('.selection input[type=hidden]', this).map(function () {
-            return parseInt($(this).val(), 10);
-        });
-
-        $('.gallery-list .media-heading a, .gallery-list .panel-body a', this).each(function () {
-            var id = $(this).data('object');
-            $(this).closest('.media').toggleClass('bg-info', -1 !== $.inArray(id, selection));
-            $(this).closest('.panel').toggleClass('panel-info', -1 !== $.inArray(id, selection));
-        });
-        $('.selection', this).toggleClass("invisible", selection.length === 0);
-    });
-
     $(document).on('click', '.file-browser .gallery-list .pagination a', function (e) {
         e.preventDefault();
         $(this).closest('.modal').animate({ scrollTop: 0 }, 'slow');
@@ -586,32 +527,27 @@
             .tikiModal(tr('Loading...'))
             .load($(this).attr('href'), function () {
                 $(this).tikiModal('');
-                $(this).closest('.file-browser').trigger('selection-update');
             });
     });
 
-    $(document).on('click', '.file-browser .gallery-list .media-heading a, .file-browser .gallery-list .panel-body a', function (e) {
-        e.preventDefault();
-        e.stopPropagation();
-        browserAddFile(this);
-    });
-    $(document).on('click', '.file-browser .gallery-list .media, .file-browser .gallery-list .panel', function (e) {
-        e.preventDefault();
-        $('.media-heading a, .panel-body a', this).trigger("click");
-    });
-
-    $(document).on('click', '.file-browser .selection a', function (e) {
-        e.preventDefault();
-        browserRemoveFile(this);
-    });
-
-    $(document).on('submit', '.file-browser .form-inline', function (e) {
+    $(document).on('submit', '.file-browser form.no-ajax[method="get"]', function (e) {
         e.preventDefault();
-        $(this).closest('.file-browser').find('.gallery-list')
-            .tikiModal(tr('Loading...'))
-            .load($(this).attr('action'), $(this).serialize(), function () {
-                $(this).tikiModal('');
-                $(this).closest('.file-browser').trigger('selection-update');
+        const $form = $(this);
+        const $fileBrowser = $form.closest('.file-browser');
+        const $galleryList = $fileBrowser.find('.gallery-list');
+        const url = $form.attr('action');
+        const data = $form.serialize();
+
+        $galleryList.tikiModal(tr('Loading...'));
+
+        $.get(url, data)
+            .done(function (response) {
+                $galleryList.html(response);
+                $galleryList.tikiModal('');
+            })
+            .fail(function () {
+                $galleryList.html('<div class="alert alert-danger">' + tr('Error loading results.') + '</div>');
+                $galleryList.tikiModal('');
             });
     });
 
@@ -629,7 +565,6 @@
                                 .attr('value', file.fileId))
                             .appendTo($list);
 
-                        $list.closest('.file-browser').trigger('selection-update');
                     });
                     $.closeModal();
                 }
@@ -678,6 +613,26 @@
         });
     });
 
+    $(document).on('click', '.file-browser .gallery-list .pagination a', function (e) {
+        e.preventDefault();
+        $('#select-all-files').prop('checked', false);
+        $(this).closest('.modal').animate({ scrollTop: 0 }, 'slow');
+        $(this).closest('.gallery-list')
+            .tikiModal(tr('Loading...'))
+            .load($(this).attr('href'), function () {
+                $(this).tikiModal('');
+            });
+    });
+
+    $(document).on('click', '.file-title-toggle', function (e) {
+        e.preventDefault();
+        const targetId = $(this).data('checkbox-id');
+        const checkbox = document.getElementById(targetId);
+        if (checkbox) {
+            checkbox.checked = !checkbox.checked;
+        }
+    });
+
 })(jQuery);
 
 function updateFileName(inputFile) {


=====================================
templates/file/browse.tpl
=====================================
@@ -6,48 +6,47 @@
 
 {block name="content"}
     <div class="row file-browser">
-        <div class="col-md-9">
-            <form class="d-flex flex-row flex-wrap align-items-center no-ajax" method="get" action="{service controller=file action=$list_view plain=1}">
-                <div class="mb-3 row">
-                    <label class="form-label sr-only" for="search-field">{tr}Search{/tr}</label>
-                    <input class="form-control" name="search" type="search" id="search-field" placeholder="{tr}Search...{/tr}"/>
+        <div class="col-md-12">
+            <form class="row g-2 align-items-center no-ajax" method="get" action="{service controller=file action=$list_view plain=1}">
+                <div class="col">
+                    <input class="form-control " name="search" type="search" id="search-field" placeholder="{tr}Search...{/tr}"/>
                     <input type="hidden" name="galleryId" value="{$galleryId|escape}"/>
+                    <input type="hidden" name="limit" value="{$limit|default:20}">
                     <input type="hidden" name="type" value="{$typeFilter|escape}"/>
                 </div>
-                <button class="btn btn-info">{tr}Search{/tr}</button>
+                <div class="col-auto">
+                    <button class="btn btn-info" type="submit">{tr}Search{/tr}</button>
+                </div>
             </form>
-            <h4>{tr}Select files{/tr}</h4>
-            <div class="gallery-list">
-                {service_inline controller=file action=$list_view galleryId=$galleryId plain=1 type=$typeFilter}
+
+            <div class="d-flex justify-content-between align-items-center my-2">
+                <h4 class="mb-0">{tr}Select files{/tr}</h4>
+                <div>
+                    <input type="checkbox" id="select-all-files" class="form-check-input me-2"/>
+                    <label for="select-all-files" class="form-label mb-0">{tr}Select all{/tr}</label>
+                </div>
             </div>
-        </div>
-        <div class="col-md-3 selection hidden">
-            <form method="post" action="{service controller=file action=browse galleryId=$galleryId}" data-gallery-id="{$galleryId|escape}" data-limit="{$limit|escape}" data-limit-reached-message="{tr}Too many files selected. De-select some files before adding more.{/tr}">
-                <h4>{tr}Current Selection{/tr}</h4>
-                <ul class="nav nav-pills nav-stacked">
-                    {foreach $files as $file}
-                        <li>
-                            <a href="{$file.fileId|sefurl:'file'}" data-type="file" data-object="{$file.fileId|escape}">
-                                {$file.name|iconify:$file.type:$file.fileId}
-                                {$file.label|escape}
-                            </a>
-                            <input type="hidden" name="file[]" value="{$file.fileId|escape}"/>
-                        </li>
-                    {/foreach}
-                </ul>
-                <div class="form-text">
-                    {tr}Click to remove{/tr}
+
+            <form method="post" action="{service controller=file action=browse galleryId=$galleryId}">
+                <div class="gallery-list flex-grow-1 overflow-auto border" style="max-height: 60vh;">
+                    {service_inline controller=file action=$list_view galleryId=$galleryId plain=1 type=$typeFilter limit=$limit}
                 </div>
-                <div class="submit">
+
+                <div class="submit sticky-bottom bg-light py-3 mt-3">
                     {if $canUpload}
-                        <a class="btn btn-secondary upload-files custom-handling" href="{service controller=file action=uploader galleryId=$galleryId limit=$limit type=$typeFilter}">{tr}Upload Files{/tr}</a>
+                        <a class="btn btn-secondary upload-files custom-handling me-2" href="{service controller=file action=uploader galleryId=$galleryId limit=$limit type=$typeFilter}">
+                            {tr}Upload Files{/tr}
+                        </a>
                     {/if}
-                    <input type="submit" class="btn btn-primary" value="{tr}Select{/tr}">
+                    <input type="submit" class="btn btn-primary" value="{tr}Attach selected file(s){/tr}">
                 </div>
             </form>
         </div>
     </div>
+
     {jq}
-        $('.file-browser').trigger('selection-update');
+        $('#select-all-files').on('change', function () {
+            $('.gallery-list .file-select').prop('checked', this.checked).trigger('change');
+        });
     {/jq}
 {/block}


=====================================
templates/file/list_gallery.tpl
=====================================
@@ -5,28 +5,32 @@
 {/block}
 
 {block name="content"}
-    <ul class="media-list">
+    <ul class="media-list list-unstyled ps-0 mb-0">
         {foreach from=$results item=row}
-            <li class="d-flex">
+            <li class="d-flex align-items-start border-bottom py-2 px-2">
+                <div class="form-check mt-2 me-2">
+                    <input class="form-check-input file-select" type="checkbox" name="file[]" value="{$row.object_id|escape}" id="file-{$row.object_id}">
+                </div>
+
                 <div class="flex-shrink-0">
                     {if $row.filetype|truncate:6:'' eq 'image/'}
-                        <img src="{$row.object_id|sefurl:'thumbnail'}"/>
+                        <label for="file-{$row.object_id}">
+                            <img src="{$row.object_id|sefurl:'thumbnail'}" class="img-thumbnail" style="width: 64px; height: auto;" />
+                        </label>
                     {else}
                         {$row.filename|iconify:$row.filetype}
                     {/if}
                 </div>
-                <div class="flex-grow-1 ms-3">
-                    <h4 class="media-heading">{object_link type=$row.object_type id=$row.object_id}</h4>
-                    <div>
-                        {$row.filename|escape}
-                    </div>
-                    <div>
-                        {$row.description|escape}
-                    </div>
-                    <div class="small">
+
+                <div class="flex-grow-1 ms-3 file-click-toggle" data-target="file-{$row.object_id}">
+                    <h6 class="media-heading mb-1">{object_link type=$row.object_type id=$row.object_id}</h6>
+                    <div class="mb-1">{$row.filename|escape}</div>
+                    <div class="mb-1 text-muted small">{$row.description|escape}</div>
+                    <div class="small text-muted">
                         {tr _0=$row.modification_date|tiki_short_datetime}Last modification: %0{/tr}
                     </div>
                 </div>
+
             </li>
         {foreachelse}
             <li>



View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/90d496bfa01f00e97f12e9d4b7301bb75125d507

-- 
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/90d496bfa01f00e97f12e9d4b7301bb75125d507
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.