diff --git a/app/assets/javascripts/discourse/components/choose-topic.js.es6 b/app/assets/javascripts/discourse/components/choose-topic.js.es6 index 51955db565..f04765c7a7 100644 --- a/app/assets/javascripts/discourse/components/choose-topic.js.es6 +++ b/app/assets/javascripts/discourse/components/choose-topic.js.es6 @@ -4,6 +4,7 @@ import Component from "@ember/component"; import discourseDebounce from "discourse/lib/debounce"; import { searchForTerm } from "discourse/lib/search"; import { observes } from "discourse-common/utils/decorators"; +import discourseComputed from "discourse-common/utils/decorators"; export default Component.extend({ loading: null, @@ -11,7 +12,33 @@ export default Component.extend({ topics: null, selectedTopicId: null, currentTopicId: null, + additionalFilters: null, topicTitle: null, + label: null, + loadOnInit: false, + topicChangedCallback: null, + + init() { + this._super(...arguments); + + this.additionalFilters = this.additionalFilters || ""; + this.topicTitle = this.topicTitle || ""; + + if (this.loadOnInit && !isEmpty(this.additionalFilters)) { + searchForTerm(this.additionalFilters, {}).then(results => { + if (results && results.posts && results.posts.length > 0) { + this.set( + "topics", + results.posts + .mapBy("topic") + .filter(t => t.id !== this.currentTopicId) + ); + } else { + this.setProperties({ topics: null, loading: false }); + } + }); + } + }, @observes("topicTitle") topicTitleChanged() { @@ -24,6 +51,11 @@ export default Component.extend({ this.search(this.topicTitle); }, + @discourseComputed("label") + labelText(label) { + return label || "choose_topic.title.search"; + }, + @observes("topics") topicsChanged() { if (this.topics) { @@ -38,18 +70,21 @@ export default Component.extend({ return; } - const currentTopicId = this.currentTopicId; - - if (isEmpty(title)) { + if (isEmpty(title) && isEmpty(this.additionalFilters)) { this.setProperties({ topics: null, loading: false }); return; } - searchForTerm(title, { - typeFilter: "topic", - searchForId: true, - restrictToArchetype: "regular" - }).then(results => { + const currentTopicId = this.currentTopicId; + const titleWithFilters = `${title} ${this.additionalFilters}`; + let searchParams = {}; + + if (!isEmpty(title)) { + searchParams.typeFilter = "topic"; + searchParams.restrictToArchetype = "regular"; + } + + searchForTerm(titleWithFilters, searchParams).then(results => { if (results && results.posts && results.posts.length > 0) { this.set( "topics", @@ -67,7 +102,7 @@ export default Component.extend({ next(() => { document.getElementById(`choose-topic-${topic.id}`).checked = true; }); - return false; + if (this.topicChangedCallback) this.topicChangedCallback(topic); } } }); diff --git a/app/assets/javascripts/discourse/components/search-advanced-options.js.es6 b/app/assets/javascripts/discourse/components/search-advanced-options.js.es6 index f0a3d817c1..db8c11ea4b 100644 --- a/app/assets/javascripts/discourse/components/search-advanced-options.js.es6 +++ b/app/assets/javascripts/discourse/components/search-advanced-options.js.es6 @@ -20,7 +20,7 @@ const REGEXP_MIN_POST_COUNT_PREFIX = /^min_post_count:/gi; const REGEXP_POST_TIME_PREFIX = /^(before|after):/gi; const REGEXP_TAGS_REPLACE = /(^(tags?:|#(?=[a-z0-9\-]+::tag))|::tag\s?$)/gi; -const REGEXP_IN_MATCH = /^(in|with):(posted|watching|tracking|bookmarks|first|pinned|unpinned|wiki|unseen|image)/gi; +const REGEXP_IN_MATCH = /^(in|with):(posted|created|watching|tracking|bookmarks|first|pinned|unpinned|wiki|unseen|image)/gi; const REGEXP_SPECIAL_IN_LIKES_MATCH = /^in:likes/gi; const REGEXP_SPECIAL_IN_TITLE_MATCH = /^in:title/gi; const REGEXP_SPECIAL_IN_PERSONAL_MATCH = /^in:personal/gi; @@ -41,6 +41,7 @@ export default Component.extend({ this.inOptionsForUsers = [ { name: I18n.t("search.advanced.filters.unseen"), value: "unseen" }, { name: I18n.t("search.advanced.filters.posted"), value: "posted" }, + { name: I18n.t("search.advanced.filters.created"), value: "created" }, { name: I18n.t("search.advanced.filters.watching"), value: "watching" }, { name: I18n.t("search.advanced.filters.tracking"), value: "tracking" }, { name: I18n.t("search.advanced.filters.bookmarks"), value: "bookmarks" } @@ -57,6 +58,7 @@ export default Component.extend({ this.statusOptions = [ { name: I18n.t("search.advanced.statuses.open"), value: "open" }, { name: I18n.t("search.advanced.statuses.closed"), value: "closed" }, + { name: I18n.t("search.advanced.statuses.public"), value: "public" }, { name: I18n.t("search.advanced.statuses.archived"), value: "archived" }, { name: I18n.t("search.advanced.statuses.noreplies"), diff --git a/app/assets/javascripts/discourse/components/topic-footer-buttons.js.es6 b/app/assets/javascripts/discourse/components/topic-footer-buttons.js.es6 index 468734633e..d37ff5c28f 100644 --- a/app/assets/javascripts/discourse/components/topic-footer-buttons.js.es6 +++ b/app/assets/javascripts/discourse/components/topic-footer-buttons.js.es6 @@ -1,6 +1,5 @@ import discourseComputed from "discourse-common/utils/decorators"; import { alias, or, and } from "@ember/object/computed"; -import { propertyEqual } from "discourse/lib/computed"; import Component from "@ember/component"; import { getTopicFooterButtons } from "discourse/lib/register-topic-footer-button"; @@ -10,11 +9,6 @@ export default Component.extend({ // Allow us to extend it layoutName: "components/topic-footer-buttons", - topicFeaturedOnProfile: propertyEqual( - "topic.id", - "currentUser.featured_topic.id" - ), - @discourseComputed("topic.isPrivateMessage") canArchive(isPM) { return this.siteSettings.enable_personal_messages && isPM; @@ -44,15 +38,6 @@ export default Component.extend({ inviteDisabled: or("topic.archived", "topic.closed", "topic.deleted"), - @discourseComputed - showAdminButton() { - return ( - !this.site.mobileView && - this.currentUser && - this.currentUser.get("canManageTopic") - ); - }, - showEditOnFooter: and("topic.isPrivateMessage", "site.can_tag_pms"), @discourseComputed("topic.message_archived") @@ -64,19 +49,5 @@ export default Component.extend({ @discourseComputed("topic.message_archived") archiveLabel: archived => - archived ? "topic.move_to_inbox.title" : "topic.archive_message.title", - - @discourseComputed( - "topic.user_id", - "topic.isPrivateMessage", - "topic.category.read_restricted" - ) - showToggleFeatureOnProfileButton(userId, isPm, restricted) { - return ( - this.siteSettings.allow_featured_topic_on_user_profiles && - userId === this.currentUser.get("id") && - !restricted && - !isPm - ); - } + archived ? "topic.move_to_inbox.title" : "topic.archive_message.title" }); diff --git a/app/assets/javascripts/discourse/controllers/feature-topic-on-profile.js.es6 b/app/assets/javascripts/discourse/controllers/feature-topic-on-profile.js.es6 new file mode 100644 index 0000000000..4a0db76713 --- /dev/null +++ b/app/assets/javascripts/discourse/controllers/feature-topic-on-profile.js.es6 @@ -0,0 +1,33 @@ +import Controller from "@ember/controller"; +import ModalFunctionality from "discourse/mixins/modal-functionality"; +import { ajax } from "discourse/lib/ajax"; +import { popupAjaxError } from "discourse/lib/ajax-error"; +import { none } from "@ember/object/computed"; + +export default Controller.extend(ModalFunctionality, { + newFeaturedTopic: null, + saving: false, + noTopicSelected: none("newFeaturedTopic"), + + onClose() { + this.set("newFeaturedTopic", null); + }, + + actions: { + save() { + return ajax(`/u/${this.model.username}/feature-topic`, { + type: "PUT", + data: { topic_id: this.newFeaturedTopic.id } + }) + .then(() => { + this.model.set("featured_topic", this.newFeaturedTopic); + this.send("closeModal"); + }) + .catch(popupAjaxError); + }, + + newTopicSelected(topic) { + this.set("newFeaturedTopic", topic); + } + } +}); diff --git a/app/assets/javascripts/discourse/controllers/preferences/profile.js.es6 b/app/assets/javascripts/discourse/controllers/preferences/profile.js.es6 index 764dbb29dc..017035323c 100644 --- a/app/assets/javascripts/discourse/controllers/preferences/profile.js.es6 +++ b/app/assets/javascripts/discourse/controllers/preferences/profile.js.es6 @@ -5,6 +5,8 @@ import { default as discourseComputed } from "discourse-common/utils/decorators" import PreferencesTabController from "discourse/mixins/preferences-tab-controller"; import { popupAjaxError } from "discourse/lib/ajax-error"; import { cookAsync } from "discourse/lib/text"; +import { ajax } from "discourse/lib/ajax"; +import showModal from "discourse/lib/show-modal"; export default Controller.extend(PreferencesTabController, { init() { @@ -48,6 +50,30 @@ export default Controller.extend(PreferencesTabController, { }, actions: { + showFeaturedTopicModal() { + showModal("feature-topic-on-profile", { + model: this.model, + title: "user.feature_topic_on_profile.title" + }); + }, + + clearFeaturedTopicFromProfile() { + bootbox.confirm( + I18n.t("user.feature_topic_on_profile.clear.warning"), + result => { + if (result) { + ajax(`/u/${this.model.username}/clear-featured-topic`, { + type: "PUT" + }) + .then(() => { + this.model.set("featured_topic", null); + }) + .catch(popupAjaxError); + } + } + ); + }, + save() { this.set("saved", false); diff --git a/app/assets/javascripts/discourse/initializers/topic-footer-buttons.js.es6 b/app/assets/javascripts/discourse/initializers/topic-footer-buttons.js.es6 index 4dbca6a9a5..3cd0827a6f 100644 --- a/app/assets/javascripts/discourse/initializers/topic-footer-buttons.js.es6 +++ b/app/assets/javascripts/discourse/initializers/topic-footer-buttons.js.es6 @@ -166,34 +166,5 @@ export default { return this.site.mobileView; } }); - - registerTopicFooterButton({ - dependentKeys: ["currentUser.featured_topic"], - id: "toggle-feature-on-profile", - icon: "id-card", - priority: 300, - label() { - return this.topicFeaturedOnProfile - ? "topic.remove_from_profile.title" - : "topic.feature_on_profile.title"; - }, - title() { - return this.topicFeaturedOnProfile - ? "topic.remove_from_profile.help" - : "topic.feature_on_profile.help"; - }, - classNames() { - return this.topicFeaturedOnProfile - ? ["feature-on-profile", "featured-on-profile"] - : ["feature-on-profile"]; - }, - action: "toggleFeaturedOnProfile", - displayed() { - return this.showToggleFeatureOnProfileButton; - }, - dropdown() { - return this.site.mobileView; - } - }); } }; diff --git a/app/assets/javascripts/discourse/templates/components/choose-topic.hbs b/app/assets/javascripts/discourse/templates/components/choose-topic.hbs index 8ddf70fe57..fd20b847ec 100644 --- a/app/assets/javascripts/discourse/templates/components/choose-topic.hbs +++ b/app/assets/javascripts/discourse/templates/components/choose-topic.hbs @@ -1,4 +1,4 @@ - + {{text-field value=topicTitle placeholderKey="choose_topic.title.placeholder" id="choose-topic-title"}} diff --git a/app/assets/javascripts/discourse/templates/components/topic-footer-buttons.hbs b/app/assets/javascripts/discourse/templates/components/topic-footer-buttons.hbs index 6347270fd2..32483ceb61 100644 --- a/app/assets/javascripts/discourse/templates/components/topic-footer-buttons.hbs +++ b/app/assets/javascripts/discourse/templates/components/topic-footer-buttons.hbs @@ -1,21 +1,21 @@ {{/if}} -{{#if model.featured_topic}} +{{#if siteSettings.allow_featured_topic_on_user_profiles}}
- + {{#if model.featured_topic}} + + {{/if}} + +
+ {{d-button action=(action "showFeaturedTopicModal") + class="btn-primary feature-topic-on-profile-btn" + label="user.feature_topic_on_profile.open_search"}} + {{#if model.featured_topic}} + {{d-button action=(action "clearFeaturedTopicFromProfile") + class="btn-danger clear-feature-topic-on-profile-btn" + label="user.feature_topic_on_profile.clear.title"}} + {{/if}} +
{{i18n 'user.change_featured_topic.instructions'}}
{{/if}} + {{plugin-outlet name="user-preferences-profile" args=(hash model=model save=(action "save"))}} {{plugin-outlet name="user-custom-preferences" args=(hash model=model)}} diff --git a/app/assets/javascripts/discourse/templates/topic.hbs b/app/assets/javascripts/discourse/templates/topic.hbs index f1cdd67765..075cd72048 100644 --- a/app/assets/javascripts/discourse/templates/topic.hbs +++ b/app/assets/javascripts/discourse/templates/topic.hbs @@ -103,6 +103,7 @@ toggleClosed=(action "toggleClosed") toggleArchived=(action "toggleArchived") toggleVisibility=(action "toggleVisibility") + toggleFeaturedOnProfile=(action "toggleFeaturedOnProfile") showTopicStatusUpdate=(route-action "showTopicStatusUpdate") showFeatureTopic=(route-action "showFeatureTopic") showChangeTimestamp=(route-action "showChangeTimestamp") @@ -303,6 +304,7 @@ toggleClosed=(action "toggleClosed") toggleArchived=(action "toggleArchived") toggleVisibility=(action "toggleVisibility") + toggleFeaturedOnProfile=(action "toggleFeaturedOnProfile") showTopicStatusUpdate=(route-action "showTopicStatusUpdate") showFeatureTopic=(route-action "showFeatureTopic") showChangeTimestamp=(route-action "showChangeTimestamp") @@ -314,8 +316,7 @@ toggleArchiveMessage=(action "toggleArchiveMessage") editFirstPost=(action "editFirstPost") deferTopic=(action "deferTopic") - replyToPost=(action "replyToPost") - toggleFeaturedOnProfile=(action "toggleFeaturedOnProfile")}} + replyToPost=(action "replyToPost")}} {{else}}