mirror of
https://github.com/discourse/discourse.git
synced 2025-05-22 22:43:33 +08:00
uses select-box for pinned-button
This commit also moves more logic in dropdown-select-box instead of duplicating it for notifications-options and pinned-options
This commit is contained in:
@ -10,8 +10,6 @@ export default DropdownSelectBoxComponent.extend({
|
||||
|
||||
generatedHeadertext: null,
|
||||
|
||||
fullWidthOnMobile: true,
|
||||
|
||||
@computed
|
||||
content() {
|
||||
const items = [
|
||||
@ -45,20 +43,5 @@ export default DropdownSelectBoxComponent.extend({
|
||||
_didSelectRow() {
|
||||
this.sendAction(`actionNames.${this.get("value")}`);
|
||||
this.set("value", null);
|
||||
},
|
||||
|
||||
@computed
|
||||
templateForRow: function() {
|
||||
return (rowComponent) => {
|
||||
const content = rowComponent.get("content");
|
||||
|
||||
return `
|
||||
<div class="icons">${iconHTML(content.icon)}</div>
|
||||
<div class="texts">
|
||||
<span class="title">${Handlebars.escapeExpression(content.text)}</span>
|
||||
<span class="desc">${Handlebars.escapeExpression(content.description)}</span>
|
||||
</div>
|
||||
`;
|
||||
};
|
||||
}
|
||||
});
|
||||
|
@ -6,7 +6,6 @@ import { iconHTML } from "discourse-common/lib/icon-library";
|
||||
export default NotificationOptionsComponent.extend({
|
||||
classNames: ["category-notifications-button"],
|
||||
|
||||
classNameBindings: ["hidden:is-hidden"],
|
||||
hidden: Ember.computed.or("category.deleted", "site.isMobileDevice"),
|
||||
|
||||
i18nPrefix: "category.notifications",
|
||||
|
@ -1,3 +1,4 @@
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
import SelectBoxComponent from "discourse/components/select-box";
|
||||
|
||||
export default SelectBoxComponent.extend({
|
||||
@ -5,6 +6,28 @@ export default SelectBoxComponent.extend({
|
||||
wrapper: false,
|
||||
verticalOffset: 3,
|
||||
collectionHeight: "auto",
|
||||
fullWidthOnMobile: true,
|
||||
selectBoxHeaderComponent: "dropdown-select-box/dropdown-header",
|
||||
|
||||
selectBoxHeaderComponent: "dropdown-select-box/dropdown-header"
|
||||
@computed
|
||||
templateForRow: function() {
|
||||
return (rowComponent) => {
|
||||
let template = "";
|
||||
const content = rowComponent.get("content");
|
||||
|
||||
const icon = rowComponent.icon();
|
||||
if (icon) {
|
||||
template += `<div class="icons">${icon}</div>`;
|
||||
}
|
||||
|
||||
template += `
|
||||
<div class="texts">
|
||||
<span class="title">${Handlebars.escapeExpression(Ember.get(content, this.get("textKey")))}</span>
|
||||
<span class="desc">${Handlebars.escapeExpression(content.description)}</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
return template;
|
||||
};
|
||||
}
|
||||
});
|
||||
|
@ -1,67 +1,22 @@
|
||||
import { iconHTML } from 'discourse-common/lib/icon-library';
|
||||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
import DropdownButton from 'discourse/components/dropdown-button';
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
|
||||
export default DropdownButton.extend({
|
||||
descriptionKey: 'help',
|
||||
classNames: ['pinned-options'],
|
||||
title: '',
|
||||
buttonExtraClasses: 'btn-icon-text',
|
||||
export default Ember.Component.extend({
|
||||
descriptionKey: "help",
|
||||
|
||||
longDescription: function(){
|
||||
const topic = this.get('topic');
|
||||
const globally = topic.get('pinned_globally') ? '_globally' : '';
|
||||
const key = 'topic_statuses.' + (topic.get('pinned') ? 'pinned' + globally : 'unpinned') + '.help';
|
||||
classNames: ["pinned-button"],
|
||||
|
||||
classNameBindings: ["hidden:is-hidden"],
|
||||
|
||||
@computed("topic.pinned_globally", "topic.pinned")
|
||||
reasonText(pinnedGlobally, pinned) {
|
||||
const globally = pinnedGlobally ? "_globally" : "";
|
||||
const pinnedKey = pinned ? `pinned${globally}` : "unpinned";
|
||||
const key = `topic_statuses.${pinnedKey}.help`;
|
||||
return I18n.t(key);
|
||||
}.property('topic.pinned'),
|
||||
|
||||
target: Em.computed.alias('topic'),
|
||||
|
||||
hidden: function(){
|
||||
const topic = this.get('topic');
|
||||
return topic.get('deleted') || (!topic.get('pinned') && !topic.get('unpinned'));
|
||||
}.property('topic.pinned', 'topic.deleted', 'topic.unpinned'),
|
||||
|
||||
activeItem: function(){
|
||||
return this.get('topic.pinned') ? 'pinned' : 'unpinned';
|
||||
}.property('topic.pinned'),
|
||||
|
||||
dropDownContent: function() {
|
||||
const globally = this.get('topic.pinned_globally') ? '_globally' : '';
|
||||
return [
|
||||
{id: 'pinned',
|
||||
title: I18n.t('topic_statuses.pinned' + globally + '.title'),
|
||||
description: I18n.t('topic_statuses.pinned' + globally + '.help'),
|
||||
icon: 'thumb-tack' },
|
||||
{id: 'unpinned',
|
||||
title: I18n.t('topic_statuses.unpinned.title'),
|
||||
description: I18n.t('topic_statuses.unpinned.help'),
|
||||
icon: 'thumb-tack',
|
||||
iconClass: 'unpinned' }
|
||||
];
|
||||
}.property(),
|
||||
|
||||
@computed('topic.pinned', 'topic.pinned_globally')
|
||||
text(pinned, pinnedGlobally) {
|
||||
const globally = pinnedGlobally ? '_globally' : '';
|
||||
const state = pinned ? 'pinned' + globally : 'unpinned';
|
||||
|
||||
const icon = iconHTML(
|
||||
'thumb-tack',
|
||||
{ tagName: 'span', class: (state === 'unpinned' ? 'unpinned' : null) }
|
||||
);
|
||||
|
||||
return icon +
|
||||
I18n.t('topic_statuses.' + state + '.title') + "<span class='caret'></span>";
|
||||
},
|
||||
|
||||
clicked(id) {
|
||||
const topic = this.get('topic');
|
||||
if(id==='unpinned'){
|
||||
topic.clearPin();
|
||||
} else {
|
||||
topic.rePin();
|
||||
@computed("topic.pinned", "topic.deleted", "topic.unpinned")
|
||||
hidden(pinned, deleted, unpinned) {
|
||||
return deleted || (!pinned && !unpinned);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -0,0 +1,70 @@
|
||||
import DropdownSelectBoxComponent from "discourse/components/dropdown-select-box";
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
import { observes } from "ember-addons/ember-computed-decorators";
|
||||
import { iconHTML } from "discourse-common/lib/icon-library";
|
||||
|
||||
export default DropdownSelectBoxComponent.extend({
|
||||
classNames: ["pinned-options"],
|
||||
|
||||
@computed("topic.pinned")
|
||||
value(pinned) {
|
||||
return pinned ? "pinned" : "unpinned";
|
||||
},
|
||||
|
||||
@observes("topic.pinned")
|
||||
_pinnedChanged() {
|
||||
this.set("value", this.get("topic.pinned") ? "pinned" : "unpinned");
|
||||
},
|
||||
|
||||
@computed("topic.pinned_globally")
|
||||
content(pinnedGlobally) {
|
||||
const globally = pinnedGlobally ? "_globally" : "";
|
||||
|
||||
return [
|
||||
{
|
||||
id: "pinned",
|
||||
text: I18n.t("topic_statuses.pinned" + globally + ".title"),
|
||||
description: I18n.t('topic_statuses.pinned' + globally + '.help'),
|
||||
icon: "thumb-tack"
|
||||
},
|
||||
{
|
||||
id: "unpinned",
|
||||
text: I18n.t("topic_statuses.unpinned.title"),
|
||||
icon: "thumb-tack",
|
||||
description: I18n.t('topic_statuses.unpinned.help'),
|
||||
iconClass: "unpinned"
|
||||
}
|
||||
];
|
||||
},
|
||||
|
||||
@computed("topic.pinned", "topic.pinned_globally")
|
||||
icon(pinned, pinnedGlobally) {
|
||||
const globally = pinnedGlobally ? "_globally" : "";
|
||||
const state = pinned ? `pinned${globally}` : "unpinned";
|
||||
|
||||
return iconHTML(
|
||||
"thumb-tack",
|
||||
{ class: (state === "unpinned" ? "unpinned" : null) }
|
||||
);
|
||||
},
|
||||
|
||||
@computed("topic.pinned", "topic.pinned_globally")
|
||||
generatedHeadertext(pinned, pinnedGlobally) {
|
||||
const globally = pinnedGlobally ? "_globally" : "";
|
||||
const state = pinned ? `pinned${globally}` : "unpinned";
|
||||
const title = I18n.t(`topic_statuses.${state}.title`);
|
||||
|
||||
return `${title}${iconHTML("caret-down")}`.htmlSafe();
|
||||
},
|
||||
|
||||
@observes("value")
|
||||
_didSelectRow() {
|
||||
const topic = this.get("topic");
|
||||
|
||||
if (this.get("value") === "unpinned") {
|
||||
topic.clearPin();
|
||||
} else {
|
||||
topic.rePin();
|
||||
}
|
||||
}
|
||||
});
|
@ -1,17 +1,17 @@
|
||||
import { on, observes } from "ember-addons/ember-computed-decorators";
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
import { iconHTML } from "discourse-common/lib/icon-library";
|
||||
|
||||
export default Ember.Component.extend({
|
||||
layoutName: "components/select-box",
|
||||
classNames: "select-box",
|
||||
classNameBindings: ["expanded:is-expanded"],
|
||||
classNameBindings: ["expanded:is-expanded", "hidden:is-hidden"],
|
||||
|
||||
expanded: false,
|
||||
focused: false,
|
||||
filterFocused: false,
|
||||
renderBody: false,
|
||||
wrapper: true,
|
||||
hidden: false,
|
||||
tabindex: 0,
|
||||
scrollableParentSelector: ".modal-body",
|
||||
|
||||
@ -86,9 +86,7 @@ export default Ember.Component.extend({
|
||||
return (rowComponent) => {
|
||||
let template = "";
|
||||
|
||||
if (rowComponent.get("content.icon")) {
|
||||
template += iconHTML(Handlebars.escapeExpression(rowComponent.get("content.icon")));
|
||||
}
|
||||
template += rowComponent.icon();
|
||||
|
||||
const text = rowComponent.get(`content.${this.get("textKey")}`);
|
||||
template += `<p class="text">${Handlebars.escapeExpression(text)}</p>`;
|
||||
|
@ -1,4 +1,5 @@
|
||||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
import { iconHTML } from "discourse-common/lib/icon-library";
|
||||
|
||||
export default Ember.Component.extend({
|
||||
layoutName: "components/select-box/select-box-row",
|
||||
@ -31,6 +32,16 @@ export default Ember.Component.extend({
|
||||
return shouldSelectRow(this);
|
||||
},
|
||||
|
||||
icon() {
|
||||
if (this.get("content.icon")) {
|
||||
const iconName = this.get("content.icon");
|
||||
const iconClass = this.get("content.iconClass");
|
||||
return iconHTML(iconName, { class: iconClass });
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
mouseEnter() {
|
||||
this.sendAction("onHover", this.get("content"));
|
||||
},
|
||||
|
@ -4,9 +4,9 @@
|
||||
type="button"
|
||||
title="{{text}}">
|
||||
|
||||
{{icon}}
|
||||
{{{icon}}}
|
||||
|
||||
{{#if text}}
|
||||
<span class="d-button-label">{{text}}</span>
|
||||
<span class="d-button-label">{{{text}}}</span>
|
||||
{{/if}}
|
||||
</button>
|
||||
|
@ -0,0 +1,5 @@
|
||||
{{pinned-options topic=topic}}
|
||||
|
||||
<p class="reason">
|
||||
{{{reasonText}}}
|
||||
</p>
|
@ -1,3 +1,4 @@
|
||||
.notifications-button.notifications-button.notifications-button {
|
||||
.d-icon.regular, .d-icon.muted, .d-icon.watching-first-post {
|
||||
color: dark-light-choose(scale-color($primary, $lightness: 40%), scale-color($secondary, $lightness: 60%));
|
||||
}
|
||||
@ -5,3 +6,4 @@
|
||||
color: $tertiary;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
|
@ -3,14 +3,4 @@
|
||||
min-width: auto;
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.select-box-row .icons {
|
||||
align-self: flex-start;
|
||||
width: 30px;
|
||||
justify-content: center;
|
||||
|
||||
.d-icon {
|
||||
color: dark-light-choose(scale-color($primary, $lightness: 40%), scale-color($secondary, $lightness: 60%));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +0,0 @@
|
||||
.category-notification-button.category-notification-button.is-hidden {
|
||||
display: none;
|
||||
}
|
@ -16,6 +16,7 @@
|
||||
background-clip: padding-box;
|
||||
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
|
||||
max-width: 300px;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.select-box-row {
|
||||
@ -25,16 +26,18 @@
|
||||
.icons {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
align-self: center;
|
||||
justify-content: center;
|
||||
align-self: flex-start;
|
||||
margin-right: 10px;
|
||||
margin-top: 2px;
|
||||
width: 30px;
|
||||
|
||||
.d-icon {
|
||||
font-size: 1.286em;
|
||||
align-self: center;
|
||||
margin-right: 0;
|
||||
opacity: 1;
|
||||
color: dark-light-choose(scale-color($primary, $lightness: 40%), scale-color($secondary, $lightness: 60%));
|
||||
}
|
||||
}
|
||||
|
||||
|
44
app/assets/stylesheets/common/components/pinned-button.scss
Normal file
44
app/assets/stylesheets/common/components/pinned-button.scss
Normal file
@ -0,0 +1,44 @@
|
||||
#topic-footer-buttons {
|
||||
.pinned-button {
|
||||
min-width: auto;
|
||||
margin: 10px 0 5px 0;
|
||||
|
||||
&.is-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.reason {
|
||||
line-height: 16px;
|
||||
margin: 0 0 0 10px;
|
||||
|
||||
a {
|
||||
margin-left: 3px;
|
||||
margin-right: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pinned-button {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
min-width: auto;
|
||||
|
||||
.pinned-options, .reason {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.pinned-options.pinned-options.pinned-options {
|
||||
.select-box-body {
|
||||
min-width: unset;
|
||||
max-width: unset;
|
||||
width: 550px;
|
||||
}
|
||||
}
|
||||
}
|
@ -11,6 +11,10 @@
|
||||
height: 34px;
|
||||
min-width: 220px;
|
||||
|
||||
&.is-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.small {
|
||||
height: 28px;
|
||||
}
|
||||
@ -128,6 +132,18 @@
|
||||
margin-left: 5px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.d-button-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
|
||||
.d-icon {
|
||||
margin-left: 5px;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.select-box-body {
|
||||
|
44
test/javascripts/components/pinned-button-test.js.es6
Normal file
44
test/javascripts/components/pinned-button-test.js.es6
Normal file
@ -0,0 +1,44 @@
|
||||
import componentTest from 'helpers/component-test';
|
||||
import Topic from 'discourse/models/topic';
|
||||
|
||||
const buildTopic = function() {
|
||||
return Topic.create({
|
||||
id: 1234,
|
||||
title: "Qunit Test Topic",
|
||||
deleted: false,
|
||||
pinned: true
|
||||
});
|
||||
};
|
||||
|
||||
moduleForComponent('pinned-button', { integration: true });
|
||||
|
||||
componentTest('updating the content refreshes the list', {
|
||||
template: '{{pinned-button topic=topic}}',
|
||||
|
||||
beforeEach() {
|
||||
this.siteSettings.automatically_unpin_topics = false;
|
||||
this.set("topic", buildTopic());
|
||||
},
|
||||
|
||||
test(assert) {
|
||||
andThen(() => {
|
||||
assert.equal(find(".pinned-button").hasClass("is-hidden"), false);
|
||||
});
|
||||
|
||||
click(".select-box-header");
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(find(".select-box-row.is-selected .title").html().trim(), "Pinned");
|
||||
});
|
||||
|
||||
andThen(() => {
|
||||
this.set("topic.pinned", false);
|
||||
assert.equal(find(".select-box-row.is-selected .title").html().trim(), "Unpinned");
|
||||
});
|
||||
|
||||
andThen(() => {
|
||||
this.set("topic.deleted", true);
|
||||
assert.equal(find(".pinned-button").hasClass("is-hidden"), true);
|
||||
});
|
||||
}
|
||||
});
|
@ -129,6 +129,7 @@ export default function() {
|
||||
this.get("/t/28830.json", () => response(fixturesByUrl['/t/28830/1.json']));
|
||||
this.get("/t/9.json", () => response(fixturesByUrl['/t/9/1.json']));
|
||||
this.get("/t/12.json", () => response(fixturesByUrl['/t/12/1.json']));
|
||||
this.put("/t/1234/re-pin", success);
|
||||
|
||||
this.get("/t/id_for/:slug", () => {
|
||||
return response({id: 280, slug: "internationalization-localization", url: "/t/internationalization-localization/280"});
|
||||
|
Reference in New Issue
Block a user