mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
Started on a live-preview on global search input
This commit is contained in:
parent
a1b1f8138a
commit
19a792bc12
@ -11,7 +11,7 @@ use Illuminate\Http\Request;
|
|||||||
|
|
||||||
class SearchController extends Controller
|
class SearchController extends Controller
|
||||||
{
|
{
|
||||||
protected $searchRunner;
|
protected SearchRunner $searchRunner;
|
||||||
|
|
||||||
public function __construct(SearchRunner $searchRunner)
|
public function __construct(SearchRunner $searchRunner)
|
||||||
{
|
{
|
||||||
|
47
resources/js/components/global-search.js
Normal file
47
resources/js/components/global-search.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* @extends {Component}
|
||||||
|
*/
|
||||||
|
import {htmlToDom} from "../services/dom";
|
||||||
|
|
||||||
|
class GlobalSearch {
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
this.input = this.$refs.input;
|
||||||
|
this.suggestions = this.$refs.suggestions;
|
||||||
|
this.suggestionResultsWrap = this.$refs.suggestionResults;
|
||||||
|
|
||||||
|
this.setupListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
setupListeners() {
|
||||||
|
this.input.addEventListener('input', () => {
|
||||||
|
const value = this.input.value;
|
||||||
|
if (value.length > 0) {
|
||||||
|
this.updateSuggestions(value);
|
||||||
|
} else {
|
||||||
|
this.hideSuggestions();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateSuggestions(search) {
|
||||||
|
const {data: results} = await window.$http.get('/ajax/search/entities', {term: search, count: 5});
|
||||||
|
const resultDom = htmlToDom(results);
|
||||||
|
|
||||||
|
const childrenToTrim = Array.from(resultDom.children).slice(9);
|
||||||
|
for (const child of childrenToTrim) {
|
||||||
|
child.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.suggestions.style.display = 'block';
|
||||||
|
this.suggestionResultsWrap.innerHTML = '';
|
||||||
|
this.suggestionResultsWrap.append(resultDom);
|
||||||
|
}
|
||||||
|
|
||||||
|
hideSuggestions() {
|
||||||
|
this.suggestions.style.display = null;
|
||||||
|
this.suggestionResultsWrap.innerHTML = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GlobalSearch;
|
@ -57,6 +57,7 @@ import triLayout from "./tri-layout.js"
|
|||||||
import userSelect from "./user-select.js"
|
import userSelect from "./user-select.js"
|
||||||
import webhookEvents from "./webhook-events";
|
import webhookEvents from "./webhook-events";
|
||||||
import wysiwygEditor from "./wysiwyg-editor.js"
|
import wysiwygEditor from "./wysiwyg-editor.js"
|
||||||
|
import globalSearch from "./global-search";
|
||||||
|
|
||||||
const componentMapping = {
|
const componentMapping = {
|
||||||
"add-remove-rows": addRemoveRows,
|
"add-remove-rows": addRemoveRows,
|
||||||
@ -86,6 +87,7 @@ const componentMapping = {
|
|||||||
"entity-selector-popup": entitySelectorPopup,
|
"entity-selector-popup": entitySelectorPopup,
|
||||||
"event-emit-select": eventEmitSelect,
|
"event-emit-select": eventEmitSelect,
|
||||||
"expand-toggle": expandToggle,
|
"expand-toggle": expandToggle,
|
||||||
|
"global-search": globalSearch,
|
||||||
"header-mobile-toggle": headerMobileToggle,
|
"header-mobile-toggle": headerMobileToggle,
|
||||||
"homepage-control": homepageControl,
|
"homepage-control": homepageControl,
|
||||||
"image-manager": imageManager,
|
"image-manager": imageManager,
|
||||||
|
@ -86,11 +86,13 @@
|
|||||||
.card-title a {
|
.card-title a {
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
.card-footer-link {
|
.card-footer-link, button.card-footer-link {
|
||||||
display: block;
|
display: block;
|
||||||
padding: $-s $-m;
|
padding: $-s $-m;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
border-top: 1px solid;
|
border-top: 1px solid;
|
||||||
|
width: 100%;
|
||||||
|
text-align: left;
|
||||||
@include lightDark(border-color, #DDD, #555);
|
@include lightDark(border-color, #DDD, #555);
|
||||||
border-radius: 0 0 3px 3px;
|
border-radius: 0 0 3px 3px;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
|
@ -1011,3 +1011,30 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
|
|||||||
box-shadow: 0 1px 1px rgba(0, 0, 0, .2), 0 2px 0 0 rgba(255, 255, 255, .7) inset;
|
box-shadow: 0 1px 1px rgba(0, 0, 0, .2), 0 2px 0 0 rgba(255, 255, 255, .7) inset;
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.global-search-suggestions {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: -$-s;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: -1;
|
||||||
|
margin-left: -$-xxl;
|
||||||
|
margin-right: -$-xxl;
|
||||||
|
padding-top: 56px;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: $bs-hover;
|
||||||
|
.entity-item-snippet p {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.entity-item-snippet {
|
||||||
|
font-size: .8rem;
|
||||||
|
}
|
||||||
|
.entity-list-item-name {
|
||||||
|
font-size: .9rem;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
@ -412,7 +412,7 @@ div[editor-type="markdown"] .title-input.page-title input[type="text"] {
|
|||||||
.search-box {
|
.search-box {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
button {
|
button[tabindex="-1"] {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
@include lightDark(color, #666, #AAA);
|
@include lightDark(color, #666, #AAA);
|
||||||
|
@ -108,7 +108,18 @@ header .search-box {
|
|||||||
border: 1px solid rgba(255, 255, 255, 0.4);
|
border: 1px solid rgba(255, 255, 255, 0.4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
button {
|
input::placeholder {
|
||||||
|
color: #FFF;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
@include between($l, $xl) {
|
||||||
|
max-width: 200px;
|
||||||
|
}
|
||||||
|
&:focus-within #header-search-box-button {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#header-search-box-button {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
left: 16px;
|
left: 16px;
|
||||||
top: 10px;
|
top: 10px;
|
||||||
@ -122,17 +133,6 @@ header .search-box {
|
|||||||
svg {
|
svg {
|
||||||
margin-block-end: 0;
|
margin-block-end: 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
input::placeholder {
|
|
||||||
color: #FFF;
|
|
||||||
opacity: 0.6;
|
|
||||||
}
|
|
||||||
@include between($l, $xl) {
|
|
||||||
max-width: 200px;
|
|
||||||
}
|
|
||||||
&:focus-within button {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
|
@ -19,12 +19,19 @@
|
|||||||
|
|
||||||
<div class="flex-container-column items-center justify-center hide-under-l">
|
<div class="flex-container-column items-center justify-center hide-under-l">
|
||||||
@if (hasAppAccess())
|
@if (hasAppAccess())
|
||||||
<form action="{{ url('/search') }}" method="GET" class="search-box" role="search">
|
<form component="global-search" action="{{ url('/search') }}" method="GET" class="search-box" role="search">
|
||||||
<button id="header-search-box-button" type="submit" aria-label="{{ trans('common.search') }}" tabindex="-1">@icon('search') </button>
|
<button id="header-search-box-button" type="submit" aria-label="{{ trans('common.search') }}" tabindex="-1">@icon('search') </button>
|
||||||
<input id="header-search-box-input" type="text" name="term"
|
<input id="header-search-box-input"
|
||||||
|
refs="global-search@input"
|
||||||
|
type="text"
|
||||||
|
name="term"
|
||||||
data-shortcut="global_search"
|
data-shortcut="global_search"
|
||||||
aria-label="{{ trans('common.search') }}" placeholder="{{ trans('common.search') }}"
|
aria-label="{{ trans('common.search') }}" placeholder="{{ trans('common.search') }}"
|
||||||
value="{{ isset($searchTerm) ? $searchTerm : '' }}">
|
value="{{ $searchTerm ?? '' }}">
|
||||||
|
<div refs="global-search@suggestions" class="global-search-suggestions card">
|
||||||
|
<div refs="global-search@suggestion-results" class="px-m"></div>
|
||||||
|
<button class="text-button card-footer-link" type="submit">{{ trans('common.view_all') }}</button>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user