UX: On mobile use a dropdown for topic controls instead of many buttons
This commit is contained in:
parent
4a21c29961
commit
b2c73e7045
|
@ -76,13 +76,12 @@ export default Ember.Component.extend({
|
|||
$elem.select2({formatResult: this.comboTemplate, minimumResultsForSearch, width: 'resolve'});
|
||||
|
||||
const castInteger = this.get('castInteger');
|
||||
const self = this;
|
||||
$elem.on("change", function (e) {
|
||||
$elem.on("change", e => {
|
||||
let val = $(e.target).val();
|
||||
if (val && val.length && castInteger) {
|
||||
val = parseInt(val, 10);
|
||||
}
|
||||
self.set('value', val);
|
||||
this.set('value', val);
|
||||
});
|
||||
$elem.trigger('change');
|
||||
}.on('didInsertElement'),
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
import Combobox from 'discourse/components/combo-box';
|
||||
import { on, observes } from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
export default Combobox.extend({
|
||||
none: "topic.controls",
|
||||
|
||||
@on('init')
|
||||
_createContent() {
|
||||
const content = [];
|
||||
const topic = this.get('topic');
|
||||
const details = topic.get('details');
|
||||
|
||||
if (details.get('can_invite_to')) {
|
||||
content.push({ id: 'invite', name: I18n.t('topic.invite_reply.title') });
|
||||
}
|
||||
|
||||
if (topic.get('bookmarked')) {
|
||||
content.push({ id: 'bookmark', name: I18n.t('bookmarked.clear_bookmarks') });
|
||||
} else {
|
||||
content.push({ id: 'bookmark', name: I18n.t('bookmarked.title') });
|
||||
}
|
||||
content.push({ id: 'share', name: I18n.t('topic.share.title') });
|
||||
|
||||
if (details.get('can_flag_topic')) {
|
||||
content.push({ id: 'flag', name: I18n.t('topic.flag_topic.title') });
|
||||
}
|
||||
|
||||
this.set('content', content);
|
||||
},
|
||||
|
||||
@observes('value')
|
||||
_valueChanged() {
|
||||
const value = this.get('value');
|
||||
const controller = this.get('parentView.controller');
|
||||
const topic = this.get('topic');
|
||||
|
||||
const refresh = () => {
|
||||
this._createContent();
|
||||
this.set('value', null);
|
||||
};
|
||||
|
||||
switch(value) {
|
||||
case 'invite':
|
||||
controller.send('showInvite');
|
||||
refresh();
|
||||
break;
|
||||
case 'bookmark':
|
||||
topic.toggleBookmark().then(() => refresh());
|
||||
break;
|
||||
case 'share':
|
||||
this.appEvents.trigger('share:url', topic.get('shareUrl'), $('#topic-footer-buttons'));
|
||||
refresh();
|
||||
break;
|
||||
case 'flag':
|
||||
controller.send('showFlagTopic', topic);
|
||||
refresh();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
|
@ -1,9 +1,4 @@
|
|||
/**
|
||||
An object that is responsible for logic related to mobile devices.
|
||||
|
||||
@namespace Discourse
|
||||
@module Mobile
|
||||
**/
|
||||
// An object that is responsible for logic related to mobile devices.
|
||||
Discourse.Mobile = {
|
||||
isMobileDevice: false,
|
||||
mobileView: false,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import ButtonView from 'discourse/views/button';
|
||||
import { iconHTML } from 'discourse/helpers/fa-icon';
|
||||
|
||||
export default ButtonView.extend({
|
||||
classNames: ['bookmark'],
|
||||
|
@ -16,12 +17,12 @@ export default ButtonView.extend({
|
|||
return this.get("bookmarked") ? "bookmarked.help.unbookmark" : "bookmarked.help.bookmark";
|
||||
}.property("bookmarked"),
|
||||
|
||||
click: function() {
|
||||
click() {
|
||||
this.get('controller').send('toggleBookmark');
|
||||
},
|
||||
|
||||
renderIcon: function(buffer) {
|
||||
var className = this.get("bookmarked") ? "bookmarked" : "";
|
||||
buffer.push("<i class='fa fa-bookmark " + className + "'></i>");
|
||||
renderIcon(buffer) {
|
||||
const className = this.get("bookmarked") ? "bookmarked" : "";
|
||||
buffer.push(iconHTML('bookmark', { class: className }));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
import ButtonView from 'discourse/views/button';
|
||||
import { iconHTML } from 'discourse/helpers/fa-icon';
|
||||
|
||||
export default ButtonView.extend({
|
||||
classNames: ['flag-topic'],
|
||||
textKey: 'topic.flag_topic.title',
|
||||
helpKey: 'topic.flag_topic.help',
|
||||
|
||||
click: function() {
|
||||
click() {
|
||||
this.get('controller').send('showFlagTopic', this.get('controller.content'));
|
||||
},
|
||||
|
||||
renderIcon: function(buffer) {
|
||||
buffer.push("<i class='fa fa-flag'></i>");
|
||||
renderIcon(buffer) {
|
||||
buffer.push(iconHTML('flag'));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import ButtonView from 'discourse/views/button';
|
||||
import { iconHTML } from 'discourse/helpers/fa-icon';
|
||||
|
||||
export default ButtonView.extend({
|
||||
textKey: 'topic.invite_reply.title',
|
||||
|
@ -7,7 +8,7 @@ export default ButtonView.extend({
|
|||
disabled: Em.computed.or('controller.model.archived', 'controller.model.closed', 'controller.model.deleted'),
|
||||
|
||||
renderIcon(buffer) {
|
||||
buffer.push("<i class='fa fa-users'></i>");
|
||||
buffer.push(iconHTML('users'));
|
||||
},
|
||||
|
||||
click() {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import ButtonView from 'discourse/views/button';
|
||||
import { iconHTML } from 'discourse/helpers/fa-icon';
|
||||
|
||||
export default ButtonView.extend({
|
||||
classNames: ['share'],
|
||||
|
@ -7,8 +8,7 @@ export default ButtonView.extend({
|
|||
'data-share-url': Em.computed.alias('topic.shareUrl'),
|
||||
topic: Em.computed.alias('controller.model'),
|
||||
|
||||
renderIcon: function(buffer) {
|
||||
buffer.push("<i class='fa fa-link'></i>");
|
||||
renderIcon(buffer) {
|
||||
buffer.push(iconHTML("link"));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -56,26 +56,17 @@ export default Ember.View.extend({
|
|||
return true;
|
||||
});
|
||||
|
||||
$html.on('click.discoure-share-link', '[data-share-url]', function(e) {
|
||||
// if they want to open in a new tab, let it so
|
||||
if (e.shiftKey || e.metaKey || e.ctrlKey || e.which === 2) { return true; }
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
var $currentTarget = $(e.currentTarget),
|
||||
$currentTargetOffset = $currentTarget.offset(),
|
||||
$shareLink = $('#share-link'),
|
||||
url = $currentTarget.data('share-url'),
|
||||
postNumber = $currentTarget.data('post-number'),
|
||||
date = $currentTarget.children().data('time');
|
||||
function showPanel($target, url, postNumber, date) {
|
||||
const $currentTargetOffset = $target.offset();
|
||||
const $shareLink = $('#share-link');
|
||||
|
||||
// Relative urls
|
||||
if (url.indexOf("/") === 0) {
|
||||
url = window.location.protocol + "//" + window.location.host + url;
|
||||
}
|
||||
|
||||
var shareLinkWidth = $shareLink.width();
|
||||
var x = $currentTargetOffset.left - (shareLinkWidth / 2);
|
||||
const shareLinkWidth = $shareLink.width();
|
||||
let x = $currentTargetOffset.left - (shareLinkWidth / 2);
|
||||
if (x < 25) {
|
||||
x = 25;
|
||||
}
|
||||
|
@ -83,8 +74,8 @@ export default Ember.View.extend({
|
|||
x -= shareLinkWidth / 2;
|
||||
}
|
||||
|
||||
var header = $('.d-header');
|
||||
var y = $currentTargetOffset.top - ($shareLink.height() + 20);
|
||||
const header = $('.d-header');
|
||||
let y = $currentTargetOffset.top - ($shareLink.height() + 20);
|
||||
if (y < header.offset().top + header.height()) {
|
||||
y = $currentTargetOffset.top + 10;
|
||||
}
|
||||
|
@ -98,7 +89,21 @@ export default Ember.View.extend({
|
|||
self.set('controller.link', url);
|
||||
self.set('controller.postNumber', postNumber);
|
||||
self.set('controller.date', date);
|
||||
}
|
||||
|
||||
this.appEvents.on('share:url', (url, $target) => showPanel($target, url));
|
||||
|
||||
$html.on('click.discoure-share-link', '[data-share-url]', function(e) {
|
||||
// if they want to open in a new tab, let it so
|
||||
if (e.shiftKey || e.metaKey || e.ctrlKey || e.which === 2) { return true; }
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
const $currentTarget = $(e.currentTarget),
|
||||
url = $currentTarget.data('share-url'),
|
||||
postNumber = $currentTarget.data('post-number'),
|
||||
date = $currentTarget.children().data('time');
|
||||
showPanel($currentTarget, url, postNumber, date);
|
||||
return false;
|
||||
});
|
||||
|
||||
|
|
|
@ -6,22 +6,30 @@ export default ContainerView.extend({
|
|||
|
||||
@on('init')
|
||||
createButtons() {
|
||||
if (this.currentUser.get('staff')) {
|
||||
const mobileView = Discourse.Mobile.mobileView;
|
||||
|
||||
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 topic = this.get('topic');
|
||||
if (!topic.get('isPrivateMessage')) {
|
||||
// We hide some controls from private messages
|
||||
if (this.get('topic.details.can_invite_to')) {
|
||||
this.attachViewClass('invite-reply-button');
|
||||
}
|
||||
this.attachViewClass('bookmark-button');
|
||||
this.attachViewClass('share-button');
|
||||
if (this.get('topic.details.can_flag_topic')) {
|
||||
this.attachViewClass('flag-topic-button');
|
||||
|
||||
if (mobileView) {
|
||||
this.attachViewWithArgs({ topic }, 'topic-footer-mobile-dropdown');
|
||||
} else {
|
||||
// We hide some controls from private messages
|
||||
if (this.get('topic.details.can_invite_to')) {
|
||||
this.attachViewClass('invite-reply-button');
|
||||
}
|
||||
this.attachViewClass('bookmark-button');
|
||||
this.attachViewClass('share-button');
|
||||
if (this.get('topic.details.can_flag_topic')) {
|
||||
this.attachViewClass('flag-topic-button');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (this.get('topic.details.can_create_post')) {
|
||||
this.attachViewClass('reply-button');
|
||||
|
|
|
@ -300,6 +300,13 @@ a.star {
|
|||
border-top: 1px solid dark-light-diff($primary, $secondary, 90%, -60%);
|
||||
padding: 20px 0 0 0;
|
||||
.fa-bookmark.bookmarked { color: $tertiary; }
|
||||
|
||||
.combobox {
|
||||
float: left;
|
||||
margin-right: 1em;
|
||||
width: 160px;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
/* this is to force the drop-down notification state description para below the button */
|
||||
|
|
|
@ -1275,6 +1275,8 @@ en:
|
|||
error: "Sorry, there was an error inviting that user."
|
||||
group_name: "group name"
|
||||
|
||||
controls: "Topic Controls"
|
||||
|
||||
invite_reply:
|
||||
title: 'Invite'
|
||||
username_placeholder: "username"
|
||||
|
|
Loading…
Reference in New Issue