FEATURE: Add ability to claim topics on flagged topics page
This commit is contained in:
parent
aa885dcfac
commit
856c5a5435
|
@ -0,0 +1,12 @@
|
||||||
|
{{#unless canAct}}
|
||||||
|
{{#if flaggedPost.topic.assigned_to_user}}
|
||||||
|
<div class='cant-act-flagged-post'>
|
||||||
|
<div class='cant-act-message'>
|
||||||
|
{{i18n "discourse_assign.cant_act"}}
|
||||||
|
</div>
|
||||||
|
<div class='assigned-to'>
|
||||||
|
{{assigned-to user=flaggedPost.topic.assigned_to_user}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
{{/unless}}
|
|
@ -1,25 +1,50 @@
|
||||||
import { withPluginApi } from 'discourse/lib/plugin-api';
|
import { withPluginApi } from 'discourse/lib/plugin-api';
|
||||||
import { observes } from 'ember-addons/ember-computed-decorators';
|
import { default as computed, observes } from 'ember-addons/ember-computed-decorators';
|
||||||
|
|
||||||
|
|
||||||
// should this be in API ?
|
// should this be in API ?
|
||||||
import Topic from 'discourse/models/topic';
|
|
||||||
import TopicFooterDropdown from 'discourse/components/topic-footer-mobile-dropdown';
|
|
||||||
import showModal from 'discourse/lib/show-modal';
|
import showModal from 'discourse/lib/show-modal';
|
||||||
import { iconNode } from 'discourse-common/lib/icon-library';
|
import { iconNode } from 'discourse-common/lib/icon-library';
|
||||||
import { h } from 'virtual-dom';
|
import { h } from 'virtual-dom';
|
||||||
|
|
||||||
function initialize(api, container) {
|
function initialize(api) {
|
||||||
|
|
||||||
const siteSettings = container.lookup('site-settings:main');
|
// You can't act on flags claimed by another user
|
||||||
const currentUser = container.lookup('current-user:main');
|
api.modifyClass('component:flagged-post', {
|
||||||
|
@computed('flaggedPost.topic.assigned_to_user_id', 'filter')
|
||||||
|
canAct(assignedToUserId, filter) {
|
||||||
|
if (assignedToUserId && this.currentUser.id !== assignedToUserId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._super(filter);
|
||||||
|
},
|
||||||
|
|
||||||
|
didInsertElement() {
|
||||||
|
this._super();
|
||||||
|
this.messageBus.subscribe("/staff/topic-assignment", data => {
|
||||||
|
|
||||||
|
let flaggedPost = this.get('flaggedPost');
|
||||||
|
if (data.topic_id === flaggedPost.get('topic.id')) {
|
||||||
|
flaggedPost.set('topic.assigned_to_user_id',
|
||||||
|
data.type === 'assigned' ? data.assigned_to.id : null
|
||||||
|
);
|
||||||
|
flaggedPost.set('topic.assigned_to_user', data.assigned_to);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
willDestroyElement() {
|
||||||
|
this._super();
|
||||||
|
this.messageBus.unsubscribe("/staff/topic-assignment");
|
||||||
|
}
|
||||||
|
}, { ignoreMissing: true });
|
||||||
|
|
||||||
// doing this mess while we come up with a better API
|
// doing this mess while we come up with a better API
|
||||||
TopicFooterDropdown.reopen({
|
api.modifyClass('component:topic-footer-mobile-dropdown', {
|
||||||
_createContent() {
|
_createContent() {
|
||||||
this._super();
|
this._super();
|
||||||
|
|
||||||
if (!this.get('currentUser.staff') || !siteSettings.assign_enabled) {
|
if (!this.get('currentUser.staff') || !this.siteSettings.assign_enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const content = this.get('content');
|
const content = this.get('content');
|
||||||
|
@ -50,16 +75,20 @@ function initialize(api, container) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Topic.reopen({
|
api.modifyClass('model:topic', {
|
||||||
assignedToUserPath: function(){
|
@computed('assigned_to_user')
|
||||||
return siteSettings.assigns_user_url_path.replace("{username}", this.get("assigned_to_user.username"));
|
assignedToUserPath(assignedToUser) {
|
||||||
}.property('assigned_to_user')
|
return this.siteSettings.assigns_user_url_path.replace(
|
||||||
|
"{username}",
|
||||||
|
Ember.get(assignedToUser, 'username')
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
api.addPostSmallActionIcon('assigned','user-plus');
|
api.addPostSmallActionIcon('assigned','user-plus');
|
||||||
api.addPostSmallActionIcon('unassigned','user-times');
|
api.addPostSmallActionIcon('unassigned','user-times');
|
||||||
|
|
||||||
api.addPostTransformCallback((transformed) => {
|
api.addPostTransformCallback(transformed => {
|
||||||
if (transformed.actionCode === "assigned" || transformed.actionCode === "unassigned") {
|
if (transformed.actionCode === "assigned" || transformed.actionCode === "unassigned") {
|
||||||
transformed.isSmallAction = true;
|
transformed.isSmallAction = true;
|
||||||
transformed.canEdit = false;
|
transformed.canEdit = false;
|
||||||
|
@ -77,14 +106,45 @@ function initialize(api, container) {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (currentUser && currentUser.get("staff") && siteSettings.assign_enabled) {
|
api.addUserMenuGlyph(widget => {
|
||||||
api.addUserMenuGlyph({
|
return undefined;
|
||||||
|
|
||||||
|
if (widget.currentUser &&
|
||||||
|
widget.currentUser.get('staff') &&
|
||||||
|
widget.siteSettings.assign_enabled) {
|
||||||
|
|
||||||
|
return {
|
||||||
label: 'discourse_assign.assigned',
|
label: 'discourse_assign.assigned',
|
||||||
className: 'assigned',
|
className: 'assigned',
|
||||||
icon: 'user-plus',
|
icon: 'user-plus',
|
||||||
href: `${currentUser.get("path")}/activity/assigned`
|
href: `${widget.currentUser.get("path")}/activity/assigned`,
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
api.createWidget('assigned-to', {
|
||||||
|
html(attrs) {
|
||||||
|
let { assignedToUser, href } = attrs;
|
||||||
|
|
||||||
|
return h('p.assigned-to', [
|
||||||
|
iconNode('user-plus'),
|
||||||
|
h('span.assign-text', I18n.t('discourse_assign.assigned_to')),
|
||||||
|
h('a', { attributes: { class: 'assigned-to-username', href } }, assignedToUser.username)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
api.createWidget('assigned-to', {
|
||||||
|
html(attrs) {
|
||||||
|
let { assignedToUser, href } = attrs;
|
||||||
|
|
||||||
|
return h('p.assigned-to', [
|
||||||
|
iconNode('user-plus'),
|
||||||
|
h('span.assign-text', I18n.t('discourse_assign.assigned_to')),
|
||||||
|
h('a', { attributes: { class: 'assigned-to-username', href } }, assignedToUser.username)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
api.createWidget('assigned-to', {
|
api.createWidget('assigned-to', {
|
||||||
html(attrs) {
|
html(attrs) {
|
||||||
|
@ -113,19 +173,12 @@ function initialize(api, container) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
api.replaceIcon('notification.discourse_assign.assign_notification', 'user-plus');
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'extend-for-assign',
|
name: 'extend-for-assign',
|
||||||
initialize(container) {
|
initialize(container) {
|
||||||
withPluginApi('0.8.5', api => {
|
withPluginApi('0.8.11', api => initialize(api, container));
|
||||||
initialize(api, container);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Fix icons in new versions of discourse
|
|
||||||
withPluginApi('0.8.10', api => {
|
|
||||||
api.replaceIcon('notification.discourse_assign.assign_notification', 'user-plus');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
export default Ember.Component.extend({
|
||||||
|
classNames: ['assigned-to-user']
|
||||||
|
});
|
|
@ -22,4 +22,3 @@ export default Ember.Component.extend({
|
||||||
this.messageBus.unsubscribe("/staff/topic-assignment");
|
this.messageBus.unsubscribe("/staff/topic-assignment");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
{{avatar user imageSize="small"}}
|
||||||
|
<span class='assigned-username'>
|
||||||
|
{{user.username}}
|
||||||
|
</span>
|
||||||
|
{{yield}}
|
|
@ -1,16 +1,12 @@
|
||||||
{{#if topic.assigned_to_user}}
|
{{#if topic.assigned_to_user}}
|
||||||
<div class='assigned-to-user'>
|
{{#assigned-to user=topic.assigned_to_user}}
|
||||||
{{avatar topic.assigned_to_user imageSize="small"}}
|
|
||||||
<span class='assigned-username'>
|
|
||||||
{{topic.assigned_to_user.username}}
|
|
||||||
</span>
|
|
||||||
{{d-button
|
{{d-button
|
||||||
icon="times"
|
icon="times"
|
||||||
class="btn-small unassign"
|
class="btn-small unassign"
|
||||||
action=(action "unassign")
|
action=(action "unassign")
|
||||||
disabled=unassigning
|
disabled=unassigning
|
||||||
title="discourse_assign.unassign.help"}}
|
title="discourse_assign.unassign.help"}}
|
||||||
</div>
|
{{/assigned-to}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{d-button class="btn-small assign"
|
{{d-button class="btn-small assign"
|
||||||
icon="user-plus"
|
icon="user-plus"
|
||||||
|
|
|
@ -8,6 +8,16 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cant-act-flagged-post {
|
||||||
|
padding: 0.5em;
|
||||||
|
border: 1px dashed $primary-medium;
|
||||||
|
color: $primary;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
.assigned-to-user {
|
.assigned-to-user {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
@ -4,6 +4,7 @@ en:
|
||||||
assigned: "assigned %{who} %{when}"
|
assigned: "assigned %{who} %{when}"
|
||||||
unassigned: "unassigned %{who} %{when}"
|
unassigned: "unassigned %{who} %{when}"
|
||||||
discourse_assign:
|
discourse_assign:
|
||||||
|
cant_act: "You cannot act on flags that have been assigned to other users"
|
||||||
assigned: "Assigned"
|
assigned: "Assigned"
|
||||||
assigned_to: "Assigned to"
|
assigned_to: "Assigned to"
|
||||||
assign_notification: "<i title='assigned' class='fa fa-user-plus'></i><p><span>{{username}}</span> {{description}}</p>"
|
assign_notification: "<i title='assigned' class='fa fa-user-plus'></i><p><span>{{username}}</span> {{description}}</p>"
|
||||||
|
|
|
@ -13,3 +13,4 @@ en:
|
||||||
assigned_to: "Topic assigned to @%{username}"
|
assigned_to: "Topic assigned to @%{username}"
|
||||||
unassigned: "Topic was unassigned"
|
unassigned: "Topic was unassigned"
|
||||||
already_claimed: "That topic has already been claimed."
|
already_claimed: "That topic has already been claimed."
|
||||||
|
flag_assigned: "Sorry, flag's topic is assigned to another user"
|
||||||
|
|
16
plugin.rb
16
plugin.rb
|
@ -17,6 +17,22 @@ end
|
||||||
after_initialize do
|
after_initialize do
|
||||||
require 'topic_assigner'
|
require 'topic_assigner'
|
||||||
|
|
||||||
|
# Raise an invalid access error if a user tries to act on something
|
||||||
|
# not assigned to them
|
||||||
|
DiscourseEvent.on(:before_staff_flag_action) do |args|
|
||||||
|
if custom_fields = args[:post].topic.custom_fields
|
||||||
|
if assigned_to_id = custom_fields['assigned_to_id']
|
||||||
|
unless assigned_to_id.to_i == args[:user].id
|
||||||
|
raise Discourse::InvalidAccess.new(
|
||||||
|
"That flag has been assigned to another user",
|
||||||
|
nil,
|
||||||
|
custom_message: 'discourse_assign.flag_assigned'
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# We can remove this check once this method is stable
|
# We can remove this check once this method is stable
|
||||||
if respond_to?(:add_preloaded_topic_list_custom_field)
|
if respond_to?(:add_preloaded_topic_list_custom_field)
|
||||||
add_preloaded_topic_list_custom_field('assigned_to_id')
|
add_preloaded_topic_list_custom_field('assigned_to_id')
|
||||||
|
|
Loading…
Reference in New Issue