mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-05-05 16:50:12 +00:00
Added user-select input
This commit is contained in:
parent
33e35c9a8a
commit
8833b5bc3b
15 changed files with 271 additions and 128 deletions
resources/js/components
|
@ -1,55 +0,0 @@
|
|||
|
||||
class BreadcrumbListing {
|
||||
|
||||
setup() {
|
||||
this.elem = this.$el;
|
||||
this.searchInput = this.$refs.searchInput;
|
||||
this.loadingElem = this.$refs.loading;
|
||||
this.entityListElem = this.$refs.entityList;
|
||||
|
||||
this.entityType = this.$opts.entityType;
|
||||
this.entityId = Number(this.$opts.entityId);
|
||||
|
||||
this.elem.addEventListener('show', this.onShow.bind(this));
|
||||
this.searchInput.addEventListener('input', this.onSearch.bind(this));
|
||||
}
|
||||
|
||||
onShow() {
|
||||
this.loadEntityView();
|
||||
}
|
||||
|
||||
onSearch() {
|
||||
const input = this.searchInput.value.toLowerCase().trim();
|
||||
const listItems = this.entityListElem.querySelectorAll('.entity-list-item');
|
||||
for (let listItem of listItems) {
|
||||
const match = !input || listItem.textContent.toLowerCase().includes(input);
|
||||
listItem.style.display = match ? 'flex' : 'none';
|
||||
listItem.classList.toggle('hidden', !match);
|
||||
}
|
||||
}
|
||||
|
||||
loadEntityView() {
|
||||
this.toggleLoading(true);
|
||||
|
||||
const params = {
|
||||
'entity_id': this.entityId,
|
||||
'entity_type': this.entityType,
|
||||
};
|
||||
|
||||
window.$http.get('/search/entity/siblings', params).then(resp => {
|
||||
this.entityListElem.innerHTML = resp.data;
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
}).then(() => {
|
||||
this.toggleLoading(false);
|
||||
this.onSearch();
|
||||
});
|
||||
}
|
||||
|
||||
toggleLoading(show = false) {
|
||||
this.loadingElem.style.display = show ? 'block' : 'none';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default BreadcrumbListing;
|
79
resources/js/components/dropdown-search.js
Normal file
79
resources/js/components/dropdown-search.js
Normal file
|
@ -0,0 +1,79 @@
|
|||
import {debounce} from "../services/util";
|
||||
|
||||
class DropdownSearch {
|
||||
|
||||
setup() {
|
||||
this.elem = this.$el;
|
||||
this.searchInput = this.$refs.searchInput;
|
||||
this.loadingElem = this.$refs.loading;
|
||||
this.listContainerElem = this.$refs.listContainer;
|
||||
|
||||
this.localSearchSelector = this.$opts.localSearchSelector;
|
||||
this.url = this.$opts.url;
|
||||
|
||||
this.elem.addEventListener('show', this.onShow.bind(this));
|
||||
this.searchInput.addEventListener('input', this.onSearch.bind(this));
|
||||
|
||||
this.runAjaxSearch = debounce(this.runAjaxSearch, 300, false);
|
||||
}
|
||||
|
||||
onShow() {
|
||||
this.loadList();
|
||||
}
|
||||
|
||||
onSearch() {
|
||||
const input = this.searchInput.value.toLowerCase().trim();
|
||||
if (this.localSearchSelector) {
|
||||
this.runLocalSearch(input);
|
||||
} else {
|
||||
this.toggleLoading(true);
|
||||
this.runAjaxSearch(input);
|
||||
}
|
||||
}
|
||||
|
||||
runAjaxSearch(searchTerm) {
|
||||
this.loadList(searchTerm);
|
||||
}
|
||||
|
||||
runLocalSearch(searchTerm) {
|
||||
const listItems = this.listContainerElem.querySelectorAll(this.localSearchSelector);
|
||||
for (let listItem of listItems) {
|
||||
const match = !searchTerm || listItem.textContent.toLowerCase().includes(searchTerm);
|
||||
listItem.style.display = match ? 'flex' : 'none';
|
||||
listItem.classList.toggle('hidden', !match);
|
||||
}
|
||||
}
|
||||
|
||||
async loadList(searchTerm = '') {
|
||||
this.listContainerElem.innerHTML = '';
|
||||
this.toggleLoading(true);
|
||||
|
||||
try {
|
||||
const resp = await window.$http.get(this.getAjaxUrl(searchTerm));
|
||||
this.listContainerElem.innerHTML = resp.data;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
this.toggleLoading(false);
|
||||
if (this.localSearchSelector) {
|
||||
this.onSearch();
|
||||
}
|
||||
}
|
||||
|
||||
getAjaxUrl(searchTerm = null) {
|
||||
if (!searchTerm) {
|
||||
return this.url;
|
||||
}
|
||||
|
||||
const joiner = this.url.includes('?') ? '&' : '?';
|
||||
return `${this.url}${joiner}search=${encodeURIComponent(searchTerm)}`;
|
||||
}
|
||||
|
||||
toggleLoading(show = false) {
|
||||
this.loadingElem.style.display = show ? 'block' : 'none';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default DropdownSearch;
|
|
@ -17,6 +17,7 @@ class DropDown {
|
|||
this.body = document.body;
|
||||
this.showing = false;
|
||||
this.setupListeners();
|
||||
this.hide = this.hide.bind(this);
|
||||
}
|
||||
|
||||
show(event = null) {
|
||||
|
|
|
@ -5,7 +5,6 @@ import attachments from "./attachments.js"
|
|||
import autoSuggest from "./auto-suggest.js"
|
||||
import backToTop from "./back-to-top.js"
|
||||
import bookSort from "./book-sort.js"
|
||||
import breadcrumbListing from "./breadcrumb-listing.js"
|
||||
import chapterToggle from "./chapter-toggle.js"
|
||||
import codeEditor from "./code-editor.js"
|
||||
import codeHighlighter from "./code-highlighter.js"
|
||||
|
@ -13,6 +12,7 @@ import collapsible from "./collapsible.js"
|
|||
import customCheckbox from "./custom-checkbox.js"
|
||||
import detailsHighlighter from "./details-highlighter.js"
|
||||
import dropdown from "./dropdown.js"
|
||||
import dropdownSearch from "./dropdown-search.js"
|
||||
import dropzone from "./dropzone.js"
|
||||
import editorToolbox from "./editor-toolbox.js"
|
||||
import entityPermissionsEditor from "./entity-permissions-editor.js"
|
||||
|
@ -48,6 +48,7 @@ import tagManager from "./tag-manager.js"
|
|||
import templateManager from "./template-manager.js"
|
||||
import toggleSwitch from "./toggle-switch.js"
|
||||
import triLayout from "./tri-layout.js"
|
||||
import userSelect from "./user-select.js"
|
||||
import wysiwygEditor from "./wysiwyg-editor.js"
|
||||
|
||||
const componentMapping = {
|
||||
|
@ -58,7 +59,6 @@ const componentMapping = {
|
|||
"auto-suggest": autoSuggest,
|
||||
"back-to-top": backToTop,
|
||||
"book-sort": bookSort,
|
||||
"breadcrumb-listing": breadcrumbListing,
|
||||
"chapter-toggle": chapterToggle,
|
||||
"code-editor": codeEditor,
|
||||
"code-highlighter": codeHighlighter,
|
||||
|
@ -66,6 +66,7 @@ const componentMapping = {
|
|||
"custom-checkbox": customCheckbox,
|
||||
"details-highlighter": detailsHighlighter,
|
||||
"dropdown": dropdown,
|
||||
"dropdown-search": dropdownSearch,
|
||||
"dropzone": dropzone,
|
||||
"editor-toolbox": editorToolbox,
|
||||
"entity-permissions-editor": entityPermissionsEditor,
|
||||
|
@ -101,6 +102,7 @@ const componentMapping = {
|
|||
"template-manager": templateManager,
|
||||
"toggle-switch": toggleSwitch,
|
||||
"tri-layout": triLayout,
|
||||
"user-select": userSelect,
|
||||
"wysiwyg-editor": wysiwygEditor,
|
||||
};
|
||||
|
||||
|
|
24
resources/js/components/user-select.js
Normal file
24
resources/js/components/user-select.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
import {onChildEvent} from "../services/dom";
|
||||
|
||||
class UserSelect {
|
||||
|
||||
setup() {
|
||||
|
||||
this.input = this.$refs.input;
|
||||
this.userInfoContainer = this.$refs.userInfo;
|
||||
|
||||
this.hide = this.$el.components.dropdown.hide;
|
||||
|
||||
onChildEvent(this.$el, 'a.dropdown-search-item', 'click', this.selectUser.bind(this));
|
||||
}
|
||||
|
||||
selectUser(event, userEl) {
|
||||
const id = userEl.getAttribute('data-id');
|
||||
this.input.value = id;
|
||||
this.userInfoContainer.innerHTML = userEl.innerHTML;
|
||||
this.hide();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default UserSelect;
|
Loading…
Add table
Add a link
Reference in a new issue