From 2b189c7ce983dc2ce7cccc26a7fdb703706a79e2 Mon Sep 17 00:00:00 2001 From: Santosh Prasad Sah Date: Wed, 29 Jan 2025 15:25:30 +0545 Subject: [PATCH 1/9] chore: add @rails/request.js --- package.json | 1 + yarn.lock | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/package.json b/package.json index 4fefd2159..e736e9e0f 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "@hotwired/stimulus": "^3.2.2", "@hotwired/turbo-rails": "^8.0.13", "@rails/activestorage": "^6.1.710", + "@rails/request.js": "^0.0.11", "@stimulus-components/clipboard": "^5.0.0", "@stimulus-components/password-visibility": "^3.0.0", "@tailwindcss/container-queries": "^0.1.1", diff --git a/yarn.lock b/yarn.lock index 833d5caa7..b96e64830 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1739,6 +1739,11 @@ dependencies: spark-md5 "^3.0.0" +"@rails/request.js@^0.0.11": + version "0.0.11" + resolved "https://registry.yarnpkg.com/@rails/request.js/-/request.js-0.0.11.tgz#4d9be25a49d97911c64ccd0f00b79d57fca4c3b4" + integrity sha512-2U3uYS0kbljt+pAstN+LIlZOl7xmOKig5N6FrvtUWO1wq0zR1Hf90fHfD2SYiyV8yH1nyKpoTmbLqWT0xe1zDg== + "@remirror/core-constants@3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@remirror/core-constants/-/core-constants-3.0.0.tgz#96fdb89d25c62e7b6a5d08caf0ce5114370e3b8f" From 5c0798e97df27d57e8641bb90d6ce9ab70c6a830 Mon Sep 17 00:00:00 2001 From: Santosh Prasad Sah Date: Wed, 29 Jan 2025 15:26:48 +0545 Subject: [PATCH 2/9] feat: add resource search controller --- .../views/resource_index_component.html.erb | 11 ++++++++- app/javascript/js/controllers.js | 2 ++ .../controllers/resource_search_controller.js | 24 +++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 app/javascript/js/controllers/resource_search_controller.js diff --git a/app/components/avo/views/resource_index_component.html.erb b/app/components/avo/views/resource_index_component.html.erb index 9cbe4aa5d..cab3c9e7c 100644 --- a/app/components/avo/views/resource_index_component.html.erb +++ b/app/components/avo/views/resource_index_component.html.erb @@ -36,7 +36,16 @@
">
<% if show_search_input %> - <%= render partial: "avo/partials/resource_search", locals: {resource: @resource.route_key, via_reflection: via_reflection} %> + <%#= render partial: "avo/partials/resource_search", locals: {resource: @resource.route_key, via_reflection: via_reflection} %> + + <% else %> <%# Offset for the space-y-2 property when the search is missing %>
diff --git a/app/javascript/js/controllers.js b/app/javascript/js/controllers.js index 3876d7104..907bcafde 100644 --- a/app/javascript/js/controllers.js +++ b/app/javascript/js/controllers.js @@ -35,6 +35,7 @@ import RecordSelectorController from './controllers/record_selector_controller' import ReloadBelongsToFieldController from './controllers/fields/reload_belongs_to_field_controller' import ResourceEditController from './controllers/resource_edit_controller' import ResourceIndexController from './controllers/resource_index_controller' +import ResourceSearchController from './controllers/resource_search_controller' import ResourceShowController from './controllers/resource_show_controller' import SearchController from './controllers/search_controller' import SelectController from './controllers/select_controller' @@ -80,6 +81,7 @@ application.register('preview', PreviewController) application.register('record-selector', RecordSelectorController) application.register('resource-edit', ResourceEditController) application.register('resource-index', ResourceIndexController) +application.register('resource-search', ResourceSearchController) application.register('resource-show', ResourceShowController) application.register('search', SearchController) application.register('select', SelectController) diff --git a/app/javascript/js/controllers/resource_search_controller.js b/app/javascript/js/controllers/resource_search_controller.js new file mode 100644 index 000000000..17f328b42 --- /dev/null +++ b/app/javascript/js/controllers/resource_search_controller.js @@ -0,0 +1,24 @@ +import { Controller } from "@hotwired/stimulus" +import { get } from "@rails/request.js" + +export default class extends Controller { + static targets = ['input'] + + connect() { + console.log('Resource search controller connected') + } + + async search() { + const query = this.inputTarget.value + const currentUrl = new URL(window.location.href) + currentUrl.searchParams.set('q', query) + + try { + await get(currentUrl.pathname + currentUrl.search, { + responseKind: 'turbo-stream' + }) + } catch (error) { + console.error('Error performing search:', error) + } + } +} From da7469c5ece65cddd80c17e1940d8a1127bd0705 Mon Sep 17 00:00:00 2001 From: Santosh Prasad Sah Date: Wed, 29 Jan 2025 15:27:45 +0545 Subject: [PATCH 3/9] feat: add apply search query method to search resource items --- app/controllers/avo/base_controller.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/controllers/avo/base_controller.rb b/app/controllers/avo/base_controller.rb index 94224ee38..729d5aecd 100644 --- a/app/controllers/avo/base_controller.rb +++ b/app/controllers/avo/base_controller.rb @@ -25,6 +25,8 @@ def index end add_breadcrumb @resource.plural_name.humanize + # Apply the search query if configured on the resource + apply_search_query if params[:q].present? && @resource.search.present? set_index_params set_filters set_actions @@ -658,5 +660,12 @@ def set_pagination_params def set_query @query ||= @resource.class.query_scope end + + def apply_search_query + search_query = @resource.search[:query] + return unless search_query.present? + + @query = instance_exec(@query, &search_query) + end end end From e6df9149a767c4f817a9e3d39e51f48968aca6b9 Mon Sep 17 00:00:00 2001 From: Santosh Prasad Sah Date: Wed, 29 Jan 2025 16:13:58 +0545 Subject: [PATCH 4/9] feat: set search param to index params also try to use ExecutionContext --- app/controllers/avo/base_controller.rb | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/app/controllers/avo/base_controller.rb b/app/controllers/avo/base_controller.rb index 729d5aecd..3538b8f6a 100644 --- a/app/controllers/avo/base_controller.rb +++ b/app/controllers/avo/base_controller.rb @@ -26,8 +26,8 @@ def index add_breadcrumb @resource.plural_name.humanize # Apply the search query if configured on the resource - apply_search_query if params[:q].present? && @resource.search.present? set_index_params + apply_search set_filters set_actions set_query @@ -322,6 +322,9 @@ def set_index_params set_pagination_params + # Search + @index_params[:q] = params[:q] if params[:q].present? + # Sorting @index_params[:sort_by] = params[:sort_by] || @resource.sort_by_param @@ -661,11 +664,18 @@ def set_query @query ||= @resource.class.query_scope end - def apply_search_query + def apply_search + return if @resource.class.search_query.nil? + return if @index_params[:q].nil? + search_query = @resource.search[:query] return unless search_query.present? - @query = instance_exec(@query, &search_query) + @query = Avo::ExecutionContext.new( + target: @resource.class.search_query, + params: params, + query: @query + ).handle end end end From 7a5e338e6fbb7f96a208365d024edc1c0989f952 Mon Sep 17 00:00:00 2001 From: Santosh Prasad Sah Date: Tue, 4 Mar 2025 20:08:58 +0545 Subject: [PATCH 5/9] feat: move apply_search method after @query is initialized --- app/controllers/avo/base_controller.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/controllers/avo/base_controller.rb b/app/controllers/avo/base_controller.rb index 3538b8f6a..2f6b3a9c6 100644 --- a/app/controllers/avo/base_controller.rb +++ b/app/controllers/avo/base_controller.rb @@ -25,9 +25,7 @@ def index end add_breadcrumb @resource.plural_name.humanize - # Apply the search query if configured on the resource set_index_params - apply_search set_filters set_actions set_query @@ -37,6 +35,9 @@ def index @query = @query.includes(*@resource.includes) end + # Apply the search query if configured on the resource + apply_search + # Eager load attachments if @resource.attachments.present? @resource.attachments.each do |attachment| From 2ca81df0a9a56d006c583c6e2e7f85f3438782d7 Mon Sep 17 00:00:00 2001 From: Santosh Prasad Sah Date: Mon, 7 Apr 2025 18:01:53 +0545 Subject: [PATCH 6/9] feature: inline search working now --- .../views/resource_index_component.html.erb | 3 ++- app/controllers/avo/base_controller.rb | 22 ++++++++++++++++++- .../controllers/resource_search_controller.js | 9 +++++--- .../index/_resource_table_component.html.erb | 10 +++++++++ 4 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 app/views/avo/index/_resource_table_component.html.erb diff --git a/app/components/avo/views/resource_index_component.html.erb b/app/components/avo/views/resource_index_component.html.erb index cab3c9e7c..3f9377a09 100644 --- a/app/components/avo/views/resource_index_component.html.erb +++ b/app/components/avo/views/resource_index_component.html.erb @@ -45,7 +45,8 @@ data-resource-search-target="input" data-action="input->resource-search#search" placeholder="Type to search..." - class="block w-full rounded-md border-gray-300 shadow-sm focus:border-primary-500 focus:ring-primary-500 sm:text-sm"> + class="block w-full rounded-md border-gray-300 shadow-sm focus:border-primary-500 focus:ring-primary-500 sm:text-sm" + value="<%= @index_params[:q] %>"> <% else %> <%# Offset for the space-y-2 property when the search is missing %>
diff --git a/app/controllers/avo/base_controller.rb b/app/controllers/avo/base_controller.rb index 444058406..165a2bfc8 100644 --- a/app/controllers/avo/base_controller.rb +++ b/app/controllers/avo/base_controller.rb @@ -37,7 +37,7 @@ def index end # Apply the search query if configured on the resource - apply_search + safe_call :apply_search # Eager load attachments if @resource.attachments.present? @@ -67,6 +67,26 @@ def index end set_component_for __method__ + + respond_to do |format| + format.html + format.turbo_stream do + render turbo_stream: turbo_stream.replace( + "#{@resource.model_key}_list", + partial: "avo/index/resource_table_component", + locals: { + resources: @resources, + resource: @resource, + reflection: @reflection, + parent_record: @parent_record, + parent_resource: @parent_resource, + pagy: @pagy, + query: @query, + actions: @actions + } + ) + end + end end def show diff --git a/app/javascript/js/controllers/resource_search_controller.js b/app/javascript/js/controllers/resource_search_controller.js index 17f328b42..d40ef6dd3 100644 --- a/app/javascript/js/controllers/resource_search_controller.js +++ b/app/javascript/js/controllers/resource_search_controller.js @@ -1,5 +1,5 @@ -import { Controller } from "@hotwired/stimulus" -import { get } from "@rails/request.js" +import { Controller } from '@hotwired/stimulus' +import { get } from '@rails/request.js' export default class extends Controller { static targets = ['input'] @@ -15,7 +15,10 @@ export default class extends Controller { try { await get(currentUrl.pathname + currentUrl.search, { - responseKind: 'turbo-stream' + responseKind: 'turbo-stream', + headers: { + Accept: 'text/vnd.turbo-stream.html', + }, }) } catch (error) { console.error('Error performing search:', error) diff --git a/app/views/avo/index/_resource_table_component.html.erb b/app/views/avo/index/_resource_table_component.html.erb new file mode 100644 index 000000000..a935fae12 --- /dev/null +++ b/app/views/avo/index/_resource_table_component.html.erb @@ -0,0 +1,10 @@ +<%= render Avo::Index::ResourceTableComponent.new( + resources: resources, + resource: resource, + reflection: reflection, + parent_record: parent_record, + parent_resource: parent_resource, + pagy: pagy, + query: query, + actions: actions +) %> From f15e72d98efc39fd8f5a6ace00bdec96272ce7ba Mon Sep 17 00:00:00 2001 From: Santosh Prasad Sah Date: Mon, 7 Apr 2025 18:07:52 +0545 Subject: [PATCH 7/9] refactor: set_index_params to improve Cognitive Complexity analysis --- app/controllers/avo/base_controller.rb | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/app/controllers/avo/base_controller.rb b/app/controllers/avo/base_controller.rb index 165a2bfc8..73fd8be4d 100644 --- a/app/controllers/avo/base_controller.rb +++ b/app/controllers/avo/base_controller.rb @@ -348,20 +348,31 @@ def set_index_params @index_params = {} set_pagination_params + set_search_params + set_sorting_params + set_view_type_params - # Search + validate_view_type + end + + def set_search_params @index_params[:q] = params[:q] if params[:q].present? + end - # Sorting + def set_sorting_params @index_params[:sort_by] = params[:sort_by] || @resource.sort_by_param - @index_params[:sort_direction] = params[:sort_direction] || @resource.default_sort_direction + end - # View types + def set_view_type_params available_view_types = @resource.available_view_types @index_params[:available_view_types] = available_view_types - @index_params[:view_type] = if params[:view_type].present? + @index_params[:view_type] = determine_view_type(available_view_types) + end + + def determine_view_type(available_view_types) + if params[:view_type].present? params[:view_type] elsif available_view_types.size == 1 available_view_types.first @@ -372,8 +383,10 @@ def set_index_params view: @view ).handle end + end - if available_view_types.exclude? @index_params[:view_type].to_sym + def validate_view_type + if @index_params[:available_view_types].exclude? @index_params[:view_type].to_sym raise "View type '#{@index_params[:view_type]}' is unavailable for #{@resource.class}." end end From ff21be6e3a811356b10e36b4fc7a76f46e3ded6b Mon Sep 17 00:00:00 2001 From: Santosh Prasad Sah Date: Wed, 9 Apr 2025 23:19:46 +0545 Subject: [PATCH 8/9] feat: wip add debounce for index search --- .../views/resource_index_component.html.erb | 1 + app/controllers/avo/base_controller.rb | 2 +- .../controllers/resource_search_controller.js | 45 +++++++++++++++++-- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/app/components/avo/views/resource_index_component.html.erb b/app/components/avo/views/resource_index_component.html.erb index 3f9377a09..6241bdf64 100644 --- a/app/components/avo/views/resource_index_component.html.erb +++ b/app/components/avo/views/resource_index_component.html.erb @@ -45,6 +45,7 @@ data-resource-search-target="input" data-action="input->resource-search#search" placeholder="Type to search..." + data-resource-search-debounce-value="500" class="block w-full rounded-md border-gray-300 shadow-sm focus:border-primary-500 focus:ring-primary-500 sm:text-sm" value="<%= @index_params[:q] %>"> <% else %> diff --git a/app/controllers/avo/base_controller.rb b/app/controllers/avo/base_controller.rb index 73fd8be4d..9550d6aae 100644 --- a/app/controllers/avo/base_controller.rb +++ b/app/controllers/avo/base_controller.rb @@ -709,7 +709,7 @@ def apply_search @query = Avo::ExecutionContext.new( target: @resource.class.search_query, - params: params, + params: params.merge(q: @index_params[:q]), query: @query ).handle end diff --git a/app/javascript/js/controllers/resource_search_controller.js b/app/javascript/js/controllers/resource_search_controller.js index d40ef6dd3..7084696f2 100644 --- a/app/javascript/js/controllers/resource_search_controller.js +++ b/app/javascript/js/controllers/resource_search_controller.js @@ -4,17 +4,42 @@ import { get } from '@rails/request.js' export default class extends Controller { static targets = ['input'] + static values = { + debounce: { type: Number, default: 300 }, + } + connect() { console.log('Resource search controller connected') } - async search() { + search() { + this.debouncedSearch() + } + + debouncedSearch = this.debounce(this.performSearch, this.debounceValue) + + async performSearch() { const query = this.inputTarget.value const currentUrl = new URL(window.location.href) - currentUrl.searchParams.set('q', query) + + // Get existing search params + const searchParams = new URLSearchParams(window.location.search) + + // Update the search parameter + if (query) { + searchParams.set('q', query) + } else { + searchParams.delete('q') + } + + // Reset to first page when searching + searchParams.set('page', '1') + + // Construct the new URL with all parameters + const newUrl = `${currentUrl.pathname}?${searchParams.toString()}` try { - await get(currentUrl.pathname + currentUrl.search, { + await get(newUrl, { responseKind: 'turbo-stream', headers: { Accept: 'text/vnd.turbo-stream.html', @@ -24,4 +49,18 @@ export default class extends Controller { console.error('Error performing search:', error) } } + + debounce(func, wait) { + let timeout + + return function executedFunction(...args) { + const later = () => { + clearTimeout(timeout) + func.apply(this, args) + } + clearTimeout(timeout) + timeout = setTimeout(later, wait) + } + } + } From 36d0d79bbb12ef8aeb7e8c81cdd18d16bc3a5990 Mon Sep 17 00:00:00 2001 From: Paul Bob Date: Wed, 16 Apr 2025 13:36:06 +0300 Subject: [PATCH 9/9] replace pagination & update query params --- .../avo/paginator_component.html.erb | 2 +- app/controllers/avo/base_controller.rb | 40 ++++++++++++------- .../controllers/resource_search_controller.js | 4 +- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/app/components/avo/paginator_component.html.erb b/app/components/avo/paginator_component.html.erb index 976add7fa..fa63f490b 100644 --- a/app/components/avo/paginator_component.html.erb +++ b/app/components/avo/paginator_component.html.erb @@ -1,4 +1,4 @@ -
+
" class="flex flex-col sm:flex-row items-center justify-between aborder-t aborder-slate-200 rounded-2xl space-y-2 sm:space-y-0">
diff --git a/app/controllers/avo/base_controller.rb b/app/controllers/avo/base_controller.rb index 9550d6aae..6ac5f05eb 100644 --- a/app/controllers/avo/base_controller.rb +++ b/app/controllers/avo/base_controller.rb @@ -71,20 +71,32 @@ def index respond_to do |format| format.html format.turbo_stream do - render turbo_stream: turbo_stream.replace( - "#{@resource.model_key}_list", - partial: "avo/index/resource_table_component", - locals: { - resources: @resources, - resource: @resource, - reflection: @reflection, - parent_record: @parent_record, - parent_resource: @parent_resource, - pagy: @pagy, - query: @query, - actions: @actions - } - ) + render turbo_stream: [ + turbo_stream.replace( + "#{@resource.model_key}_list", + partial: "avo/index/resource_table_component", + locals: { + resources: @resources, + resource: @resource, + reflection: @reflection, + parent_record: @parent_record, + parent_resource: @parent_resource, + pagy: @pagy, + query: @query, + actions: @actions + } + ), + turbo_stream.replace("#{@resource.model_key}_pagination") do + Avo::Current.view_context.render Avo::PaginatorComponent.new( + pagy: @pagy, + turbo_frame: @turbo_frame, + index_params: @index_params, + resource: @resource, + parent_record: @parent_record, + parent_resource: @parent_resource + ) + end + ] end end end diff --git a/app/javascript/js/controllers/resource_search_controller.js b/app/javascript/js/controllers/resource_search_controller.js index 7084696f2..e40c837ac 100644 --- a/app/javascript/js/controllers/resource_search_controller.js +++ b/app/javascript/js/controllers/resource_search_controller.js @@ -38,6 +38,9 @@ export default class extends Controller { // Construct the new URL with all parameters const newUrl = `${currentUrl.pathname}?${searchParams.toString()}` + // Replace current URL without affecting browser history + window.history.replaceState({}, '', newUrl) + try { await get(newUrl, { responseKind: 'turbo-stream', @@ -62,5 +65,4 @@ export default class extends Controller { timeout = setTimeout(later, wait) } } - }