mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-23 23:58:31 -05:00
FEATURE: Move topic admin button into timeline
Also includes converting the topic admin menu to the widget framework.
This commit is contained in:
parent
c0e4d0f6f2
commit
1643ff0f3c
11 changed files with 221 additions and 128 deletions
|
@ -21,6 +21,8 @@ export default Ember.Component.extend({
|
|||
this._super();
|
||||
const name = this.get('widget');
|
||||
|
||||
(this.get('delegated') || []).forEach(m => this.set(m, m));
|
||||
|
||||
this._widgetClass = queryRegistry(name) || this.container.lookupFactory(`widget:${name}`);
|
||||
|
||||
if (!this._widgetClass) {
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
import DButton from 'discourse/components/d-button';
|
||||
|
||||
export default DButton.extend({
|
||||
click() {
|
||||
const $target = this.$(),
|
||||
position = $target.position(),
|
||||
width = $target.innerWidth(),
|
||||
loc = {
|
||||
position: this.get('position') || "fixed",
|
||||
left: position.left + width,
|
||||
top: position.top
|
||||
};
|
||||
|
||||
this.appEvents.trigger("popup-menu:open", loc);
|
||||
this.sendAction("action");
|
||||
}
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
import MountWidget from 'discourse/components/mount-widget';
|
||||
|
||||
export default MountWidget.extend({
|
||||
tagName: 'span',
|
||||
widget: "topic-admin-menu-button",
|
||||
|
||||
buildArgs() {
|
||||
return this.getProperties('topic', 'fixed');
|
||||
}
|
||||
});
|
|
@ -1,16 +1,15 @@
|
|||
import ContainerView from 'discourse/views/container';
|
||||
import { on } from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
export default ContainerView.extend({
|
||||
elementId: 'topic-footer-buttons',
|
||||
|
||||
@on('init')
|
||||
createButtons() {
|
||||
const topic = this.get('topic');
|
||||
const currentUser = this.get('controller.currentUser');
|
||||
init() {
|
||||
this._super();
|
||||
|
||||
if (this.currentUser) {
|
||||
const viewArgs = this.getProperties('topic', 'topicDelegated');
|
||||
viewArgs.currentUser = this.currentUser;
|
||||
|
||||
if (currentUser) {
|
||||
const viewArgs = { topic, currentUser };
|
||||
this.attachViewWithArgs(viewArgs, 'topic-footer-main-buttons');
|
||||
this.attachViewWithArgs(viewArgs, 'pinned-button');
|
||||
this.attachViewWithArgs(viewArgs, 'topic-notifications-button');
|
||||
|
|
|
@ -17,13 +17,28 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
|||
selectedPosts: null,
|
||||
selectedReplies: null,
|
||||
queryParams: ['filter', 'username_filters', 'show_deleted'],
|
||||
loadedAllPosts: Em.computed.or('model.postStream.loadedAllPosts', 'model.postStream.loadingLastPost'),
|
||||
loadedAllPosts: Ember.computed.or('model.postStream.loadedAllPosts', 'model.postStream.loadingLastPost'),
|
||||
enteredAt: null,
|
||||
retrying: false,
|
||||
adminMenuVisible: false,
|
||||
|
||||
showRecover: Em.computed.and('model.deleted', 'model.details.can_recover'),
|
||||
isFeatured: Em.computed.or("model.pinned_at", "model.isBanner"),
|
||||
topicDelegated: [
|
||||
'toggleMultiSelect',
|
||||
'deleteTopic',
|
||||
'recoverTopic',
|
||||
'toggleClosed',
|
||||
'showAutoClose',
|
||||
'showFeatureTopic',
|
||||
'showChangeTimestamp',
|
||||
'toggleArchived',
|
||||
'toggleVisibility',
|
||||
'convertToPublicTopic',
|
||||
'convertToPrivateMessage',
|
||||
'jumpTop',
|
||||
'jumpToPost',
|
||||
'jumpToIndex',
|
||||
'jumpBottom',
|
||||
'replyToPost'
|
||||
],
|
||||
|
||||
@computed
|
||||
showTimeline() {
|
||||
|
@ -237,14 +252,6 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
|||
return this.get('model.details').removeAllowedUser(user);
|
||||
},
|
||||
|
||||
showTopicAdminMenu() {
|
||||
this.set('adminMenuVisible', true);
|
||||
},
|
||||
|
||||
hideTopicAdminMenu() {
|
||||
this.set('adminMenuVisible', false);
|
||||
},
|
||||
|
||||
deleteTopic() {
|
||||
this.deleteTopic();
|
||||
},
|
||||
|
|
|
@ -72,19 +72,10 @@
|
|||
<div class="posts-wrapper">
|
||||
|
||||
{{#if showTimeline}}
|
||||
{{topic-timeline topic=model
|
||||
loading=model.postStream.loading
|
||||
jumpTop="jumpTop"
|
||||
jumpToPost="jumpToPost"
|
||||
jumpToIndex="jumpToIndex"
|
||||
jumpBottom="jumpBottom"
|
||||
replyToPost="replyToPost"}}
|
||||
{{topic-timeline topic=model loading=model.postStream.loading delegated=topicDelegated}}
|
||||
{{else}}
|
||||
{{topic-progress topic=model
|
||||
jumpTop="jumpTop"
|
||||
jumpToPost="jumpToPost"
|
||||
jumpToIndex="jumpToIndex"
|
||||
jumpBottom="jumpBottom"}}
|
||||
{{topic-progress topic=model delegated=topicDelegated}}
|
||||
{{topic-admin-menu-button topic=model fixed="true" delegated=topicDelegated}}
|
||||
{{/if}}
|
||||
{{conditional-loading-spinner condition=model.postStream.loadingAbove}}
|
||||
|
||||
|
@ -136,7 +127,7 @@
|
|||
{{! replace "Log In to Reply" with the infobox }}
|
||||
{{signup-cta}}
|
||||
{{else}}
|
||||
{{topic-footer-buttons topic=model}}
|
||||
{{topic-footer-buttons topic=model topicDelegated=topicDelegated}}
|
||||
{{/if}}
|
||||
|
||||
{{#if model.pending_posts_count}}
|
||||
|
@ -212,78 +203,3 @@
|
|||
{{render "quote-button"}}
|
||||
{{/if}}
|
||||
|
||||
{{#if currentUser.canManageTopic}}
|
||||
{{show-popup-button action="showTopicAdminMenu" class="show-topic-admin" title="topic_admin_menu" icon="wrench"}}
|
||||
{{#popup-menu visible=adminMenuVisible hide="hideTopicAdminMenu" title="admin_title" extraClasses="topic-admin-popup-menu"}}
|
||||
<li class="topic-admin-multi-select">
|
||||
{{d-button action="toggleMultiSelect" icon="tasks" label="topic.actions.multi_select"}}
|
||||
</li>
|
||||
|
||||
{{#if model.details.can_delete}}
|
||||
<li class="topic-admin-delete">
|
||||
{{d-button action="deleteTopic" icon="trash-o" label="topic.actions.delete" class="btn-danger"}}
|
||||
</li>
|
||||
{{/if}}
|
||||
|
||||
{{#if showRecover}}
|
||||
<li class="topic-admin-recover">
|
||||
{{d-button action="recoverTopic" icon="undo" label="topic.actions.recover"}}
|
||||
</li>
|
||||
{{/if}}
|
||||
|
||||
<li class="topic-admin-autoclose">
|
||||
{{#if model.closed}}
|
||||
{{d-button action="toggleClosed" icon="unlock" label="topic.actions.open"}}
|
||||
{{else}}
|
||||
{{d-button action="toggleClosed" icon="lock" label="topic.actions.close"}}
|
||||
{{d-button action="showAutoClose" icon="clock-o" label="topic.actions.auto_close"}}
|
||||
{{/if}}
|
||||
</li>
|
||||
|
||||
{{#unless model.isPrivateMessage}}
|
||||
{{#if model.visible}}
|
||||
<li class="topic-admin-pin">
|
||||
{{#if isFeatured}}
|
||||
{{d-button action="showFeatureTopic" icon="thumb-tack" label="topic.actions.unpin"}}
|
||||
{{else}}
|
||||
{{d-button action="showFeatureTopic" icon="thumb-tack" label="topic.actions.pin"}}
|
||||
{{/if}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
|
||||
<li class="topic-admin-change-timestamp">
|
||||
{{d-button action="showChangeTimestamp" icon="calendar" label="topic.change_timestamp.title"}}
|
||||
</li>
|
||||
|
||||
<li class="topic-admin-archive">
|
||||
{{#if model.archived}}
|
||||
{{d-button action="toggleArchived" icon="folder" label="topic.actions.unarchive"}}
|
||||
{{else}}
|
||||
{{#unless model.isPrivateMessage}}
|
||||
{{d-button action="toggleArchived" icon="folder" label="topic.actions.archive"}}
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
</li>
|
||||
|
||||
<li class="topic-admin-visible">
|
||||
{{#if model.visible}}
|
||||
{{d-button action="toggleVisibility" icon="eye-slash" label="topic.actions.invisible"}}
|
||||
{{else}}
|
||||
{{d-button action="toggleVisibility" icon="eye" label="topic.actions.visible"}}
|
||||
{{/if}}
|
||||
</li>
|
||||
|
||||
{{#if currentUser.staff}}
|
||||
<li class="topic-admin-convert">
|
||||
{{#if model.isPrivateMessage}}
|
||||
{{d-button action="convertToPublicTopic" icon="comment" label="topic.actions.make_public"}}
|
||||
{{else}}
|
||||
{{d-button action="convertToPrivateMessage" icon="envelope" label="topic.actions.make_private"}}
|
||||
{{/if}}
|
||||
</li>
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet "topic-admin-menu-buttons"}}
|
||||
{{/popup-menu}}
|
||||
{{/if}}
|
||||
|
|
|
@ -8,12 +8,13 @@ export default ContainerView.extend({
|
|||
createButtons() {
|
||||
const mobileView = this.site.mobileView;
|
||||
|
||||
const topic = this.get('topic');
|
||||
|
||||
if (!mobileView && this.currentUser.get('staff')) {
|
||||
const viewArgs = {action: 'showTopicAdminMenu', title: 'topic_admin_menu', icon: 'wrench', position: 'absolute'};
|
||||
this.attachViewWithArgs(viewArgs, 'show-popup-button');
|
||||
const viewArgs = { topic, delegated: this.get('topicDelegated') };
|
||||
this.attachViewWithArgs(viewArgs, 'topic-admin-menu-button');
|
||||
}
|
||||
|
||||
const topic = this.get('topic');
|
||||
if (!topic.get('isPrivateMessage')) {
|
||||
if (mobileView) {
|
||||
this.attachViewWithArgs({ topic }, 'topic-footer-mobile-dropdown');
|
||||
|
|
|
@ -40,11 +40,18 @@ export default createWidget('button', {
|
|||
return contents;
|
||||
},
|
||||
|
||||
click() {
|
||||
click(e) {
|
||||
const attrs = this.attrs;
|
||||
if (attrs.disabled) { return; }
|
||||
|
||||
$(`button.widget-button`).removeClass('d-hover').blur();
|
||||
if (attrs.secondaryAction) {
|
||||
this.sendWidgetAction(attrs.secondaryAction);
|
||||
}
|
||||
|
||||
if (attrs.sendActionEvent) {
|
||||
return this.sendWidgetAction(attrs.action, e);
|
||||
}
|
||||
return this.sendWidgetAction(attrs.action);
|
||||
}
|
||||
});
|
||||
|
|
160
app/assets/javascripts/discourse/widgets/topic-admin-menu.js.es6
Normal file
160
app/assets/javascripts/discourse/widgets/topic-admin-menu.js.es6
Normal file
|
@ -0,0 +1,160 @@
|
|||
import { createWidget, applyDecorators } from 'discourse/widgets/widget';
|
||||
import { h } from 'virtual-dom';
|
||||
|
||||
createWidget('admin-menu-button', {
|
||||
html(attrs) {
|
||||
let className = 'btn';
|
||||
if (attrs.buttonClass) { className += ' ' + attrs.buttonClass; }
|
||||
|
||||
return h('li', { className: attrs.className }, this.attach('button', {
|
||||
className,
|
||||
action: attrs.action,
|
||||
icon: attrs.icon,
|
||||
label: `topic.${attrs.label}`,
|
||||
secondaryAction: 'hideAdminMenu'
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
createWidget('topic-admin-menu-button', {
|
||||
tagName: 'span',
|
||||
buildKey: () => `topic-admin-menu-button`,
|
||||
|
||||
defaultState() {
|
||||
return { expanded: false, position: null };
|
||||
},
|
||||
|
||||
html(attrs, state) {
|
||||
if (!this.currentUser || !this.currentUser.get('canManageTopic')) { return; }
|
||||
|
||||
const result = [];
|
||||
result.push(this.attach('button', {
|
||||
className: 'btn no-text' + (attrs.fixed ? " show-topic-admin" : ""),
|
||||
title: 'topic_admin_menu',
|
||||
icon: 'wrench',
|
||||
action: 'showAdminMenu',
|
||||
sendActionEvent: true
|
||||
}));
|
||||
|
||||
if (state.expanded) {
|
||||
result.push(this.attach('topic-admin-menu', { position: state.position,
|
||||
fixed: attrs.fixed,
|
||||
topic: attrs.topic }));
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
hideAdminMenu() {
|
||||
this.state.expanded = false;
|
||||
this.state.position = null;
|
||||
},
|
||||
|
||||
showAdminMenu(e) {
|
||||
this.state.expanded = true;
|
||||
|
||||
const $button = $(e.target).closest('button');
|
||||
const position = $button.position();
|
||||
position.left = position.left;
|
||||
|
||||
if (this.attrs.fixed) {
|
||||
position.left += $button.width() - 203;
|
||||
}
|
||||
this.state.position = position;
|
||||
}
|
||||
});
|
||||
|
||||
export default createWidget('topic-admin-menu', {
|
||||
tagName: 'div.popup-menu.topic-admin-popup-menu',
|
||||
|
||||
buildAttributes(attrs) {
|
||||
const { top, left } = attrs.position;
|
||||
const position = attrs.fixed ? 'fixed' : 'absolute';
|
||||
|
||||
return { style: `position: ${position}; top: ${top}px; left: ${left}px;` };
|
||||
},
|
||||
|
||||
html(attrs) {
|
||||
const buttons = [];
|
||||
buttons.push({ className: 'topic-admin-multi-select',
|
||||
action: 'toggleMultiSelect',
|
||||
icon: 'tasks',
|
||||
label: 'actions.multi_select' });
|
||||
|
||||
const topic = attrs.topic;
|
||||
const details = topic.get('details');
|
||||
if (details.get('can_delete')) {
|
||||
buttons.push({ className: 'topic-admin-delete',
|
||||
buttonClass: 'btn-danger',
|
||||
action: 'deleteTopic',
|
||||
icon: 'trash-o',
|
||||
label: 'actions.delete' });
|
||||
}
|
||||
|
||||
if (topic.get('deleted') && details.get('can_recover')) {
|
||||
buttons.push({ className: 'topic-admin-recover',
|
||||
action: 'recoverTopic',
|
||||
icon: 'undo',
|
||||
label: 'actions.recover' });
|
||||
}
|
||||
|
||||
if (topic.get('closed')) {
|
||||
buttons.push({ className: 'topic-admin-open',
|
||||
action: 'toggleClosed',
|
||||
icon: 'unlock',
|
||||
label: 'actions.open' });
|
||||
} else {
|
||||
buttons.push({ className: 'topic-admin-close',
|
||||
action: 'toggleClosed',
|
||||
icon: 'lock',
|
||||
label: 'actions.close' });
|
||||
buttons.push({ className: 'topic-admin-autoclose',
|
||||
action: 'showAutoClose',
|
||||
icon: 'clock-o',
|
||||
label: 'actions.auto_close' });
|
||||
}
|
||||
|
||||
const isPrivateMessage = topic.get('isPrivateMessage');
|
||||
|
||||
if (!isPrivateMessage && topic.get('visible')) {
|
||||
const featured = topic.get('pinned_at') || topic.get('isBanner');
|
||||
buttons.push({ className: 'topic-admin-pin',
|
||||
action: 'showFeatureTopic',
|
||||
icon: 'thumb-tack',
|
||||
label: featured ? 'actions.unpin' : 'actions.pin' });
|
||||
}
|
||||
buttons.push({ className: 'topic-admin-change-timestamp',
|
||||
action: 'showChangeTimestamp',
|
||||
icon: 'calendar',
|
||||
label: 'change_timestamp.title' });
|
||||
|
||||
if (!isPrivateMessage) {
|
||||
buttons.push({ className: 'topic-admin-archive',
|
||||
action: 'toggleArchived',
|
||||
icon: 'folder',
|
||||
label: topic.get('archived') ? 'actions.unarchive' : 'actions.archive' });
|
||||
}
|
||||
|
||||
const visible = topic.get('visible');
|
||||
buttons.push({ className: 'topic-admin-visible',
|
||||
action: 'toggleVisibility',
|
||||
icon: visible ? 'eye' : 'eye-slash',
|
||||
label: visible ? 'actions.invisible' : 'actions.visible' });
|
||||
|
||||
if (this.currentUser.get('staff')) {
|
||||
buttons.push({ className: 'topic-admin-convert',
|
||||
action: isPrivateMessage ? 'convertToPublicTopic' : 'convertToPrivateMessage',
|
||||
icon: isPrivateMessage ? 'comment' : 'envelope',
|
||||
label: isPrivateMessage ? 'actions.make_public' : 'actions.make_private' });
|
||||
}
|
||||
|
||||
const extraButtons = applyDecorators(this, 'adminMenuButtons', this.attrs, this.state);
|
||||
|
||||
return [ h('h3', I18n.t('admin_title')),
|
||||
h('ul', buttons.concat(extraButtons).map(b => this.attach('admin-menu-button', b))) ];
|
||||
},
|
||||
|
||||
clickOutside() {
|
||||
this.sendWidgetAction('hideAdminMenu');
|
||||
}
|
||||
});
|
|
@ -210,6 +210,10 @@ export default createWidget('topic-timeline', {
|
|||
}));
|
||||
}
|
||||
|
||||
if (this.currentUser.get('canManageTopic')) {
|
||||
controls.push(this.attach('topic-admin-menu-button', { topic }));
|
||||
}
|
||||
|
||||
const result = [ h('div.timeline-controls', controls) ];
|
||||
const stream = attrs.topic.get('postStream.stream');
|
||||
if (stream.length > 2) {
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
|
||||
.timeline-controls {
|
||||
margin-bottom: 2em;
|
||||
|
||||
button {
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.start-date {
|
||||
|
|
Loading…
Reference in a new issue