0
0
Fork 0
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:
Dan Brown 2020-12-31 17:25:20 +00:00
parent 33e35c9a8a
commit 8833b5bc3b
No known key found for this signature in database
GPG key ID: 46D9F943C24A2EF9
15 changed files with 271 additions and 128 deletions

View file

@ -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;

View 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;

View file

@ -17,6 +17,7 @@ class DropDown {
this.body = document.body;
this.showing = false;
this.setupListeners();
this.hide = this.hide.bind(this);
}
show(event = null) {

View file

@ -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,
};

View 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;