client/posts: add expanders to edit sidebar
This commit is contained in:
parent
b9f2db1c63
commit
51ea06d837
5 changed files with 185 additions and 76 deletions
|
@ -222,3 +222,23 @@ a .access-key
|
|||
[data-pseudo-content]:before {
|
||||
content: attr(data-pseudo-content)
|
||||
}
|
||||
|
||||
.expander
|
||||
&.collapsed
|
||||
margin-bottom: 1em
|
||||
&>*
|
||||
display: none
|
||||
&>header
|
||||
display: block
|
||||
header
|
||||
background: $active-tab-background-color
|
||||
line-height: 2em
|
||||
a
|
||||
padding: 0 0.5em
|
||||
display: block
|
||||
color: $inactive-link-color
|
||||
i
|
||||
float: right
|
||||
line-height: 2em
|
||||
.expander-content
|
||||
padding: 1em 0.5em
|
||||
|
|
|
@ -303,8 +303,9 @@ $safety-unsafe = #F3985F
|
|||
margin-bottom: 0.5em
|
||||
|
||||
.post-view .edit-sidebar
|
||||
section
|
||||
margin-bottom: 1em
|
||||
.expander-content
|
||||
section:not(:last-child)
|
||||
margin-bottom: 1em
|
||||
|
||||
.safety
|
||||
display: flex
|
||||
|
|
|
@ -1,86 +1,77 @@
|
|||
<div class='edit-sidebar'>
|
||||
<form autocomplete='off'>
|
||||
<div class='input'>
|
||||
<% if (ctx.canEditPostSafety) { %>
|
||||
<section class='safety'>
|
||||
<label>Safety</label>
|
||||
<%= ctx.makeRadio({
|
||||
name: 'safety',
|
||||
class: 'safety-safe',
|
||||
value: 'safe',
|
||||
selectedValue: ctx.post.safety,
|
||||
text: 'Safe'}) %>
|
||||
<%= ctx.makeRadio({
|
||||
name: 'safety',
|
||||
class: 'safety-sketchy',
|
||||
value: 'sketchy',
|
||||
selectedValue: ctx.post.safety,
|
||||
text: 'Sketchy'}) %>
|
||||
<%= ctx.makeRadio({
|
||||
name: 'safety',
|
||||
value: 'unsafe',
|
||||
selectedValue: ctx.post.safety,
|
||||
class: 'safety-unsafe',
|
||||
text: 'Unsafe'}) %>
|
||||
</section>
|
||||
<% } %>
|
||||
<% if (ctx.canEditPostSafety) { %>
|
||||
<section class='safety'>
|
||||
<label>Safety</label>
|
||||
<%= ctx.makeRadio({
|
||||
name: 'safety',
|
||||
class: 'safety-safe',
|
||||
value: 'safe',
|
||||
selectedValue: ctx.post.safety,
|
||||
text: 'Safe'}) %>
|
||||
<%= ctx.makeRadio({
|
||||
name: 'safety',
|
||||
class: 'safety-sketchy',
|
||||
value: 'sketchy',
|
||||
selectedValue: ctx.post.safety,
|
||||
text: 'Sketchy'}) %>
|
||||
<%= ctx.makeRadio({
|
||||
name: 'safety',
|
||||
value: 'unsafe',
|
||||
selectedValue: ctx.post.safety,
|
||||
class: 'safety-unsafe',
|
||||
text: 'Unsafe'}) %>
|
||||
</section>
|
||||
<% } %>
|
||||
|
||||
<% if (ctx.canEditPostRelations) { %>
|
||||
<section class='relations'>
|
||||
<%= ctx.makeTextInput({
|
||||
text: 'Relations',
|
||||
name: 'relations',
|
||||
placeholder: 'space-separated post IDs',
|
||||
pattern: '^[0-9 ]*$',
|
||||
value: ctx.post.relations.map(rel => rel.id).join(' '),
|
||||
}) %>
|
||||
</section>
|
||||
<% } %>
|
||||
<% if (ctx.canEditPostRelations) { %>
|
||||
<section class='relations'>
|
||||
<%= ctx.makeTextInput({
|
||||
text: 'Relations',
|
||||
name: 'relations',
|
||||
placeholder: 'space-separated post IDs',
|
||||
pattern: '^[0-9 ]*$',
|
||||
value: ctx.post.relations.map(rel => rel.id).join(' '),
|
||||
}) %>
|
||||
</section>
|
||||
<% } %>
|
||||
|
||||
<% if (ctx.canEditPostTags) { %>
|
||||
<section class='tags'>
|
||||
<%= ctx.makeTextInput({
|
||||
text: 'Tags',
|
||||
value: ctx.post.tags.join(' '),
|
||||
}) %>
|
||||
</section>
|
||||
<% } %>
|
||||
<% if (ctx.canEditPostFlags && ctx.post.type === 'video') { %>
|
||||
<section class='flags'>
|
||||
<label>Miscellaneous</label>
|
||||
<%= ctx.makeCheckbox({
|
||||
text: 'Loop video',
|
||||
name: 'loop',
|
||||
checked: ctx.post.flags.includes('loop'),
|
||||
}) %>
|
||||
</section>
|
||||
<% } %>
|
||||
|
||||
<% if (ctx.canEditPostFlags && ctx.post.type === 'video') { %>
|
||||
<section class='flags'>
|
||||
<label>Miscellaneous</label>
|
||||
<% if (ctx.canEditPostTags) { %>
|
||||
<section class='tags'>
|
||||
<%= ctx.makeTextInput({
|
||||
value: ctx.post.tags.join(' '),
|
||||
}) %>
|
||||
</section>
|
||||
<% } %>
|
||||
|
||||
<%= ctx.makeCheckbox({
|
||||
text: 'Loop video',
|
||||
name: 'loop',
|
||||
checked: ctx.post.flags.includes('loop'),
|
||||
}) %>
|
||||
</section>
|
||||
<% } %>
|
||||
<% if (ctx.canEditPostContent) { %>
|
||||
<section class='post-content'>
|
||||
<label>Content</label>
|
||||
<div class='dropper-container'></div>
|
||||
</section>
|
||||
<% } %>
|
||||
|
||||
<% if (ctx.canEditPostContent) { %>
|
||||
<section class='post-content'>
|
||||
<label>Content</label>
|
||||
|
||||
<div class='dropper-container'></div>
|
||||
</section>
|
||||
<% } %>
|
||||
|
||||
<% if (ctx.canEditPostThumbnail) { %>
|
||||
<section class='post-thumbnail'>
|
||||
<label>Thumbnail</label>
|
||||
|
||||
<div class='dropper-container'></div>
|
||||
|
||||
<a>Discard custom thumbnail</a>
|
||||
</section>
|
||||
<% } %>
|
||||
</div>
|
||||
<% if (ctx.canEditPostThumbnail) { %>
|
||||
<section class='post-thumbnail'>
|
||||
<label>Thumbnail</label>
|
||||
<div class='dropper-container'></div>
|
||||
<a>Discard custom thumbnail</a>
|
||||
</section>
|
||||
<% } %>
|
||||
|
||||
<div class='messages'></div>
|
||||
|
||||
<div class='buttons'>
|
||||
<input class='encourage' type='submit' value='Submit' class='submit'/>
|
||||
</div>
|
||||
<input type='submit' value='Submit' class='submit'/>
|
||||
</form>
|
||||
</div>
|
||||
|
|
86
client/js/controls/expander_control.js
Normal file
86
client/js/controls/expander_control.js
Normal file
|
@ -0,0 +1,86 @@
|
|||
'use strict';
|
||||
|
||||
const ICON_CLASS_OPENED = 'fa-chevron-down';
|
||||
const ICON_CLASS_CLOSED = 'fa-chevron-up';
|
||||
|
||||
class ExpanderControl {
|
||||
constructor(title, nodes) {
|
||||
this._title = title;
|
||||
|
||||
nodes = Array.from(nodes).filter(n => n);
|
||||
if (!nodes.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const expanderNode = document.createElement('section');
|
||||
expanderNode.classList.add('expander');
|
||||
|
||||
const toggleLinkNode = document.createElement('a');
|
||||
const toggleIconNode = document.createElement('i');
|
||||
toggleIconNode.classList.add('fa');
|
||||
toggleLinkNode.textContent = title;
|
||||
toggleLinkNode.appendChild(toggleIconNode);
|
||||
toggleLinkNode.addEventListener('click', e => this._evtToggleClick(e));
|
||||
|
||||
const headerNode = document.createElement('header');
|
||||
headerNode.appendChild(toggleLinkNode);
|
||||
expanderNode.appendChild(headerNode);
|
||||
|
||||
const expanderContentNode = document.createElement('div');
|
||||
expanderContentNode.classList.add('expander-content');
|
||||
expanderNode.appendChild(expanderContentNode);
|
||||
|
||||
nodes[0].parentNode.insertBefore(expanderNode, nodes[0]);
|
||||
|
||||
for (let node of nodes) {
|
||||
expanderContentNode.appendChild(node);
|
||||
}
|
||||
|
||||
this._expanderNode = expanderNode;
|
||||
this._toggleIconNode = toggleIconNode;
|
||||
|
||||
expanderNode.classList.toggle(
|
||||
'collapsed',
|
||||
this._allStates[this._title] === undefined ?
|
||||
false :
|
||||
!this._allStates[this._title]);
|
||||
this._syncIcon();
|
||||
}
|
||||
|
||||
get _isOpened() {
|
||||
return !this._expanderNode.classList.contains('collapsed');
|
||||
}
|
||||
|
||||
get _allStates() {
|
||||
try {
|
||||
return JSON.parse(localStorage.getItem('expander')) || {};
|
||||
} catch (e) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
_save() {
|
||||
const newStates = Object.assign({}, this._allStates);
|
||||
newStates[this._title] = this._isOpened;
|
||||
localStorage.setItem('expander', JSON.stringify(newStates));
|
||||
}
|
||||
|
||||
_evtToggleClick(e) {
|
||||
e.preventDefault();
|
||||
this._expanderNode.classList.toggle('collapsed');
|
||||
this._save();
|
||||
this._syncIcon();
|
||||
}
|
||||
|
||||
_syncIcon() {
|
||||
if (this._isOpened) {
|
||||
this._toggleIconNode.classList.add(ICON_CLASS_OPENED);
|
||||
this._toggleIconNode.classList.remove(ICON_CLASS_CLOSED);
|
||||
} else {
|
||||
this._toggleIconNode.classList.add(ICON_CLASS_CLOSED);
|
||||
this._toggleIconNode.classList.remove(ICON_CLASS_OPENED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ExpanderControl;
|
|
@ -5,6 +5,7 @@ const events = require('../events.js');
|
|||
const misc = require('../util/misc.js');
|
||||
const views = require('../util/views.js');
|
||||
const TagInputControl = require('./tag_input_control.js');
|
||||
const ExpanderControl = require('../controls/expander_control.js');
|
||||
const FileDropperControl = require('../controls/file_dropper_control.js');
|
||||
|
||||
const template = views.getTemplate('post-edit-sidebar');
|
||||
|
@ -32,6 +33,16 @@ class PostEditSidebarControl extends events.EventTarget {
|
|||
canFeaturePosts: api.hasPrivilege('posts:feature'),
|
||||
}));
|
||||
|
||||
new ExpanderControl(
|
||||
'Basic info',
|
||||
this._hostNode.querySelectorAll('.safety, .relations, .flags'));
|
||||
new ExpanderControl(
|
||||
'Tags',
|
||||
this._hostNode.querySelectorAll('.tags'));
|
||||
new ExpanderControl(
|
||||
'Content',
|
||||
this._hostNode.querySelectorAll('.post-content, .post-thumbnail'));
|
||||
|
||||
if (this._formNode) {
|
||||
this._formNode.addEventListener('submit', e => this._evtSubmit(e));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue