client/posts: add expanders to edit sidebar

This commit is contained in:
rr- 2016-08-01 20:07:49 +02:00
parent b9f2db1c63
commit 51ea06d837
5 changed files with 185 additions and 76 deletions

View file

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

View file

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

View file

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

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

View file

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