- Aligned prefix-type filtering with back-end.
- Increased suggestion search cut-off from 3 to 4.
- Increased amount of suggestions shown.
- Ordered suggestions to be name asc, as you'd expect on search.
- Updated front-end filtering to use full search query, instead of
truncated version, for further front-end filtering capability.
Related to #3720
* Get tag name suggestions from scanning existing tag names.
* If no search term is given the 50 most popular tag names are provided.
*/
- public function getNameSuggestions(?string $searchTerm): Collection
+ public function getNameSuggestions(string $searchTerm): Collection
{
$query = Tag::query()
->select('*', DB::raw('count(*) as count'))
->groupBy('name');
if ($searchTerm) {
- $query = $query->where('name', 'LIKE', $searchTerm . '%')->orderBy('name', 'desc');
+ $query = $query->where('name', 'LIKE', $searchTerm . '%')->orderBy('name', 'asc');
} else {
$query = $query->orderBy('count', 'desc')->take(50);
}
$query = $this->permissions->restrictEntityRelationQuery($query, 'tags', 'entity_id', 'entity_type');
- return $query->get(['name'])->pluck('name');
+ return $query->pluck('name');
}
/**
* If no search is given the 50 most popular values are provided.
* Passing a tagName will only find values for a tags with a particular name.
*/
- public function getValueSuggestions(?string $searchTerm, ?string $tagName): Collection
+ public function getValueSuggestions(string $searchTerm, string $tagName): Collection
{
$query = Tag::query()
->select('*', DB::raw('count(*) as count'))
$query = $this->permissions->restrictEntityRelationQuery($query, 'tags', 'entity_id', 'entity_type');
- return $query->get(['value'])->pluck('value');
+ return $query->pluck('value');
}
/**
class TagController extends Controller
{
- protected $tagRepo;
+ protected TagRepo $tagRepo;
- /**
- * TagController constructor.
- */
public function __construct(TagRepo $tagRepo)
{
$this->tagRepo = $tagRepo;
*/
public function getNameSuggestions(Request $request)
{
- $searchTerm = $request->get('search', null);
+ $searchTerm = $request->get('search', '');
$suggestions = $this->tagRepo->getNameSuggestions($searchTerm);
return response()->json($suggestions);
*/
public function getValueSuggestions(Request $request)
{
- $searchTerm = $request->get('search', null);
- $tagName = $request->get('name', null);
+ $searchTerm = $request->get('search', '');
+ $tagName = $request->get('name', '');
$suggestions = $this->tagRepo->getValueSuggestions($searchTerm, $tagName);
return response()->json($suggestions);
}
const nameFilter = this.getNameFilterIfNeeded();
- const search = this.input.value.slice(0, 3).toLowerCase();
+ const search = this.input.value.toLowerCase();
const suggestions = await this.loadSuggestions(search, nameFilter);
- let toShow = suggestions.slice(0, 6);
- if (search.length > 0) {
- toShow = suggestions.filter(val => {
- return val.toLowerCase().includes(search);
- }).slice(0, 6);
- }
+
+ const toShow = suggestions.filter(val => {
+ return search === '' || val.toLowerCase().startsWith(search);
+ }).slice(0, 10);
this.displaySuggestions(toShow);
}
* @returns {Promise<Object|String|*>}
*/
async loadSuggestions(search, nameFilter = null) {
+ // Truncate search to prevent over numerous lookups
+ search = search.slice(0, 4);
+
const params = {search, name: nameFilter};
const cacheKey = `${this.url}:${JSON.stringify(params)}`;