mirror of
https://github.com/wagtail/wagtail.git
synced 2024-12-01 11:41:20 +01:00
Add commenting controls
This commit is contained in:
parent
779f50aa3c
commit
3174ffee08
84
client/scss/components/_comments-controls.scss
Normal file
84
client/scss/components/_comments-controls.scss
Normal file
@ -0,0 +1,84 @@
|
||||
.comments-controls {
|
||||
padding-right: $mobile-nice-padding;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
padding-right: $desktop-nice-padding;
|
||||
}
|
||||
}
|
||||
|
||||
.comments-toggle {
|
||||
float: right;
|
||||
position: relative;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
cursor: pointer;
|
||||
|
||||
// Wagtail adds some top padding to labels on mobile
|
||||
padding: 0;
|
||||
|
||||
&__icon {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 10px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
color: $color-white;
|
||||
opacity: 0.6;
|
||||
transition: opacity 100ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
&__count {
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
right: 0;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 50%;
|
||||
background-color: #00b0b1;
|
||||
border: 1px solid #007d7e;
|
||||
color: $color-white;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
[type=checkbox] {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
top: -20px;
|
||||
}
|
||||
|
||||
[type=checkbox]:checked + &__icon {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
[type=checkbox]:focus + &__icon {
|
||||
outline: 3px solid $color-focus-outline;
|
||||
}
|
||||
}
|
||||
|
||||
.comment-notifications-toggle {
|
||||
float: right;
|
||||
height: 42px;
|
||||
margin-right: 30px;
|
||||
|
||||
label {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
padding-top: 5px;
|
||||
font-weight: normal;
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
color: $color-white;
|
||||
}
|
||||
|
||||
.switch__toggle {
|
||||
margin-left: 15px;
|
||||
}
|
||||
}
|
@ -81,4 +81,32 @@ $switch-color-middle-grey: #777;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
// Colour changes for when displaying on teal background
|
||||
&--teal-background {
|
||||
$background: #005b5e;
|
||||
|
||||
.switch__toggle {
|
||||
&::before {
|
||||
background-color: $background;
|
||||
border: $switch-border solid $background;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
&::after {
|
||||
background-color: $color-white;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
[type=checkbox]:checked + .switch__toggle::before {
|
||||
// Override the white-background styling
|
||||
background-color: $background;
|
||||
border-color: $background;
|
||||
}
|
||||
|
||||
[type=checkbox]:checked + .switch__toggle::after {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,6 +72,16 @@
|
||||
margin-top: 0;
|
||||
background-color: $color-header-bg;
|
||||
}
|
||||
|
||||
li.right {
|
||||
float: right;
|
||||
margin-right: 0;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
li.wide {
|
||||
width: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
|
@ -134,6 +134,7 @@ These are classes for components.
|
||||
@import 'components/skiplink';
|
||||
@import 'components/workflow-tasks';
|
||||
@import 'components/switch';
|
||||
@import 'components/comments-controls';
|
||||
|
||||
|
||||
/* OVERRIDES
|
||||
|
@ -22,7 +22,8 @@ import {
|
||||
selectCommentFactory,
|
||||
selectEnabled,
|
||||
selectFocused,
|
||||
selectIsDirty
|
||||
selectIsDirty,
|
||||
selectCommentCount
|
||||
} from './selectors';
|
||||
import CommentComponent from './components/Comment';
|
||||
import { CommentFormSetComponent } from './components/Form';
|
||||
@ -144,7 +145,8 @@ export class CommentApp {
|
||||
selectComments,
|
||||
selectEnabled,
|
||||
selectFocused,
|
||||
selectIsDirty
|
||||
selectIsDirty,
|
||||
selectCommentCount
|
||||
}
|
||||
actions = commentActionFunctions;
|
||||
|
||||
@ -209,6 +211,11 @@ export class CommentApp {
|
||||
this.store.dispatch(setFocusedComment(commentId, { updatePinnedComment: true }));
|
||||
return commentId;
|
||||
}
|
||||
setVisible(visible: boolean) {
|
||||
this.store.dispatch(updateGlobalSettings({
|
||||
commentsEnabled: visible,
|
||||
}));
|
||||
}
|
||||
renderApp(
|
||||
element: HTMLElement,
|
||||
outputElement: HTMLElement,
|
||||
|
@ -47,3 +47,9 @@ export const selectIsDirty = createSelector(
|
||||
return Array.from(comment.replies.values()).some(reply => reply.deleted || reply.originalText !== reply.text);
|
||||
});
|
||||
});
|
||||
|
||||
export const selectCommentCount = (state: State) => (
|
||||
[...state.comments.comments.values()].filter(
|
||||
(comment: Comment) => !comment.deleted && !comment.resolved
|
||||
).length
|
||||
);
|
||||
|
@ -377,6 +377,33 @@ $(() => {
|
||||
$icon.addClass('icon-view').removeClass('icon-spinner');
|
||||
});
|
||||
});
|
||||
|
||||
// Comments toggle
|
||||
$('.comments-toggle input[type=checkbox]').change((e) => {
|
||||
// Show/hide comments
|
||||
window.commentApp.setVisible(e.target.checked);
|
||||
|
||||
// Show/hide comment notifications toggle
|
||||
if (e.target.checked) {
|
||||
$('.comment-notifications-toggle').show();
|
||||
} else {
|
||||
$('.comment-notifications-toggle').hide();
|
||||
}
|
||||
});
|
||||
|
||||
// Keep number of comments up to date with comment app
|
||||
const updateCommentCount = () => {
|
||||
const commentCount = window.commentApp.selectors.selectCommentCount(window.commentApp.store.getState());
|
||||
|
||||
if (commentCount > 0) {
|
||||
$('.comments-toggle__count').text(commentCount);
|
||||
} else {
|
||||
// Note: CSS will hide the circle when its content is empty
|
||||
$('.comments-toggle__count').text('');
|
||||
}
|
||||
};
|
||||
window.commentApp.store.subscribe(updateCommentCount);
|
||||
updateCommentCount();
|
||||
});
|
||||
|
||||
let updateFooterTextTimeout = -1;
|
||||
|
@ -365,11 +365,13 @@ class TabbedInterface(BaseFormEditHandler):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.base_form_class = kwargs.pop('base_form_class', None)
|
||||
self.show_comments_toggle = kwargs.pop('show_comments_toggle', False)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def clone_kwargs(self):
|
||||
kwargs = super().clone_kwargs()
|
||||
kwargs['base_form_class'] = self.base_form_class
|
||||
kwargs['show_comments_toggle'] = self.show_comments_toggle
|
||||
return kwargs
|
||||
|
||||
|
||||
@ -921,7 +923,7 @@ def get_edit_handler(cls):
|
||||
heading=gettext_lazy('Settings'),
|
||||
classname='settings'))
|
||||
|
||||
edit_handler = TabbedInterface(tabs, base_form_class=cls.base_form_class)
|
||||
edit_handler = TabbedInterface(tabs, base_form_class=cls.base_form_class, show_comments_toggle=True)
|
||||
|
||||
return edit_handler.bind_to(model=cls)
|
||||
|
||||
|
@ -1,10 +1,30 @@
|
||||
{% load wagtailadmin_tags %}
|
||||
{% load wagtailadmin_tags i18n %}
|
||||
<ul class="tab-nav merged" role="tablist">
|
||||
{% for child in self.children %}
|
||||
<li class="{{ child.classes|join:" " }} {% if forloop.first %}active{% endif %}" role="tab" aria-controls="tab-{{ child.heading|cautious_slugify }}">
|
||||
<a href="#tab-{{ child.heading|cautious_slugify }}" class="{% if forloop.first %}active{% endif %}">{{ child.heading }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
|
||||
{% if self.show_comments_toggle %}
|
||||
<li class="right wide">
|
||||
<div class="comments-controls">
|
||||
<label class="comments-toggle" aria-label="{% trans 'Show comments' %}">
|
||||
<input type="checkbox" checked>
|
||||
{% icon name="comment-dots" class_name="comments-toggle__icon" %}
|
||||
<div class="comments-toggle__count">{# populated in page-editor.js #}</div>
|
||||
</label>
|
||||
|
||||
<div class="comment-notifications-toggle">
|
||||
<label class="switch switch--teal-background">
|
||||
{% trans "Comment notifications" %}
|
||||
<input type="checkbox" checked>
|
||||
<span class="switch__toggle"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
|
@ -0,0 +1,3 @@
|
||||
<symbol id="icon-comment-dots" viewBox="0 0 512 512">
|
||||
<path d="M256 32C114.6 32 0 125.1 0 240c0 49.6 21.4 95 57 130.7C44.5 421.1 2.7 466 2.2 466.5c-2.2 2.3-2.8 5.7-1.5 8.7S4.8 480 8 480c66.3 0 116-31.8 140.6-51.4 32.7 12.3 69 19.4 107.4 19.4 141.4 0 256-93.1 256-208S397.4 32 256 32zM128 272c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32zm128 0c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32zm128 0c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32z"></path>
|
||||
</symbol>
|
@ -183,4 +183,4 @@
|
||||
LockUnlockAction('{{ csrf_token|escapejs }}', '{% url 'wagtailadmin_pages:edit' page.id %}');
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
@ -725,6 +725,7 @@ def register_icons(icons):
|
||||
'cogs.svg',
|
||||
'collapse-down.svg',
|
||||
'collapse-up.svg',
|
||||
'comment-dots.svg',
|
||||
'comment.svg',
|
||||
'cross.svg',
|
||||
'date.svg',
|
||||
|
Loading…
Reference in New Issue
Block a user