mirror of
https://hk.gh-proxy.com/https://github.com/NodeBB/nodebb-plugin-composer-quill.git
synced 2025-10-03 21:21:41 +08:00
feat: update for nodeb 3.2 and up
This commit is contained in:
parent
35a7576fcd
commit
be542b5159
14 changed files with 304 additions and 183 deletions
|
@ -11,6 +11,7 @@ Controllers.renderAdminPage = function (req, res, next) {
|
|||
}
|
||||
|
||||
res.render('admin/plugins/composer-quill', {
|
||||
title: 'Quill Composer',
|
||||
checks: checks,
|
||||
});
|
||||
});
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
},
|
||||
"readmeFilename": "README.md",
|
||||
"nbbpm": {
|
||||
"compatibility": "^1.17.0 || ^2.0.0"
|
||||
"compatibility": "^3.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "^3.2.0",
|
||||
|
|
11
plugin.json
11
plugin.json
|
@ -15,11 +15,11 @@
|
|||
{ "hook": "filter:messaging.getFields", "method": "handleMessageEdit" },
|
||||
{ "hook": "filter:messaging.checkContent", "method": "handleMessageCheck" }
|
||||
],
|
||||
"less": [
|
||||
"../nodebb-plugin-composer-default/static/less/composer.less",
|
||||
"./static/less/quill.less",
|
||||
"./static/less/post.less",
|
||||
"./static/less/overrides.less"
|
||||
"scss": [
|
||||
"../nodebb-plugin-composer-default/static/scss/composer.scss",
|
||||
"./static/scss/quill.scss",
|
||||
"./static/scss/post.scss",
|
||||
"./static/scss/overrides.scss"
|
||||
],
|
||||
"modules": {
|
||||
"quill.js": "./node_modules/quill/dist/quill.js",
|
||||
|
@ -36,6 +36,7 @@
|
|||
"composer/tags.js": "../nodebb-plugin-composer-default/static/lib/composer/tags.js",
|
||||
"composer/uploads.js": "../nodebb-plugin-composer-default/static/lib/composer/uploads.js",
|
||||
"composer/autocomplete.js": "../nodebb-plugin-composer-default/static/lib/composer/autocomplete.js",
|
||||
"composer/post-queue.js": "../nodebb-plugin-composer-default/static/lib/composer/post-queue.js",
|
||||
"../admin/plugins/composer-quill.js": "./static/lib/admin.js"
|
||||
},
|
||||
"scripts": [
|
||||
|
|
|
@ -23,21 +23,36 @@ $(document).ready(() => {
|
|||
$(window).on('action:composer.topic.new', (ev, data) => {
|
||||
composer.newTopic({
|
||||
cid: data.cid,
|
||||
title: data.title || '',
|
||||
body: data.body || '',
|
||||
tags: data.tags || [],
|
||||
});
|
||||
});
|
||||
|
||||
$(window).on('action:composer.post.edit', (ev, data) => {
|
||||
composer.editPost({ pid: data.pid });
|
||||
});
|
||||
|
||||
$(window).on('action:composer.post.new', (ev, data) => {
|
||||
data.body = data.body || data.text;
|
||||
data.title = data.title || data.topicName;
|
||||
composer.newReply({
|
||||
tid: data.tid,
|
||||
toPid: data.pid,
|
||||
title: data.title,
|
||||
body: data.body,
|
||||
});
|
||||
});
|
||||
|
||||
$(window).on('action:composer.post.edit', (ev, data) => {
|
||||
composer.editPost(data.pid);
|
||||
});
|
||||
|
||||
$(window).on('action:composer.post.new', (ev, data) => {
|
||||
composer.newReply(data.tid, data.pid, data.topicName, data.text);
|
||||
});
|
||||
|
||||
$(window).on('action:composer.addQuote', (ev, data) => {
|
||||
composer.newReply(data.tid, data.pid, data.topicName, wrapWithBlockquote(data.text));
|
||||
data.title = data.title || data.topicName;
|
||||
data.body = data.body || data.text;
|
||||
composer.newReply({
|
||||
tid: data.tid,
|
||||
toPid: data.pid,
|
||||
title: data.title,
|
||||
body: wrapWithBlockquote(data.body),
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -281,7 +281,7 @@ window.quill.init = function (targetEl, data, callback) {
|
|||
if (className === 'picture') {
|
||||
buttonEl.html('<i class="fa fa-file-image-o"></i>');
|
||||
} else {
|
||||
buttonEl.html('<span class="fa-stack"><i class="fa fa-file-o fa-stack-1x"></i><i class="fa fa-arrow-up fa-stack-1x"></i></span>');
|
||||
buttonEl.html('<i class="fa fa-file-o"></i>');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
31
static/scss/overrides.scss
Normal file
31
static/scss/overrides.scss
Normal file
|
@ -0,0 +1,31 @@
|
|||
.composer {
|
||||
.formatting-bar {
|
||||
display: none!important;
|
||||
}
|
||||
|
||||
.write-container {
|
||||
width: 100%!important;
|
||||
min-width: 0px; // fixes negation of overflow-wrap due this being a flex-item
|
||||
|
||||
textarea {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ql-toolbar {
|
||||
button > i {
|
||||
float: left;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
[component="chat/composer"] {
|
||||
.ql-editor {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
[component="chat/input"] {
|
||||
display: none;
|
||||
}
|
||||
}
|
19
static/scss/post.scss
Normal file
19
static/scss/post.scss
Normal file
|
@ -0,0 +1,19 @@
|
|||
[component="post/content"], [component="chat/messages"] {
|
||||
.ql-align-center {
|
||||
text-align: center;
|
||||
}
|
||||
.ql-align-right {
|
||||
text-align: right;
|
||||
}
|
||||
.ql-align-justify {
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
// Fonts
|
||||
.ql-font-serif {
|
||||
font-family: Georgia, "Times New Roman", serif;
|
||||
}
|
||||
.ql-font-monospace {
|
||||
font-family: Monaco, "Courier New", monospace;
|
||||
}
|
||||
}
|
4
static/scss/quill.scss
Normal file
4
static/scss/quill.scss
Normal file
|
@ -0,0 +1,4 @@
|
|||
// @import './quill/dist/quill.snow';
|
||||
// @import './quill/dist/quill.bubble';
|
||||
@import 'nodebb-plugin-composer-quill/node_modules/quill/dist/quill.snow';
|
||||
@import 'nodebb-plugin-composer-quill/node_modules/quill/dist/quill.bubble';
|
|
@ -1,54 +1,60 @@
|
|||
<div class="row">
|
||||
<div class="col-lg-8 col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Quill Composer</div>
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
<a href="https://quilljs.com/">Quill</a> is a free, open source WYSIWYG editor built for the modern web. With its modular architecture and expressive API, it is completely customizable to fit any need.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4 col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Migration</div>
|
||||
<div class="panel-body">
|
||||
<div class="acp-page-container">
|
||||
<style>#save {display: none;}</style>
|
||||
<!-- IMPORT admin/partials/settings/header.tpl -->
|
||||
|
||||
<div class="row m-0">
|
||||
<div id="spy-container" class="col-12 col-md-8 px-0 mb-4" tabindex="0">
|
||||
<p>
|
||||
<a href="https://quilljs.com/">Quill</a> is a free, open source WYSIWYG editor built for the modern web. With its modular architecture and expressive API, it is completely customizable to fit any need.
|
||||
</p>
|
||||
|
||||
<hr/>
|
||||
|
||||
<div>
|
||||
<h5>Migration</h5>
|
||||
|
||||
<p>
|
||||
If you are switching to Quill from a different composer (i.e. composer-default/markdown), you will need to convert your existing posts to Quill's format. You may use the utilities below to do so.
|
||||
</p>
|
||||
|
||||
<button class="btn btn-block btn-default" data-action="migrate/in">Migrate to Quill <i class="fa fa-arrow-circle-o-left"></i></button>
|
||||
<button class="btn btn-block btn-default" data-action="migrate/out">Migrate from Quill <i class="fa fa-arrow-circle-o-right"></i></button>
|
||||
<button class="btn btn-light" data-action="migrate/in">Migrate to Quill <i class="fa fa-arrow-circle-o-left"></i></button>
|
||||
<button class="btn btn-light" data-action="migrate/out">Migrate from Quill <i class="fa fa-arrow-circle-o-right"></i></button>
|
||||
</div>
|
||||
</div><div class="panel panel-default">
|
||||
<div class="panel-heading">Compatibility Checks</div>
|
||||
<div class="panel-body">
|
||||
|
||||
<hr />
|
||||
|
||||
<div>
|
||||
<h5>Compatibility Checks</h5>
|
||||
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item list-group-item-<!-- IF checks.markdown -->success<!-- ELSE -->danger<!-- ENDIF checks.markdown -->">
|
||||
<li class="list-group-item list-group-item-{{{ if checks.markdown }}}success{{{ else }}}danger{{{ end }}}">
|
||||
<strong>Markdown Compatibility</strong>
|
||||
<!-- IF checks.markdown -->
|
||||
<span class="badge"><i class="fa fa-check"></i></span>
|
||||
{{{ if checks.markdown }}}
|
||||
<i class="fa fa-check"></i>
|
||||
<p>The Markdown plugin is either disabled, or HTML sanitization is disabled</p>
|
||||
<!-- ELSE -->
|
||||
<span class="badge"><i class="fa fa-times"></i></span>
|
||||
{{{ else }}}
|
||||
<i class="fa fa-times"></i>
|
||||
<p>
|
||||
In order to render post content correctly, the Markdown plugin needs to have HTML sanitization disabled,
|
||||
or the entire plugin should be disabled altogether.
|
||||
</p>
|
||||
<!-- ENDIF checks.markdown -->
|
||||
{{{ end }}}
|
||||
</li>
|
||||
<li class="list-group-item list-group-item-<!-- IF checks.composer -->success<!-- ELSE -->danger<!-- ENDIF checks.composer -->">
|
||||
<li class="list-group-item list-group-item-{{{ if checks.composer }}}success{{{ else }}}danger{{{ end }}}">
|
||||
<strong>Composer Conflicts</strong>
|
||||
<!-- IF checks.composer -->
|
||||
<span class="badge"><i class="fa fa-check"></i></span>
|
||||
{{{ if checks.composer }}}
|
||||
<i class="fa fa-check"></i>
|
||||
<p>Great! Looks like Quill is the only composer active</p>
|
||||
<!-- ELSE -->
|
||||
<span class="badge"><i class="fa fa-times"></i></span>
|
||||
{{{ else }}}
|
||||
<i class="fa fa-times"></i>
|
||||
<p>Quill must be the only composer active. Please disable other composers and reload NodeBB.</p>
|
||||
<!-- ENDIF checks.composer -->
|
||||
{{{ end }}}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- IMPORT admin/partials/settings/toc.tpl -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,155 +1,46 @@
|
|||
<div component="composer" class="composer<!-- IF resizable --> resizable<!-- ENDIF resizable --><!-- IF !isTopicOrMain --> reply<!-- ENDIF !isTopicOrMain -->">
|
||||
|
||||
<div class="composer-container">
|
||||
<nav class="navbar navbar-fixed-top mobile-navbar hidden-md hidden-lg">
|
||||
<div component="composer" class="composer {{{ if resizable }}} resizable{{{ end }}}{{{ if !isTopicOrMain }}} reply{{{ end }}}">
|
||||
<div class="composer-container d-flex flex-column gap-1 h-100">
|
||||
<!-- mobile header -->
|
||||
<nav class="navbar fixed-top mobile-navbar hidden-md hidden-lg text-bg-primary flex-nowrap gap-1 px-1">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-primary composer-discard" data-action="discard" tabindex="-1"><i class="fa fa-times"></i></button>
|
||||
<button class="btn btn-sm btn-primary composer-minimize" data-action="minimize" tabindex="-1"><i class="fa fa-minus"></i></button>
|
||||
<button class="btn btn-sm btn-primary composer-discard" data-action="discard" tabindex="-1"><i class="fa fa-fw fa-times"></i></button>
|
||||
<button class="btn btn-sm btn-primary composer-minimize" data-action="minimize" tabindex="-1"><i class="fa fa-fw fa-minus"></i></button>
|
||||
</div>
|
||||
<!-- IF isTopic -->
|
||||
{{{ if isTopic }}}
|
||||
<div class="category-name-container">
|
||||
<span class="category-name"></span> <i class="fa fa-sort"></i>
|
||||
</div>
|
||||
<!-- ENDIF isTopic -->
|
||||
<!-- IF !isTopicOrMain -->
|
||||
<h4 class="title">[[topic:composer.replying_to, "{title}"]]</h4>
|
||||
<!-- ENDIF !isTopicOrMain -->
|
||||
<div class="display-scheduler pull-right{{{ if !canSchedule }}} hidden{{{ end }}}">
|
||||
{{{ end }}}
|
||||
{{{ if !isTopicOrMain }}}
|
||||
<h4 class="title text-bg-primary">{{{ if isEditing }}}[[topic:composer.editing-in, "{topicTitle}"]]{{{ else }}}[[topic:composer.replying-to, "{topicTitle}"]]{{{ end }}}</h4>
|
||||
{{{ end }}}
|
||||
<div class="display-scheduler p-2 {{{ if !canSchedule }}} hidden{{{ end }}}">
|
||||
<i class="fa fa-clock-o"></i>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-primary composer-submit" data-action="post" tabindex="-1"><i class="fa fa-chevron-right"></i></button>
|
||||
<button class="btn btn-sm btn-primary composer-submit" data-action="post" tabindex="-1"><i class="fa fa-fw fa-chevron-right"></i></button>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="row title-container">
|
||||
<!-- IF showHandleInput -->
|
||||
<div data-component="composer/handle">
|
||||
<input class="handle form-control" type="text" tabindex="1" placeholder="[[topic:composer.handle_placeholder]]" value="{handle}" />
|
||||
</div>
|
||||
<!-- ENDIF showHandleInput -->
|
||||
<div data-component="composer/title">
|
||||
<!-- IF isTopicOrMain -->
|
||||
<input class="title form-control" type="text" tabindex="1" placeholder="[[topic:composer.title_placeholder]]" value="{title}"/>
|
||||
<!-- ELSE -->
|
||||
<span class="title form-control">[[topic:composer.replying_to, "{title}"]]</span>
|
||||
<!-- ENDIF isTopicOrMain -->
|
||||
<div id="quick-search-container" class="quick-search-container hidden">
|
||||
<div class="quick-search-results-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-2 d-flex flex-column gap-1 h-100">
|
||||
<!-- IMPORT partials/composer-title-container.tpl -->
|
||||
|
||||
{{{ if isTopic }}}
|
||||
<div class="category-list-container hidden-sm hidden-xs">
|
||||
<!-- IMPORT partials/category-selector.tpl -->
|
||||
</div>
|
||||
<!-- IMPORT partials/composer-formatting.tpl -->
|
||||
|
||||
<!-- IMPORT partials/composer-write-preview.tpl -->
|
||||
|
||||
{{{ if isTopicOrMain }}}
|
||||
<!-- IMPORT partials/composer-tags.tpl -->
|
||||
{{{ end }}}
|
||||
|
||||
<div class="pull-right draft-icon hidden-xs hidden-sm"></div>
|
||||
<div class="imagedrop"><div>[[topic:composer.drag-and-drop-images]]</div></div>
|
||||
|
||||
<div class="display-scheduler pull-right hidden-sm hidden-xs{{{ if !canSchedule }}} hidden{{{ end }}}">
|
||||
<i class="fa fa-clock-o"></i>
|
||||
</div>
|
||||
|
||||
<div class="btn-group pull-right action-bar hidden-sm hidden-xs">
|
||||
<button class="btn btn-default composer-discard" data-action="discard" tabindex="-1"><i class="fa fa-times"></i> [[topic:composer.discard]]</button>
|
||||
|
||||
<button class="btn btn-primary composer-submit" data-action="post" tabindex="6" data-text-variant=" [[topic:composer.schedule]]"><i class="fa fa-check"></i> [[topic:composer.submit]]</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="category-tag-row">
|
||||
<div class="btn-toolbar formatting-bar">
|
||||
<ul class="formatting-group">
|
||||
<!-- BEGIN formatting -->
|
||||
<!-- IF formatting.spacer -->
|
||||
<li class="spacer"></li>
|
||||
<!-- ELSE -->
|
||||
<!-- IF !formatting.mobile -->
|
||||
<li tabindex="-1" data-format="{formatting.name}" title="{formatting.title}"><i class="{formatting.className}"></i></li>
|
||||
<!-- ENDIF !formatting.mobile -->
|
||||
<!-- ENDIF formatting.spacer -->
|
||||
<!-- END formatting -->
|
||||
|
||||
<!--[if gte IE 9]><!-->
|
||||
<!-- IF privileges.upload:post:image -->
|
||||
<li class="img-upload-btn hide" data-format="picture" tabindex="-1" title="[[modules:composer.upload-picture]]">
|
||||
<i class="fa fa-file-image-o"></i>
|
||||
</li>
|
||||
<!-- ENDIF privileges.upload:post:image -->
|
||||
<!-- IF privileges.upload:post:file -->
|
||||
<li class="file-upload-btn hide" data-format="upload" tabindex="-1" title="[[modules:composer.upload-file]]">
|
||||
<span class="fa-stack">
|
||||
<i class="fa fa-file-o fa-stack-1x"></i>
|
||||
<i class="fa fa-arrow-up fa-stack-1x"></i>
|
||||
</span>
|
||||
</li>
|
||||
<!-- ENDIF privileges.upload:post:file -->
|
||||
<!--<![endif]-->
|
||||
|
||||
<!-- IF allowTopicsThumbnail -->
|
||||
<li tabindex="-1">
|
||||
<i class="fa fa-th-large topic-thumb-btn topic-thumb-toggle-btn hide" title="[[topic:composer.thumb_title]]"></i>
|
||||
</li>
|
||||
<div class="topic-thumb-container center-block hide">
|
||||
<form id="thumbForm" method="post" class="topic-thumb-form form-inline" enctype="multipart/form-data">
|
||||
<img class="topic-thumb-preview"></img>
|
||||
<div class="form-group">
|
||||
<label for="topic-thumb-url">[[topic:composer.thumb_url_label]]</label>
|
||||
<input type="text" id="topic-thumb-url" class="form-control" placeholder="[[topic:composer.thumb_url_placeholder]]" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="topic-thumb-file">[[topic:composer.thumb_file_label]]</label>
|
||||
<input type="file" id="topic-thumb-file" class="form-control" />
|
||||
</div>
|
||||
<div class="form-group topic-thumb-ctrl">
|
||||
<i class="fa fa-spinner fa-spin hide topic-thumb-spinner" title="[[topic:composer.uploading]]"></i>
|
||||
<i class="fa fa-times topic-thumb-btn hide topic-thumb-clear-btn" title="[[topic:composer.thumb_remove]]"></i>
|
||||
</div>
|
||||
</form>
|
||||
<div class="resizer position-absolute w-100 bottom-100 pe-3 border-bottom">
|
||||
<div class="trigger text-center">
|
||||
<div class="handle d-inline-block px-2 py-1 border bg-body">
|
||||
<i class="fa fa-fw fa-up-down"></i>
|
||||
</div>
|
||||
<!-- ENDIF allowTopicsThumbnail -->
|
||||
|
||||
<form id="fileForm" method="post" enctype="multipart/form-data">
|
||||
<!--[if gte IE 9]><!-->
|
||||
<input type="file" id="files" name="files[]" multiple class="gte-ie9 hide"/>
|
||||
<!--<![endif]-->
|
||||
<!--[if lt IE 9]>
|
||||
<input type="file" id="files" name="files[]" class="lt-ie9 hide" value="Upload"/>
|
||||
<![endif]-->
|
||||
</form>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row write-preview-container">
|
||||
<div class="write-container">
|
||||
<div></div>
|
||||
<textarea></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- IF isTopicOrMain -->
|
||||
<div class="tag-row">
|
||||
<div class="tags-container">
|
||||
<div class="btn-group dropup <!-- IF !tagWhitelist.length -->hidden<!-- ENDIF !tagWhitelist.length -->" component="composer/tag/dropdown">
|
||||
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown" type="button">
|
||||
<span class="visible-sm-inline visible-md-inline visible-lg-inline"><i class="fa fa-tags"></i></span>
|
||||
[[tags:select_tags]]
|
||||
</button>
|
||||
|
||||
<ul class="dropdown-menu">
|
||||
<!-- BEGIN tagWhitelist -->
|
||||
<li data-tag="{@value}"><a href="#">{@value}</a></li>
|
||||
<!-- END tagWhitelist -->
|
||||
</ul>
|
||||
</div>
|
||||
<input class="tags" type="text" class="form-control" placeholder="[[tags:enter_tags_here, {minimumTagLength}, {maximumTagLength}]]" tabindex="5"/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ENDIF isTopicOrMain -->
|
||||
|
||||
<div class="imagedrop"><div>[[topic:composer.drag_and_drop_images]]</div></div>
|
||||
|
||||
<div class="resizer"><div class="trigger text-center"><i class="fa"></i></div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
75
static/templates/partials/composer-formatting.tpl
Normal file
75
static/templates/partials/composer-formatting.tpl
Normal file
|
@ -0,0 +1,75 @@
|
|||
<div class="d-flex justify-content-between gap-2 align-items-center formatting-bar m-0">
|
||||
<ul class="list-unstyled mb-0 d-flex formatting-group gap-2 overflow-auto">
|
||||
{{{ each formatting }}}
|
||||
{{{ if ./spacer }}}
|
||||
<li class="small spacer"></li>
|
||||
{{{ else }}}
|
||||
{{{ if (./visibility.desktop && ((isTopicOrMain && ./visibility.main) || (!isTopicOrMain && ./visibility.reply))) }}}
|
||||
{{{ if ./dropdownItems.length }}}
|
||||
<li class="dropdown bottom-sheet" title="{./title}">
|
||||
<button class="btn btn-sm btn-link text-reset" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" aria-label="{./title}">
|
||||
<i class="{./className}"></i>
|
||||
</button>
|
||||
<ul class="dropdown-menu p-1" role="menu">
|
||||
{{{ each ./dropdownItems }}}
|
||||
<li>
|
||||
<a href="#" data-format="{./name}" class="dropdown-item rounded-1 position-relative" role="menuitem">
|
||||
<i class="{./className} text-secondary"></i> {./text}
|
||||
{{{ if ./badge }}}
|
||||
<span class="px-1 position-absolute top-0 start-100 translate-middle badge rounded text-bg-info"></span>
|
||||
{{{ end }}}
|
||||
</a>
|
||||
</li>
|
||||
{{{ end }}}
|
||||
</ul>
|
||||
</li>
|
||||
{{{ else }}}
|
||||
<li title="{./title}">
|
||||
<button data-format="{./name}" class="btn btn-sm btn-link text-reset position-relative" aria-label="{./title}">
|
||||
<i class="{./className}"></i>
|
||||
{{{ if ./badge }}}
|
||||
<span class="px-1 position-absolute top-0 start-100 translate-middle badge rounded text-bg-info"></span>
|
||||
{{{ end }}}
|
||||
</button>
|
||||
</li>
|
||||
{{{ end }}}
|
||||
{{{ end }}}
|
||||
{{{ end }}}
|
||||
{{{ end }}}
|
||||
|
||||
{{{ if privileges.upload:post:image }}}
|
||||
<li title="[[modules:composer.upload-picture]]">
|
||||
<button data-format="picture" class="img-upload-btn btn btn-sm btn-link text-reset" aria-label="[[modules:composer.upload-picture]]">
|
||||
<i class="fa fa-file-image-o"></i>
|
||||
</button>
|
||||
</li>
|
||||
{{{ end }}}
|
||||
|
||||
{{{ if privileges.upload:post:file }}}
|
||||
<li title="[[modules:composer.upload-file]]">
|
||||
<button data-format="upload" class="file-upload-btn btn btn-sm btn-link text-reset" aria-label="[[modules:composer.upload-file]]">
|
||||
<i class="fa fa-file-o"></i>
|
||||
</button>
|
||||
</li>
|
||||
{{{ end }}}
|
||||
|
||||
<form id="fileForm" method="post" enctype="multipart/form-data">
|
||||
<input type="file" id="files" name="files[]" multiple class="hide"/>
|
||||
</form>
|
||||
</ul>
|
||||
<div class="d-flex align-items-center gap-1">
|
||||
<div class="draft-icon m-2 hidden-xs hidden-sm"></div>
|
||||
<button class="btn btn-sm btn-link py-2 text-body fw-semibold text-nowrap" data-action="preview">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span class="d-none d-md-inline show-text">[[modules:composer.show-preview]]</span>
|
||||
<span class="d-none d-md-inline hide-text">[[modules:composer.hide-preview]]</span>
|
||||
</button>
|
||||
{{{ if composer:showHelpTab }}}
|
||||
<button class="btn btn-sm btn-link py-2 text-body fw-semibold text-nowrap" data-action="help">
|
||||
<i class="fa fa-question"></i>
|
||||
<span class="d-none d-md-inline">[[modules:composer.help]]</span>
|
||||
</button>
|
||||
{{{ end }}}
|
||||
</div>
|
||||
</div>
|
||||
|
17
static/templates/partials/composer-tags.tpl
Normal file
17
static/templates/partials/composer-tags.tpl
Normal file
|
@ -0,0 +1,17 @@
|
|||
<div class="tag-row">
|
||||
<div class="tags-container d-flex align-items-center {{{ if tagWhitelist.length }}}haswhitelist{{{ end }}}">
|
||||
<div class="btn-group dropup me-2 {{{ if !tagWhitelist.length }}}hidden{{{ end }}}" component="composer/tag/dropdown">
|
||||
<button class="btn btn-sm btn-link text-body dropdown-toggle" data-bs-toggle="dropdown" type="button" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="visible-sm-inline visible-md-inline visible-lg-inline"><i class="fa fa-tags"></i></span>
|
||||
[[tags:select-tags]]
|
||||
</button>
|
||||
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<!-- BEGIN tagWhitelist -->
|
||||
<li data-tag="{@value}"><a class="dropdown-item" href="#" role="menuitem">{@value}</a></li>
|
||||
<!-- END tagWhitelist -->
|
||||
</ul>
|
||||
</div>
|
||||
<input class="tags" type="text" class="" placeholder="[[tags:enter-tags-here, {minimumTagLength}, {maximumTagLength}]]" />
|
||||
</div>
|
||||
</div>
|
46
static/templates/partials/composer-title-container.tpl
Normal file
46
static/templates/partials/composer-title-container.tpl
Normal file
|
@ -0,0 +1,46 @@
|
|||
<div class="title-container align-items-center gap-2 d-flex">
|
||||
{{{ if isTopic }}}
|
||||
<div class="category-list-container {{{ if !template.compose }}}d-none d-md-block{{{ end }}} align-self-center">
|
||||
<!-- IMPORT partials/category/selector-dropdown-left.tpl -->
|
||||
</div>
|
||||
{{{ end }}}
|
||||
|
||||
{{{ if showHandleInput }}}
|
||||
<div data-component="composer/handle">
|
||||
<input class="handle form-control h-100 border-0 shadow-none" type="text" placeholder="[[topic:composer.handle-placeholder]]" value="{handle}" />
|
||||
</div>
|
||||
{{{ end }}}
|
||||
|
||||
<div data-component="composer/title" class="position-relative flex-1" style="min-width: 0;">
|
||||
{{{ if isTopicOrMain }}}
|
||||
<input class="title form-control h-100 rounded-1 shadow-none" type="text" placeholder="[[topic:composer.title-placeholder]]" value="{topicTitle}" />
|
||||
{{{ else }}}
|
||||
<span class="{{{ if !template.compose }}}d-none d-md-block{{{ else }}}d-block{{{ end }}} title h-100 text-truncate">{{{ if isEditing }}}[[topic:composer.editing-in, "{topicTitle}"]]{{{ else }}}[[topic:composer.replying-to, "{topicTitle}"]]{{{ end }}}</span>
|
||||
{{{ end }}}
|
||||
<div id="quick-search-container" class="quick-search-container mt-2 dropdown-menu d-block p-2 hidden">
|
||||
<div class="text-center loading-indicator"><i class="fa fa-spinner fa-spin"></i></div>
|
||||
<div class="quick-search-results-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="{{{ if !template.compose }}}d-none d-md-flex{{{ else }}}d-flex{{{ end }}} action-bar gap-1 align-items-center">
|
||||
<button class="btn btn-sm btn-link text-body fw-semibold composer-minimize" data-action="hide"><i class="fa fa-angle-down"></i> <span class="d-none d-md-inline">[[topic:composer.hide]]</span></button>
|
||||
<button class="btn btn-sm btn-link composer-discard text-body fw-semibold" data-action="discard"><i class="fa fa-trash"></i> <span class="d-none d-md-inline">[[topic:composer.discard]]</button>
|
||||
<div class="btn-group btn-group-sm" component="composer/submit/container">
|
||||
<button class="btn btn-primary composer-submit fw-bold {{{ if !(submitOptions.length || canSchedule) }}}rounded-1{{{ end }}}" data-action="post" data-text-variant=" [[topic:composer.schedule]]"><i class="fa fa-check"></i> <span class="d-none d-md-inline">[[topic:composer.submit]]</span></button>
|
||||
<div component="composer/submit/options/container" data-submit-options="{submitOptions.length}" class="btn-group btn-group-sm {{{ if !(submitOptions.length || canSchedule) }}}hidden{{{ end }}}">
|
||||
<button type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fa fa-caret-down"></i>
|
||||
<span class="sr-only">[[topic:composer.additional-options]]</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end p-1" role="menu">
|
||||
<li><a class="dropdown-item rounded-1 display-scheduler {{{ if !canSchedule }}}hidden{{{ end }}}" role="menuitem">[[topic:composer.post-later]]</a></li>
|
||||
<li><a class="dropdown-item rounded-1 cancel-scheduling hidden" role="menuitem">[[modules:composer.cancel-scheduling]]</a></li>
|
||||
{{{ each submitOptions }}}
|
||||
<li><a class="dropdown-item rounded-1" href="#" data-action="{./action}" role="menuitem">{./text}</a></li>
|
||||
{{{ end }}}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
15
static/templates/partials/composer-write-preview.tpl
Normal file
15
static/templates/partials/composer-write-preview.tpl
Normal file
|
@ -0,0 +1,15 @@
|
|||
<div class="write-preview-container d-flex gap-2 flex-grow-1 overflow-auto">
|
||||
<div class="write-container d-flex flex-column w-100 position-relative">
|
||||
<div></div>
|
||||
<!--
|
||||
<div component="composer/post-queue/alert" class="m-2 alert alert-info fade pe-none position-absolute top-0 start-0 alert-dismissible">[[modules:composer.post-queue-alert]]<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button></div>
|
||||
<div class="draft-icon position-absolute end-0 top-0 mx-2 my-1 hidden-md hidden-lg"></div>
|
||||
-->
|
||||
<textarea class="write shadow-none rounded-1 w-100 form-control" placeholder="[[modules:composer.textarea.placeholder]]">{body}</textarea>
|
||||
</div>
|
||||
<!-- no need for preview container in quill -->
|
||||
<div class="preview-container d-none d-md-flex w-50" style="display:none!important;">
|
||||
<div class="preview w-100 overflow-auto"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
Loading…
Add table
Add a link
Reference in a new issue