Browse Source

Add search controller

pull/2535/head
Kat 2 years ago committed by kosiakkatrina
parent
commit
ac479214fd
  1. 7
      app/controllers/users_controller.rb
  2. 3
      app/frontend/controllers/index.js
  3. 47
      app/frontend/controllers/search_controller.js
  4. 35
      app/frontend/modules/search.js
  5. 2
      app/views/filters/_select_filter.html.erb
  6. 1
      app/views/filters/assigned_to.html.erb
  7. 4
      config/routes.rb

7
app/controllers/users_controller.rb

@ -32,6 +32,13 @@ class UsersController < ApplicationController
end end
end end
def search
users = User.search_by_name(params["query"]).limit(20)
x = {}
users.each { |user| x[user.id] = { value: user.name, hint: user.email } }
render json: x.to_json
end
def resend_invite def resend_invite
@user.send_confirmation_instructions @user.send_confirmation_instructions
flash[:notice] = "Invitation sent to #{@user.email}" flash[:notice] = "Invitation sent to #{@user.email}"

3
app/frontend/controllers/index.js

@ -13,6 +13,8 @@ import GovukfrontendController from './govukfrontend_controller.js'
import NumericQuestionController from './numeric_question_controller.js' import NumericQuestionController from './numeric_question_controller.js'
import SearchController from './search_controller.js'
import FilterLayoutController from './filter_layout_controller.js' import FilterLayoutController from './filter_layout_controller.js'
application.register('accessible-autocomplete', AccessibleAutocompleteController) application.register('accessible-autocomplete', AccessibleAutocompleteController)
application.register('conditional-filter', ConditionalFilterController) application.register('conditional-filter', ConditionalFilterController)
@ -20,3 +22,4 @@ application.register('conditional-question', ConditionalQuestionController)
application.register('govukfrontend', GovukfrontendController) application.register('govukfrontend', GovukfrontendController)
application.register('numeric-question', NumericQuestionController) application.register('numeric-question', NumericQuestionController)
application.register('filter-layout', FilterLayoutController) application.register('filter-layout', FilterLayoutController)
application.register('search', SearchController)

47
app/frontend/controllers/search_controller.js

@ -0,0 +1,47 @@
import { Controller } from '@hotwired/stimulus'
import accessibleAutocomplete from 'accessible-autocomplete'
import 'accessible-autocomplete/dist/accessible-autocomplete.min.css'
import { searchSuggestion, fetchAndPopulateSearchResults } from '../modules/search'
let hints = [];
const populateHint = (results) => {
console.log("populating")
hints = results
}
export default class extends Controller {
connect () {
const selectEl = this.element
const selectOptions = Array.from(selectEl.options).filter(function (option, index, arr) { return option.value !== '' })
const matches = /^(\w+)\[(\w+)\]$/.exec(selectEl.name)
const rawFieldName = matches ? `${matches[1]}[${matches[2]}_raw]` : ''
accessibleAutocomplete.enhanceSelectElement({
defaultValue: '',
selectElement: selectEl,
minLength: 1,
source: (query, populateResults) => {
fetchAndPopulateSearchResults(query, populateResults, populateHint)
},
autoselect: true,
placeholder: 'Start typing to search',
templates: { suggestion: (value) => searchSuggestion(value, hints) },
name: rawFieldName,
onConfirm: (val) => {
const selectedOption = [].filter.call(
selectOptions,
(option) => (getSearchableName(option)) === val
)[0]
if (selectedOption) selectedOption.selected = true
}
})
const parentElement = selectEl.parentElement
const inputElement = parentElement.querySelector('[role=combobox]')
inputElement.addEventListener('input', () => {
selectOptions.forEach((option) => { option.selected = false })
})
}
}

35
app/frontend/modules/search.js

@ -117,6 +117,21 @@ export const suggestion = (value, options) => {
} }
} }
export const searchSuggestion = (value, hints) => {
try {
const result = hints[value.toString()]
if (result) {
const html = result.append ? `<span class="autocomplete__option__append">${result.value}</span> <span>${result.append}</span>` : `<span>${result.value}</span>`
return result.hint ? `${html}<div class="autocomplete__option__hint">${result.hint}</div>` : html
} else {
return '<span>No results found</span>'
}
} catch (error) {
console.error('Error fetching user option:', error)
return value
}
}
export const enhanceOption = (option) => { export const enhanceOption = (option) => {
return { return {
text: option.text, text: option.text,
@ -128,6 +143,26 @@ export const enhanceOption = (option) => {
} }
} }
export const fetchAndPopulateSearchResults = async (query, populateResults, populateHint) => {
if (/\S/.test(query)) {
let results = await fetchUserOptions(query)
populateResults(Object.keys(results))
populateHint(results)
}
}
export const fetchUserOptions = async (query) => {
try {
const response = await fetch(`/users/search?query=${encodeURIComponent(query)}`)
const results = await response.json()
return results
} catch (error) {
console.error('Error fetching user options:', error)
return []
}
}
export const getSearchableName = (option) => { export const getSearchableName = (option) => {
return option.getAttribute('data-hint') ? option.text + ' ' + option.getAttribute('data-hint') : option.text return option.getAttribute('data-hint') ? option.text + ' ' + option.getAttribute('data-hint') : option.text
} }

2
app/views/filters/_select_filter.html.erb

@ -1,6 +1,6 @@
<%= f.govuk_select(category.to_sym, <%= f.govuk_select(category.to_sym,
label: { text: label, hidden: secondary }, label: { text: label, hidden: secondary },
"data-controller": "accessible-autocomplete conditional-filter") do %> "data-controller": "search conditional-filter") do %>
<% collection.each do |answer| %> <% collection.each do |answer| %>
<option value="<%= answer.id %>" <option value="<%= answer.id %>"
data-hint="<%= answer.hint %>" data-hint="<%= answer.hint %>"

1
app/views/filters/assigned_to.html.erb

@ -11,7 +11,6 @@
type: "select", type: "select",
label: "User", label: "User",
category: "user", category: "user",
options: assigned_to_filter_options(current_user),
}, },
}, },
}, },

4
config/routes.rb

@ -125,6 +125,10 @@ Rails.application.routes.draw do
get "edit-dpo", to: "users#dpo" get "edit-dpo", to: "users#dpo"
get "edit-key-contact", to: "users#key_contact" get "edit-key-contact", to: "users#key_contact"
collection do
get :search
end
member do member do
get "deactivate", to: "users#deactivate" get "deactivate", to: "users#deactivate"
get "reactivate", to: "users#reactivate" get "reactivate", to: "users#reactivate"

Loading…
Cancel
Save