mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-04-29 22:29:57 +00:00
Finished updating remainder of JS components to new system
This commit is contained in:
parent
db79167469
commit
3b8ee3954e
25 changed files with 164 additions and 214 deletions
resources
js
components
attachments-list.jsattachments.jsback-to-top.jscode-editor.jscode-textarea.jsconfirm-dialog.jsdropzone.jseditor-toolbox.jsentity-search.jsevent-emit-select.jsimage-manager.jsindex.jsmarkdown-editor.jspage-editor.jsshelf-sort.jssortable-list.jstabs.jstag-manager.jstemplate-manager.jswysiwyg-editor.js
wysiwyg
sass
views
|
@ -43,6 +43,4 @@ export class AttachmentsList extends Component {
|
||||||
link.removeAttribute('target');
|
link.removeAttribute('target');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AttachmentsList;
|
|
|
@ -71,6 +71,4 @@ export class Attachments extends Component {
|
||||||
this.listContainer.classList.remove('hidden');
|
this.listContainer.classList.remove('hidden');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Attachments;
|
|
|
@ -55,6 +55,4 @@ export class BackToTop extends Component {
|
||||||
requestAnimationFrame(setPos.bind(this));
|
requestAnimationFrame(setPos.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BackToTop;
|
|
|
@ -1,10 +1,8 @@
|
||||||
import {onChildEvent, onEnterPress, onSelect} from "../services/dom";
|
import {onChildEvent, onEnterPress, onSelect} from "../services/dom";
|
||||||
|
import {Component} from "./component";
|
||||||
|
|
||||||
/**
|
|
||||||
* Code Editor
|
export class CodeEditor extends Component {
|
||||||
* @extends {Component}
|
|
||||||
*/
|
|
||||||
class CodeEditor {
|
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
this.container = this.$refs.container;
|
this.container = this.$refs.container;
|
||||||
|
@ -184,6 +182,4 @@ class CodeEditor {
|
||||||
window.sessionStorage.setItem(this.historyKey, historyString);
|
window.sessionStorage.setItem(this.historyKey, historyString);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CodeEditor;
|
|
|
@ -12,6 +12,4 @@ export class CodeTextarea extends Component {
|
||||||
Code.inlineEditor(this.$el, mode);
|
Code.inlineEditor(this.$el, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CodeTextarea;
|
|
|
@ -1,12 +1,12 @@
|
||||||
import {onSelect} from "../services/dom";
|
import {onSelect} from "../services/dom";
|
||||||
|
import {Component} from "./component";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom equivalent of window.confirm() using our popup component.
|
* Custom equivalent of window.confirm() using our popup component.
|
||||||
* Is promise based so can be used like so:
|
* Is promise based so can be used like so:
|
||||||
* `const result = await dialog.show()`
|
* `const result = await dialog.show()`
|
||||||
* @extends {Component}
|
|
||||||
*/
|
*/
|
||||||
class ConfirmDialog {
|
export class ConfirmDialog extends Component {
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
this.container = this.$el;
|
this.container = this.$el;
|
||||||
|
@ -47,6 +47,4 @@ class ConfirmDialog {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ConfirmDialog;
|
|
|
@ -1,11 +1,8 @@
|
||||||
import DropZoneLib from "dropzone";
|
import DropZoneLib from "dropzone";
|
||||||
import {fadeOut} from "../services/animations";
|
import {fadeOut} from "../services/animations";
|
||||||
|
import {Component} from "./component";
|
||||||
|
|
||||||
/**
|
export class Dropzone extends Component {
|
||||||
* Dropzone
|
|
||||||
* @extends {Component}
|
|
||||||
*/
|
|
||||||
class Dropzone {
|
|
||||||
setup() {
|
setup() {
|
||||||
this.container = this.$el;
|
this.container = this.$el;
|
||||||
this.url = this.$opts.url;
|
this.url = this.$opts.url;
|
||||||
|
@ -73,6 +70,4 @@ class Dropzone {
|
||||||
removeAll() {
|
removeAll() {
|
||||||
this.dz.removeAllFiles(true);
|
this.dz.removeAllFiles(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Dropzone;
|
|
|
@ -1,51 +1,58 @@
|
||||||
class EditorToolbox {
|
import {Component} from "./component";
|
||||||
|
|
||||||
constructor(elem) {
|
export class EditorToolbox extends Component {
|
||||||
|
|
||||||
|
setup() {
|
||||||
// Elements
|
// Elements
|
||||||
this.elem = elem;
|
this.container = this.$el;
|
||||||
this.buttons = elem.querySelectorAll('[toolbox-tab-button]');
|
this.buttons = this.$manyRefs.tabButton;
|
||||||
this.contentElements = elem.querySelectorAll('[toolbox-tab-content]');
|
this.contentElements = this.$manyRefs.tabContent;
|
||||||
this.toggleButton = elem.querySelector('[toolbox-toggle]');
|
this.toggleButton = this.$refs.toggle;
|
||||||
|
|
||||||
// Toolbox toggle button click
|
this.setupListeners();
|
||||||
this.toggleButton.addEventListener('click', this.toggle.bind(this));
|
|
||||||
// Tab button click
|
|
||||||
this.elem.addEventListener('click', event => {
|
|
||||||
let button = event.target.closest('[toolbox-tab-button]');
|
|
||||||
if (button === null) return;
|
|
||||||
let name = button.getAttribute('toolbox-tab-button');
|
|
||||||
this.setActiveTab(name, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set the first tab as active on load
|
// Set the first tab as active on load
|
||||||
this.setActiveTab(this.contentElements[0].getAttribute('toolbox-tab-content'));
|
this.setActiveTab(this.contentElements[0].dataset.tabContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
setupListeners() {
|
||||||
|
// Toolbox toggle button click
|
||||||
|
this.toggleButton.addEventListener('click', () => this.toggle());
|
||||||
|
// Tab button click
|
||||||
|
this.container.addEventListener('click', event => {
|
||||||
|
const button = event.target.closest('button');
|
||||||
|
if (this.buttons.includes(button)) {
|
||||||
|
const name = button.dataset.tab;
|
||||||
|
this.setActiveTab(name, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
toggle() {
|
toggle() {
|
||||||
this.elem.classList.toggle('open');
|
this.container.classList.toggle('open');
|
||||||
const expanded = this.elem.classList.contains('open') ? 'true' : 'false';
|
const expanded = this.container.classList.contains('open') ? 'true' : 'false';
|
||||||
this.toggleButton.setAttribute('aria-expanded', expanded);
|
this.toggleButton.setAttribute('aria-expanded', expanded);
|
||||||
}
|
}
|
||||||
|
|
||||||
setActiveTab(tabName, openToolbox = false) {
|
setActiveTab(tabName, openToolbox = false) {
|
||||||
|
|
||||||
// Set button visibility
|
// Set button visibility
|
||||||
for (let i = 0, len = this.buttons.length; i < len; i++) {
|
for (const button of this.buttons) {
|
||||||
this.buttons[i].classList.remove('active');
|
button.classList.remove('active');
|
||||||
let bName = this.buttons[i].getAttribute('toolbox-tab-button');
|
const bName = button.dataset.tab;
|
||||||
if (bName === tabName) this.buttons[i].classList.add('active');
|
if (bName === tabName) button.classList.add('active');
|
||||||
}
|
|
||||||
// Set content visibility
|
|
||||||
for (let i = 0, len = this.contentElements.length; i < len; i++) {
|
|
||||||
this.contentElements[i].style.display = 'none';
|
|
||||||
let cName = this.contentElements[i].getAttribute('toolbox-tab-content');
|
|
||||||
if (cName === tabName) this.contentElements[i].style.display = 'block';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (openToolbox && !this.elem.classList.contains('open')) {
|
// Set content visibility
|
||||||
|
for (const contentEl of this.contentElements) {
|
||||||
|
contentEl.style.display = 'none';
|
||||||
|
const cName = contentEl.dataset.tabContent;
|
||||||
|
if (cName === tabName) contentEl.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (openToolbox && !this.container.classList.contains('open')) {
|
||||||
this.toggle();
|
this.toggle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default EditorToolbox;
|
|
|
@ -1,10 +1,7 @@
|
||||||
import {onSelect} from "../services/dom";
|
import {onSelect} from "../services/dom";
|
||||||
|
import {Component} from "./component";
|
||||||
|
|
||||||
/**
|
export class EntitySearch extends Component {
|
||||||
* Class EntitySearch
|
|
||||||
* @extends {Component}
|
|
||||||
*/
|
|
||||||
class EntitySearch {
|
|
||||||
setup() {
|
setup() {
|
||||||
this.entityId = this.$opts.entityId;
|
this.entityId = this.$opts.entityId;
|
||||||
this.entityType = this.$opts.entityType;
|
this.entityType = this.$opts.entityType;
|
||||||
|
@ -54,6 +51,4 @@ class EntitySearch {
|
||||||
this.loadingBlock.classList.add('hidden');
|
this.loadingBlock.classList.add('hidden');
|
||||||
this.searchInput.value = '';
|
this.searchInput.value = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default EntitySearch;
|
|
|
@ -1,4 +1,5 @@
|
||||||
import {onSelect} from "../services/dom";
|
import {onSelect} from "../services/dom";
|
||||||
|
import {Component} from "./component";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EventEmitSelect
|
* EventEmitSelect
|
||||||
|
@ -10,10 +11,8 @@ import {onSelect} from "../services/dom";
|
||||||
*
|
*
|
||||||
* All options will be set as the "detail" of the event with
|
* All options will be set as the "detail" of the event with
|
||||||
* their values included.
|
* their values included.
|
||||||
*
|
|
||||||
* @extends {Component}
|
|
||||||
*/
|
*/
|
||||||
class EventEmitSelect {
|
export class EventEmitSelect extends Component{
|
||||||
setup() {
|
setup() {
|
||||||
this.container = this.$el;
|
this.container = this.$el;
|
||||||
this.name = this.$opts.name;
|
this.name = this.$opts.name;
|
||||||
|
@ -24,6 +23,4 @@ class EventEmitSelect {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default EventEmitSelect;
|
|
|
@ -1,10 +1,7 @@
|
||||||
import {onChildEvent, onSelect, removeLoading, showLoading} from "../services/dom";
|
import {onChildEvent, onSelect, removeLoading, showLoading} from "../services/dom";
|
||||||
|
import {Component} from "./component";
|
||||||
|
|
||||||
/**
|
export class ImageManager extends Component {
|
||||||
* ImageManager
|
|
||||||
* @extends {Component}
|
|
||||||
*/
|
|
||||||
class ImageManager {
|
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
|
|
||||||
|
@ -210,6 +207,4 @@ class ImageManager {
|
||||||
window.$components.init(this.formContainer);
|
window.$components.init(this.formContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ImageManager;
|
|
|
@ -8,34 +8,34 @@ export {AutoSubmit} from "./auto-submit.js"
|
||||||
export {BackToTop} from "./back-to-top.js"
|
export {BackToTop} from "./back-to-top.js"
|
||||||
export {BookSort} from "./book-sort.js"
|
export {BookSort} from "./book-sort.js"
|
||||||
export {ChapterContents} from "./chapter-contents.js"
|
export {ChapterContents} from "./chapter-contents.js"
|
||||||
// export {CodeEditor} from "./code-editor.js"
|
export {CodeEditor} from "./code-editor.js"
|
||||||
export {CodeHighlighter} from "./code-highlighter.js"
|
export {CodeHighlighter} from "./code-highlighter.js"
|
||||||
export {CodeTextarea} from "./code-textarea.js"
|
export {CodeTextarea} from "./code-textarea.js"
|
||||||
export {Collapsible} from "./collapsible.js"
|
export {Collapsible} from "./collapsible.js"
|
||||||
// export {ConfirmDialog} from "./confirm-dialog"
|
export {ConfirmDialog} from "./confirm-dialog"
|
||||||
export {CustomCheckbox} from "./custom-checkbox.js"
|
export {CustomCheckbox} from "./custom-checkbox.js"
|
||||||
export {DetailsHighlighter} from "./details-highlighter.js"
|
export {DetailsHighlighter} from "./details-highlighter.js"
|
||||||
export {Dropdown} from "./dropdown.js"
|
export {Dropdown} from "./dropdown.js"
|
||||||
export {DropdownSearch} from "./dropdown-search.js"
|
export {DropdownSearch} from "./dropdown-search.js"
|
||||||
// export {Dropzone} from "./dropzone.js"
|
export {Dropzone} from "./dropzone.js"
|
||||||
// export {EditorToolbox} from "./editor-toolbox.js"
|
export {EditorToolbox} from "./editor-toolbox.js"
|
||||||
export {EntityPermissions} from "./entity-permissions"
|
export {EntityPermissions} from "./entity-permissions"
|
||||||
// export {EntitySearch} from "./entity-search.js"
|
export {EntitySearch} from "./entity-search.js"
|
||||||
export {EntitySelector} from "./entity-selector.js"
|
export {EntitySelector} from "./entity-selector.js"
|
||||||
export {EntitySelectorPopup} from "./entity-selector-popup.js"
|
export {EntitySelectorPopup} from "./entity-selector-popup.js"
|
||||||
// export {EventEmitSelect} from "./event-emit-select.js"
|
export {EventEmitSelect} from "./event-emit-select.js"
|
||||||
export {ExpandToggle} from "./expand-toggle.js"
|
export {ExpandToggle} from "./expand-toggle.js"
|
||||||
export {HeaderMobileToggle} from "./header-mobile-toggle.js"
|
export {HeaderMobileToggle} from "./header-mobile-toggle.js"
|
||||||
// export {ImageManager} from "./image-manager.js"
|
export {ImageManager} from "./image-manager.js"
|
||||||
export {ImagePicker} from "./image-picker.js"
|
export {ImagePicker} from "./image-picker.js"
|
||||||
export {ListSortControl} from "./list-sort-control.js"
|
export {ListSortControl} from "./list-sort-control.js"
|
||||||
// export {MarkdownEditor} from "./markdown-editor.js"
|
export {MarkdownEditor} from "./markdown-editor.js"
|
||||||
export {NewUserPassword} from "./new-user-password.js"
|
export {NewUserPassword} from "./new-user-password.js"
|
||||||
export {Notification} from "./notification.js"
|
export {Notification} from "./notification.js"
|
||||||
export {OptionalInput} from "./optional-input.js"
|
export {OptionalInput} from "./optional-input.js"
|
||||||
export {PageComments} from "./page-comments.js"
|
export {PageComments} from "./page-comments.js"
|
||||||
export {PageDisplay} from "./page-display.js"
|
export {PageDisplay} from "./page-display.js"
|
||||||
// export {PageEditor} from "./page-editor.js"
|
export {PageEditor} from "./page-editor.js"
|
||||||
export {PagePicker} from "./page-picker.js"
|
export {PagePicker} from "./page-picker.js"
|
||||||
export {PermissionsTable} from "./permissions-table.js"
|
export {PermissionsTable} from "./permissions-table.js"
|
||||||
export {Pointer} from "./pointer.js";
|
export {Pointer} from "./pointer.js";
|
||||||
|
@ -46,13 +46,13 @@ export {SettingHomepageControl} from "./setting-homepage-control.js"
|
||||||
export {ShelfSort} from "./shelf-sort.js"
|
export {ShelfSort} from "./shelf-sort.js"
|
||||||
export {Shortcuts} from "./shortcuts"
|
export {Shortcuts} from "./shortcuts"
|
||||||
export {ShortcutInput} from "./shortcut-input"
|
export {ShortcutInput} from "./shortcut-input"
|
||||||
// export {SortableList} from "./sortable-list.js"
|
export {SortableList} from "./sortable-list.js"
|
||||||
export {SubmitOnChange} from "./submit-on-change.js"
|
export {SubmitOnChange} from "./submit-on-change.js"
|
||||||
// export {Tabs} from "./tabs.js"
|
export {Tabs} from "./tabs.js"
|
||||||
// export {TagManager} from "./tag-manager.js"
|
export {TagManager} from "./tag-manager.js"
|
||||||
// export {TemplateManager} from "./template-manager.js"
|
export {TemplateManager} from "./template-manager.js"
|
||||||
export {ToggleSwitch} from "./toggle-switch.js"
|
export {ToggleSwitch} from "./toggle-switch.js"
|
||||||
export {TriLayout} from "./tri-layout.js"
|
export {TriLayout} from "./tri-layout.js"
|
||||||
export {UserSelect} from "./user-select.js"
|
export {UserSelect} from "./user-select.js"
|
||||||
export {WebhookEvents} from "./webhook-events";
|
export {WebhookEvents} from "./webhook-events";
|
||||||
// export {WysiwygEditor} from "./wysiwyg-editor.js"
|
export {WysiwygEditor} from "./wysiwyg-editor.js"
|
|
@ -4,8 +4,9 @@ import Clipboard from "../services/clipboard";
|
||||||
import {debounce} from "../services/util";
|
import {debounce} from "../services/util";
|
||||||
import {patchDomFromHtmlString} from "../services/vdom";
|
import {patchDomFromHtmlString} from "../services/vdom";
|
||||||
import DrawIO from "../services/drawio";
|
import DrawIO from "../services/drawio";
|
||||||
|
import {Component} from "./component";
|
||||||
|
|
||||||
class MarkdownEditor {
|
export class MarkdownEditor extends Component {
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
this.elem = this.$el;
|
this.elem = this.$el;
|
||||||
|
@ -619,5 +620,3 @@ class MarkdownEditor {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MarkdownEditor ;
|
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
import * as Dates from "../services/dates";
|
import * as Dates from "../services/dates";
|
||||||
import {onSelect} from "../services/dom";
|
import {onSelect} from "../services/dom";
|
||||||
|
import {Component} from "./component";
|
||||||
|
|
||||||
/**
|
export class PageEditor extends Component {
|
||||||
* Page Editor
|
|
||||||
* @extends {Component}
|
|
||||||
*/
|
|
||||||
class PageEditor {
|
|
||||||
setup() {
|
setup() {
|
||||||
// Options
|
// Options
|
||||||
this.draftsEnabled = this.$opts.draftsEnabled === 'true';
|
this.draftsEnabled = this.$opts.draftsEnabled === 'true';
|
||||||
|
@ -207,6 +204,4 @@ class PageEditor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PageEditor;
|
|
|
@ -79,6 +79,4 @@ export class ShelfSort extends Component {
|
||||||
this.input.value = shelfBookElems.map(elem => elem.getAttribute('data-id')).join(',');
|
this.input.value = shelfBookElems.map(elem => elem.getAttribute('data-id')).join(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ShelfSort;
|
|
|
@ -1,4 +1,5 @@
|
||||||
import Sortable from "sortablejs";
|
import Sortable from "sortablejs";
|
||||||
|
import {Component} from "./component";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SortableList
|
* SortableList
|
||||||
|
@ -6,10 +7,8 @@ import Sortable from "sortablejs";
|
||||||
* Can have data set on the dragged items by setting a 'data-drag-content' attribute.
|
* Can have data set on the dragged items by setting a 'data-drag-content' attribute.
|
||||||
* This attribute must contain JSON where the keys are content types and the values are
|
* This attribute must contain JSON where the keys are content types and the values are
|
||||||
* the data to set on the data-transfer.
|
* the data to set on the data-transfer.
|
||||||
*
|
|
||||||
* @extends {Component}
|
|
||||||
*/
|
*/
|
||||||
class SortableList {
|
export class SortableList extends Component {
|
||||||
setup() {
|
setup() {
|
||||||
this.container = this.$el;
|
this.container = this.$el;
|
||||||
this.handleSelector = this.$opts.handleSelector;
|
this.handleSelector = this.$opts.handleSelector;
|
||||||
|
@ -34,6 +33,4 @@ class SortableList {
|
||||||
dragoverBubble: false,
|
dragoverBubble: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SortableList;
|
|
|
@ -1,11 +1,11 @@
|
||||||
|
import {onSelect} from "../services/dom";
|
||||||
|
import {Component} from "./component";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tabs
|
* Tabs
|
||||||
* Works by matching 'tabToggle<Key>' with 'tabContent<Key>' sections.
|
* Works by matching 'tabToggle<Key>' with 'tabContent<Key>' sections.
|
||||||
* @extends {Component}
|
|
||||||
*/
|
*/
|
||||||
import {onSelect} from "../services/dom";
|
export class Tabs extends Component {
|
||||||
|
|
||||||
class Tabs {
|
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
this.tabContentsByName = {};
|
this.tabContentsByName = {};
|
||||||
|
@ -46,6 +46,4 @@ class Tabs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Tabs;
|
|
|
@ -1,8 +1,6 @@
|
||||||
/**
|
import {Component} from "./component";
|
||||||
* TagManager
|
|
||||||
* @extends {Component}
|
export class TagManager extends Component {
|
||||||
*/
|
|
||||||
class TagManager {
|
|
||||||
setup() {
|
setup() {
|
||||||
this.addRemoveComponentEl = this.$refs.addRemove;
|
this.addRemoveComponentEl = this.$refs.addRemove;
|
||||||
this.container = this.$el;
|
this.container = this.$el;
|
||||||
|
@ -27,6 +25,4 @@ class TagManager {
|
||||||
});
|
});
|
||||||
return firstEmpty !== undefined;
|
return firstEmpty !== undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default TagManager;
|
|
|
@ -1,25 +1,48 @@
|
||||||
import * as DOM from "../services/dom";
|
import * as DOM from "../services/dom";
|
||||||
|
import {Component} from "./component";
|
||||||
|
|
||||||
class TemplateManager {
|
export class TemplateManager extends Component {
|
||||||
|
|
||||||
constructor(elem) {
|
setup() {
|
||||||
this.elem = elem;
|
this.container = this.$el;
|
||||||
this.list = elem.querySelector('[template-manager-list]');
|
this.list = this.$refs.list;
|
||||||
this.searching = false;
|
|
||||||
|
|
||||||
|
this.searchInput = this.$refs.searchInput;
|
||||||
|
this.searchButton = this.$refs.searchButton;
|
||||||
|
this.searchCancel = this.$refs.searchCancel;
|
||||||
|
|
||||||
|
this.setupListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
setupListeners() {
|
||||||
// Template insert action buttons
|
// Template insert action buttons
|
||||||
DOM.onChildEvent(this.elem, '[template-action]', 'click', this.handleTemplateActionClick.bind(this));
|
DOM.onChildEvent(this.container, '[template-action]', 'click', this.handleTemplateActionClick.bind(this));
|
||||||
|
|
||||||
// Template list pagination click
|
// Template list pagination click
|
||||||
DOM.onChildEvent(this.elem, '.pagination a', 'click', this.handlePaginationClick.bind(this));
|
DOM.onChildEvent(this.container, '.pagination a', 'click', this.handlePaginationClick.bind(this));
|
||||||
|
|
||||||
// Template list item content click
|
// Template list item content click
|
||||||
DOM.onChildEvent(this.elem, '.template-item-content', 'click', this.handleTemplateItemClick.bind(this));
|
DOM.onChildEvent(this.container, '.template-item-content', 'click', this.handleTemplateItemClick.bind(this));
|
||||||
|
|
||||||
// Template list item drag start
|
// Template list item drag start
|
||||||
DOM.onChildEvent(this.elem, '.template-item', 'dragstart', this.handleTemplateItemDragStart.bind(this));
|
DOM.onChildEvent(this.container, '.template-item', 'dragstart', this.handleTemplateItemDragStart.bind(this));
|
||||||
|
|
||||||
this.setupSearchBox();
|
// Search box enter press
|
||||||
|
this.searchInput.addEventListener('keypress', event => {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
event.preventDefault();
|
||||||
|
this.performSearch();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Search submit button press
|
||||||
|
this.searchButton.addEventListener('click', event => this.performSearch());
|
||||||
|
|
||||||
|
// Search cancel button press
|
||||||
|
this.searchCancel.addEventListener('click', event => {
|
||||||
|
this.searchInput.value = '';
|
||||||
|
this.performSearch();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTemplateItemClick(event, templateItem) {
|
handleTemplateItemClick(event, templateItem) {
|
||||||
|
@ -54,45 +77,12 @@ class TemplateManager {
|
||||||
this.list.innerHTML = resp.data;
|
this.list.innerHTML = resp.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
setupSearchBox() {
|
async performSearch() {
|
||||||
const searchBox = this.elem.querySelector('.search-box');
|
const searchTerm = this.searchInput.value;
|
||||||
|
const resp = await window.$http.get(`/templates`, {
|
||||||
// Search box may not exist if there are no existing templates in the system.
|
search: searchTerm
|
||||||
if (!searchBox) return;
|
|
||||||
|
|
||||||
const input = searchBox.querySelector('input');
|
|
||||||
const submitButton = searchBox.querySelector('button');
|
|
||||||
const cancelButton = searchBox.querySelector('button.search-box-cancel');
|
|
||||||
|
|
||||||
async function performSearch() {
|
|
||||||
const searchTerm = input.value;
|
|
||||||
const resp = await window.$http.get(`/templates`, {
|
|
||||||
search: searchTerm
|
|
||||||
});
|
|
||||||
cancelButton.style.display = searchTerm ? 'block' : 'none';
|
|
||||||
this.list.innerHTML = resp.data;
|
|
||||||
}
|
|
||||||
performSearch = performSearch.bind(this);
|
|
||||||
|
|
||||||
// Search box enter press
|
|
||||||
searchBox.addEventListener('keypress', event => {
|
|
||||||
if (event.key === 'Enter') {
|
|
||||||
event.preventDefault();
|
|
||||||
performSearch();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Submit button press
|
|
||||||
submitButton.addEventListener('click', event => {
|
|
||||||
performSearch();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Cancel button press
|
|
||||||
cancelButton.addEventListener('click', event => {
|
|
||||||
input.value = '';
|
|
||||||
performSearch();
|
|
||||||
});
|
});
|
||||||
|
this.searchCancel.style.display = searchTerm ? 'block' : 'none';
|
||||||
|
this.list.innerHTML = resp.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default TemplateManager;
|
|
|
@ -1,6 +1,7 @@
|
||||||
import {build as buildEditorConfig} from "../wysiwyg/config";
|
import {build as buildEditorConfig} from "../wysiwyg/config";
|
||||||
|
import {Component} from "./component";
|
||||||
|
|
||||||
class WysiwygEditor {
|
export class WysiwygEditor extends Component {
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
this.elem = this.$el;
|
this.elem = this.$el;
|
||||||
|
@ -35,6 +36,4 @@ class WysiwygEditor {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default WysiwygEditor;
|
|
|
@ -44,7 +44,9 @@ export function register(editor) {
|
||||||
|
|
||||||
// Link selector shortcut
|
// Link selector shortcut
|
||||||
editor.shortcuts.add('meta+shift+K', '', function() {
|
editor.shortcuts.add('meta+shift+K', '', function() {
|
||||||
window.EntitySelectorPopup.show(function(entity) {
|
/** @var {EntitySelectorPopup} **/
|
||||||
|
const selectorPopup = window.$components.first('entity-selector-popup');
|
||||||
|
selectorPopup.show(function(entity) {
|
||||||
|
|
||||||
if (editor.selection.isCollapsed()) {
|
if (editor.selection.isCollapsed()) {
|
||||||
editor.insertContent(editor.dom.createHTML('a', {href: entity.link}, editor.dom.encode(entity.name)));
|
editor.insertContent(editor.dom.createHTML('a', {href: entity.link}, editor.dom.encode(entity.name)));
|
||||||
|
|
|
@ -278,16 +278,16 @@ body.tox-fullscreen, body.markdown-fullscreen {
|
||||||
&.open {
|
&.open {
|
||||||
width: 480px;
|
width: 480px;
|
||||||
}
|
}
|
||||||
[toolbox-toggle] svg {
|
.toolbox-toggle svg {
|
||||||
transition: transform ease-in-out 180ms;
|
transition: transform ease-in-out 180ms;
|
||||||
}
|
}
|
||||||
[toolbox-toggle] {
|
.toolbox-toggle {
|
||||||
transition: background-color ease-in-out 180ms;
|
transition: background-color ease-in-out 180ms;
|
||||||
}
|
}
|
||||||
&.open [toolbox-toggle] {
|
&.open .toolbox-toggle {
|
||||||
background-color: rgba(255, 0, 0, 0.29);
|
background-color: rgba(255, 0, 0, 0.29);
|
||||||
}
|
}
|
||||||
&.open [toolbox-toggle] svg {
|
&.open .toolbox-toggle svg {
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
}
|
}
|
||||||
> div {
|
> div {
|
||||||
|
@ -357,7 +357,7 @@ body.tox-fullscreen, body.markdown-fullscreen {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[toolbox-tab-content] {
|
.toolbox-tab-content {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
<div style="display: block;" toolbox-tab-content="files"
|
<div style="display: block;"
|
||||||
|
refs="editor-toolbox@tab-content"
|
||||||
|
data-tab-content="files"
|
||||||
component="attachments"
|
component="attachments"
|
||||||
option:attachments:page-id="{{ $page->id ?? 0 }}">
|
option:attachments:page-id="{{ $page->id ?? 0 }}"
|
||||||
|
class="toolbox-tab-content">
|
||||||
|
|
||||||
<h4>{{ trans('entities.attachments') }}</h4>
|
<h4>{{ trans('entities.attachments') }}</h4>
|
||||||
<div class="px-l files">
|
<div class="px-l files">
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
<div editor-toolbox class="floating-toolbox">
|
<div component="editor-toolbox" class="floating-toolbox">
|
||||||
|
|
||||||
<div class="tabs primary-background-light">
|
<div class="tabs primary-background-light">
|
||||||
<button type="button" toolbox-toggle aria-expanded="false">@icon('caret-left-circle')</button>
|
<button type="button" refs="editor-toolbox@toggle" aria-expanded="false" class="toolbox-toggle">@icon('caret-left-circle')</button>
|
||||||
<button type="button" toolbox-tab-button="tags" title="{{ trans('entities.page_tags') }}" class="active">@icon('tag')</button>
|
<button type="button" refs="editor-toolbox@tab-button" data-tab="tags" title="{{ trans('entities.page_tags') }}" class="active">@icon('tag')</button>
|
||||||
@if(userCan('attachment-create-all'))
|
@if(userCan('attachment-create-all'))
|
||||||
<button type="button" toolbox-tab-button="files" title="{{ trans('entities.attachments') }}">@icon('attach')</button>
|
<button type="button" refs="editor-toolbox@tab-button" data-tab="files" title="{{ trans('entities.attachments') }}">@icon('attach')</button>
|
||||||
@endif
|
@endif
|
||||||
<button type="button" toolbox-tab-button="templates" title="{{ trans('entities.templates') }}">@icon('template')</button>
|
<button type="button" refs="editor-toolbox@tab-button" data-tab="templates" title="{{ trans('entities.templates') }}">@icon('template')</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div toolbox-tab-content="tags">
|
<div refs="editor-toolbox@tab-content" data-tab-content="tags" class="toolbox-tab-content">
|
||||||
<h4>{{ trans('entities.page_tags') }}</h4>
|
<h4>{{ trans('entities.page_tags') }}</h4>
|
||||||
<div class="px-l">
|
<div class="px-l">
|
||||||
@include('entities.tag-manager', ['entity' => $page])
|
@include('entities.tag-manager', ['entity' => $page])
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
@include('attachments.manager', ['page' => $page])
|
@include('attachments.manager', ['page' => $page])
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<div toolbox-tab-content="templates">
|
<div refs="editor-toolbox@tab-content" data-tab-content="templates" class="toolbox-tab-content">
|
||||||
<h4>{{ trans('entities.templates') }}</h4>
|
<h4>{{ trans('entities.templates') }}</h4>
|
||||||
|
|
||||||
<div class="px-l">
|
<div class="px-l">
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<div template-manager>
|
<div component="template-manager">
|
||||||
@if(userCan('templates-manage'))
|
@if(userCan('templates-manage'))
|
||||||
<p class="text-muted small mb-none">
|
<p class="text-muted small mb-none">
|
||||||
{{ trans('entities.templates_explain_set_as_template') }}
|
{{ trans('entities.templates_explain_set_as_template') }}
|
||||||
|
@ -11,15 +11,13 @@
|
||||||
<hr>
|
<hr>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if(count($templates) > 0)
|
<div class="search-box flexible mb-m" style="display: {{ count($templates) > 0 ? 'block' : 'none' }}">
|
||||||
<div class="search-box flexible mb-m">
|
<input refs="template-manager@searchInput" type="text" name="template-search" placeholder="{{ trans('common.search') }}">
|
||||||
<input type="text" name="template-search" placeholder="{{ trans('common.search') }}">
|
<button refs="template-manager@searchButton" type="button">@icon('search')</button>
|
||||||
<button type="button">@icon('search')</button>
|
<button refs="template-manager@searchCancel" class="search-box-cancel text-neg" type="button" style="display: none">@icon('close')</button>
|
||||||
<button class="search-box-cancel text-neg hidden" type="button">@icon('close')</button>
|
</div>
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<div template-manager-list>
|
<div refs="template-manager@list">
|
||||||
@include('pages.parts.template-manager-list', ['templates' => $templates])
|
@include('pages.parts.template-manager-list', ['templates' => $templates])
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
Loading…
Add table
Add a link
Reference in a new issue