DEV: Ember 3.8.0

Co-Authored-By: majakomel <maja.komel@gmail.com>
This commit is contained in:
Maja Komel 2019-04-26 12:16:21 +02:00 committed by Joffrey JAFFEUX
parent c617e512ad
commit 4b455e741e
63 changed files with 573 additions and 438 deletions

View File

@ -49,7 +49,7 @@ gem 'onebox', '1.8.86'
gem 'http_accept_language', '~>2.0.5', require: false
gem 'ember-rails', '0.18.5'
gem 'discourse-ember-source', '~> 3.7.0'
gem 'discourse-ember-source', '~> 3.8.0'
gem 'ember-handlebars-template', '0.8.0'
gem 'barber'

View File

@ -108,7 +108,7 @@ GEM
terminal-table (~> 1)
debug_inspector (0.0.3)
diff-lcs (1.3)
discourse-ember-source (3.7.0.2)
discourse-ember-source (3.8.0.1)
discourse_image_optim (0.26.2)
exifr (~> 1.2, >= 1.2.2)
fspath (~> 3.0)
@ -472,7 +472,7 @@ DEPENDENCIES
colored2
cppjieba_rb
danger
discourse-ember-source (~> 3.7.0)
discourse-ember-source (~> 3.8.0)
discourse_image_optim
email_reply_trimmer (~> 0.1)
ember-handlebars-template (= 0.8.0)

View File

@ -1,5 +1,6 @@
import { iconHTML } from "discourse-common/lib/icon-library";
import { bufferedRender } from "discourse-common/lib/buffered-render";
import computed from "ember-addons/ember-computed-decorators";
/*global Resumable:true */
@ -27,18 +28,19 @@ export default Ember.Component.extend(
rerenderTriggers: ["isUploading", "progress"],
translatedTitle: function() {
const title = this.get("title");
return title ? I18n.t(title) : this.get("text");
}.property("title", "text"),
@computed("title", "text")
translatedTitle(title, text) {
return title ? I18n.t(title) : text;
},
text: function() {
if (this.get("isUploading")) {
return this.get("progress") + " %";
@computed("isUploading", "progress")
text(isUploading, progress) {
if (isUploading) {
return progress + " %";
} else {
return this.get("uploadText");
}
}.property("isUploading", "progress"),
},
buildBuffer(buffer) {
const icon = this.get("isUploading") ? "times" : "upload";

View File

@ -1,6 +1,7 @@
import { popupAjaxError } from "discourse/lib/ajax-error";
import { bufferedProperty } from "discourse/mixins/buffered-content";
import { propertyNotEqual } from "discourse/lib/computed";
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend(bufferedProperty("model"), {
adminBadges: Ember.inject.controller(),
@ -17,14 +18,13 @@ export default Ember.Controller.extend(bufferedProperty("model"), {
readOnly: Ember.computed.alias("buffered.system"),
showDisplayName: propertyNotEqual("name", "displayName"),
hasQuery: function() {
const bQuery = this.get("buffered.query");
if (bQuery) {
return bQuery.trim().length > 0;
@computed("model.query", "buffered.query")
hasQuery(modelQuery, bufferedQuery) {
if (bufferedQuery) {
return bufferedQuery.trim().length > 0;
}
const mQuery = this.get("model.query");
return mQuery && mQuery.trim().length > 0;
}.property("model.query", "buffered.query"),
return modelQuery && modelQuery.trim().length > 0;
},
_resetSaving: function() {
this.set("saving", false);

View File

@ -1,17 +1,18 @@
import { popupAjaxError } from "discourse/lib/ajax-error";
import { bufferedProperty } from "discourse/mixins/buffered-content";
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend(bufferedProperty("emailTemplate"), {
saved: false,
hasMultipleSubjects: function() {
const buffered = this.get("buffered");
@computed("buffered")
hasMultipleSubjects(buffered) {
if (buffered.getProperties("subject")["subject"]) {
return false;
} else {
return buffered.getProperties("id")["id"];
}
}.property("buffered"),
},
actions: {
saveChanges() {

View File

@ -1,6 +1,7 @@
import { exportEntity } from "discourse/lib/export-csv";
import { outputExportResult } from "discourse/lib/export-result";
import StaffActionLog from "admin/models/staff-action-log";
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend({
loading: false,
@ -20,14 +21,14 @@ export default Ember.Controller.extend({
}
}.observes("filterActionId"),
actionFilter: function() {
var name = this.get("filters.action_name");
@computed("filters.action_name")
actionFilter(name) {
if (name) {
return I18n.t("admin.logs.staff_actions.actions." + name);
} else {
return null;
}
}.property("filters.action_name"),
},
showInstructions: Ember.computed.gt("model.length", 0),

View File

@ -1,4 +1,7 @@
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend({
@computed
adminRoutes: function() {
return this.get("model")
.map(p => {
@ -7,7 +10,8 @@ export default Ember.Controller.extend({
}
})
.compact();
}.property(),
},
actions: {
clearFilter() {
this.setProperties({ filter: "", onlyOverridden: false });

View File

@ -1,5 +1,6 @@
import GrantBadgeController from "discourse/mixins/grant-badge-controller";
import { popupAjaxError } from "discourse/lib/ajax-error";
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend(GrantBadgeController, {
adminUser: Ember.inject.controller(),
@ -10,7 +11,8 @@ export default Ember.Controller.extend(GrantBadgeController, {
sortedBadges: Ember.computed.sort("model", "badgeSortOrder"),
badgeSortOrder: ["granted_at:desc"],
groupedBadges: function() {
@computed("model", "model.[]", "model.expandedBadges.[]")
groupedBadges() {
const allBadges = this.get("model");
var grouped = _.groupBy(allBadges, badge => badge.badge_id);
@ -46,7 +48,7 @@ export default Ember.Controller.extend(GrantBadgeController, {
.sortBy(group => group.granted_at)
.reverse()
.value();
}.property("model", "model.[]", "model.expandedBadges.[]"),
},
actions: {
expandGroup: function(userBadge) {

View File

@ -2,6 +2,7 @@ import debounce from "discourse/lib/debounce";
import { i18n } from "discourse/lib/computed";
import AdminUser from "admin/models/admin-user";
import CanCheckEmails from "discourse/mixins/can-check-emails";
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend(CanCheckEmails, {
model: null,
@ -14,9 +15,10 @@ export default Ember.Controller.extend(CanCheckEmails, {
selectAll: false,
searchHint: i18n("search_hint"),
title: function() {
return I18n.t("admin.users.titles." + this.get("query"));
}.property("query"),
@computed("query")
title(query) {
return I18n.t("admin.users.titles." + query);
},
_filterUsers: debounce(function() {
this._refreshUsers();

View File

@ -1,19 +1,20 @@
export default Ember.Mixin.create({
overridden: function() {
let val = this.get("value"),
defaultVal = this.get("default");
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Mixin.create({
@computed("value", "default")
overridden(val, defaultVal) {
if (val === null) val = "";
if (defaultVal === null) defaultVal = "";
return val.toString() !== defaultVal.toString();
}.property("value", "default"),
},
validValues: function() {
@computed("valid_values")
validValues(validValues) {
const vals = [],
translateNames = this.get("translate_names");
this.get("valid_values").forEach(v => {
validValues.forEach(v => {
if (v.name && v.name.length > 0 && translateNames) {
vals.addObject({ name: I18n.t(v.name), value: v.value });
} else {
@ -21,12 +22,12 @@ export default Ember.Mixin.create({
}
});
return vals;
}.property("valid_values"),
},
allowsNone: function() {
const validValues = this.get("valid_values");
@computed("valid_values")
allowsNone(validValues) {
if (validValues && validValues.indexOf("") >= 0) {
return "admin.settings.none";
}
}.property("valid_values")
}
});

View File

@ -293,17 +293,19 @@ const AdminUser = Discourse.User.extend({
});
},
canLockTrustLevel: function() {
return this.get("trust_level") < 4;
}.property("trust_level"),
@computed("trust_level")
canLockTrustLevel(trustLevel) {
return trustLevel < 4;
},
canSuspend: Ember.computed.not("staff"),
suspendDuration: function() {
const suspended_at = moment(this.suspended_at),
suspended_till = moment(this.suspended_till);
return suspended_at.format("L") + " - " + suspended_till.format("L");
}.property("suspended_till", "suspended_at"),
@computed("suspended_till", "suspended_at")
suspendDuration(suspendedTill, suspendedAt) {
suspendedAt = moment(suspendedAt);
suspendedTill = moment(suspendedTill);
return suspendedAt.format("L") + " - " + suspendedTill.format("L");
},
suspend(data) {
return ajax(`/admin/users/${this.id}/suspend`, {

View File

@ -1,5 +1,6 @@
import { ajax } from "discourse/lib/ajax";
import ColorSchemeColor from "admin/models/color-scheme-color";
import computed from "ember-addons/ember-computed-decorators";
const ColorScheme = Discourse.Model.extend(Ember.Copyable, {
init: function() {
@ -7,9 +8,10 @@ const ColorScheme = Discourse.Model.extend(Ember.Copyable, {
this.startTrackingChanges();
},
description: function() {
@computed
description() {
return "" + this.name;
}.property(),
},
startTrackingChanges: function() {
this.set("originals", {
@ -44,7 +46,8 @@ const ColorScheme = Discourse.Model.extend(Ember.Copyable, {
return newScheme;
},
changed: function() {
@computed("name", "colors.@each.changed", "saving")
changed() {
if (!this.originals) return false;
if (this.originals["name"] !== this.get("name")) return true;
if (
@ -54,24 +57,23 @@ const ColorScheme = Discourse.Model.extend(Ember.Copyable, {
)
return true;
return false;
}.property("name", "colors.@each.changed", "saving"),
},
disableSave: function() {
@computed("changed")
disableSave(changed) {
if (this.get("theme_id")) {
return false;
}
return (
!this.get("changed") ||
!changed ||
this.get("saving") ||
_.any(this.get("colors"), function(c) {
return !c.get("valid");
})
);
}.property("changed"),
},
newRecord: function() {
return !this.get("id");
}.property("id"),
newRecord: Ember.computed.not("id"),
save: function(opts) {
if (this.get("is_base") || this.get("disableSave")) return;

View File

@ -76,25 +76,35 @@ const Report = Discourse.Model.extend({
}
},
todayCount: function() {
@computed("data", "average")
todayCount() {
return this.valueAt(0);
}.property("data", "average"),
yesterdayCount: function() {
return this.valueAt(1);
}.property("data", "average"),
sevenDaysAgoCount: function() {
return this.valueAt(7);
}.property("data", "average"),
thirtyDaysAgoCount: function() {
return this.valueAt(30);
}.property("data", "average"),
},
lastSevenDaysCount: function() {
@computed("data", "average")
yesterdayCount() {
return this.valueAt(1);
},
@computed("data", "average")
sevenDaysAgoCount() {
return this.valueAt(7);
},
@computed("data", "average")
thirtyDaysAgoCount() {
return this.valueAt(30);
},
@computed("data", "average")
lastSevenDaysCount() {
return this.averageCount(7, this.valueFor(1, 7));
}.property("data", "average"),
lastThirtyDaysCount: function() {
},
@computed("data", "average")
lastThirtyDaysCount() {
return this.averageCount(30, this.valueFor(1, 30));
}.property("data", "average"),
},
averageCount(count, value) {
return this.get("average") ? value / count : value;

View File

@ -1,8 +1,11 @@
import { ajax } from "discourse/lib/ajax";
import computed from "ember-addons/ember-computed-decorators";
const ScreenedEmail = Discourse.Model.extend({
actionName: function() {
return I18n.t("admin.logs.screened_actions." + this.get("action"));
}.property("action"),
@computed("action")
actionName(action) {
return I18n.t("admin.logs.screened_actions." + action);
},
clearBlock: function() {
return ajax("/admin/logs/screened_emails/" + this.get("id"), {

View File

@ -1,8 +1,11 @@
import { ajax } from "discourse/lib/ajax";
import computed from "ember-addons/ember-computed-decorators";
const ScreenedUrl = Discourse.Model.extend({
actionName: function() {
return I18n.t("admin.logs.screened_actions." + this.get("action"));
}.property("action")
@computed("action")
actionName(action) {
return I18n.t("admin.logs.screened_actions." + action);
}
});
ScreenedUrl.reopenClass({

View File

@ -11,36 +11,7 @@ export default Discourse.Model.extend({
return Math.round((minDaysVisited * 100) / timePeriod);
},
met: function() {
return {
days_visited: this.get("days_visited") >= this.get("min_days_visited"),
topics_replied_to:
this.get("num_topics_replied_to") >= this.get("min_topics_replied_to"),
topics_viewed: this.get("topics_viewed") >= this.get("min_topics_viewed"),
posts_read: this.get("posts_read") >= this.get("min_posts_read"),
topics_viewed_all_time:
this.get("topics_viewed_all_time") >=
this.get("min_topics_viewed_all_time"),
posts_read_all_time:
this.get("posts_read_all_time") >= this.get("min_posts_read_all_time"),
flagged_posts:
this.get("num_flagged_posts") <= this.get("max_flagged_posts"),
flagged_by_users:
this.get("num_flagged_by_users") <= this.get("max_flagged_by_users"),
likes_given: this.get("num_likes_given") >= this.get("min_likes_given"),
likes_received:
this.get("num_likes_received") >= this.get("min_likes_received"),
likes_received_days:
this.get("num_likes_received_days") >=
this.get("min_likes_received_days"),
likes_received_users:
this.get("num_likes_received_users") >=
this.get("min_likes_received_users"),
level_locked: this.get("trust_level_locked"),
silenced: this.get("penalty_counts.silenced") === 0,
suspended: this.get("penalty_counts.suspended") === 0
};
}.property(
@computed(
"days_visited",
"min_days_visited",
"num_topics_replied_to",
@ -71,4 +42,34 @@ export default Discourse.Model.extend({
"penalty_counts.silenced",
"penalty_counts.suspended"
)
met() {
return {
days_visited: this.get("days_visited") >= this.get("min_days_visited"),
topics_replied_to:
this.get("num_topics_replied_to") >= this.get("min_topics_replied_to"),
topics_viewed: this.get("topics_viewed") >= this.get("min_topics_viewed"),
posts_read: this.get("posts_read") >= this.get("min_posts_read"),
topics_viewed_all_time:
this.get("topics_viewed_all_time") >=
this.get("min_topics_viewed_all_time"),
posts_read_all_time:
this.get("posts_read_all_time") >= this.get("min_posts_read_all_time"),
flagged_posts:
this.get("num_flagged_posts") <= this.get("max_flagged_posts"),
flagged_by_users:
this.get("num_flagged_by_users") <= this.get("max_flagged_by_users"),
likes_given: this.get("num_likes_given") >= this.get("min_likes_given"),
likes_received:
this.get("num_likes_received") >= this.get("min_likes_received"),
likes_received_days:
this.get("num_likes_received_days") >=
this.get("min_likes_received_days"),
likes_received_users:
this.get("num_likes_received_users") >=
this.get("min_likes_received_users"),
level_locked: this.get("trust_level_locked"),
silenced: this.get("penalty_counts.silenced") === 0,
suspended: this.get("penalty_counts.suspended") === 0
};
}
});

View File

@ -1,3 +1,5 @@
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({
tagName: "span",
classNameBindings: [
@ -5,9 +7,12 @@ export default Ember.Component.extend({
"badge.badgeTypeClassName",
"badge.enabled::disabled"
],
title: function() {
return $("<div>" + this.get("badge.description") + "</div>").text();
}.property("badge.description"),
@computed("badge.description")
title(badgeDescription) {
return $("<div>" + badgeDescription + "</div>").text();
},
attributeBindings: ["data-badge-name", "title"],
"data-badge-name": Ember.computed.alias("badge.name")
});

View File

@ -1,15 +1,18 @@
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({
loadingMore: Ember.computed.alias("topicList.loadingMore"),
loading: Ember.computed.not("loaded"),
loaded: function() {
@computed("topicList.loaded")
loaded() {
var topicList = this.get("topicList");
if (topicList) {
return topicList.get("loaded");
} else {
return true;
}
}.property("topicList.loaded"),
},
_topicListChanged: function() {
this._initFromTopicList(this.get("topicList"));
@ -27,9 +30,6 @@ export default Ember.Component.extend({
const topicList = this.get("topicList");
if (topicList) {
this._initFromTopicList(topicList);
} else {
// Without a topic list, we assume it's loaded always.
this.set("loaded", true);
}
},

View File

@ -30,13 +30,25 @@ export default Ember.Component.extend({
noText: Ember.computed.empty("translatedLabel"),
@computed("title")
translatedTitle(title) {
if (title) return I18n.t(title);
translatedTitle: {
get() {
if (this._translatedTitle) return this._translatedTitle;
if (this.title) return I18n.t(this.title);
},
set(value) {
return (this._translatedTitle = value);
}
},
@computed("label")
translatedLabel(label) {
if (label) return I18n.t(label);
translatedLabel: {
get() {
if (this._translatedLabel) return this._translatedLabel;
if (this.label) return I18n.t(this.label);
},
set(value) {
return (this._translatedLabel = value);
}
},
click() {

View File

@ -1,9 +1,10 @@
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({
visible: function() {
var bannerKey = this.get("banner.key"),
@computed("user.dismissed_banner_key", "banner.key", "hide")
visible(dismissedBannerKey, bannerKey, hide) {
dismissedBannerKey =
this.get("user.dismissed_banner_key") ||
this.keyValueStore.get("dismissed_banner_key");
dismissedBannerKey || this.keyValueStore.get("dismissed_banner_key");
if (bannerKey) {
bannerKey = parseInt(bannerKey, 10);
@ -12,8 +13,8 @@ export default Ember.Component.extend({
dismissedBannerKey = parseInt(dismissedBannerKey, 10);
}
return !this.get("hide") && bannerKey && dismissedBannerKey !== bannerKey;
}.property("user.dismissed_banner_key", "banner.key", "hide"),
return !hide && bannerKey && dismissedBannerKey !== bannerKey;
},
actions: {
dismiss() {

View File

@ -1,13 +1,17 @@
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({
tagName: "a",
classNameBindings: [":discourse-tag", "style", "tagClass"],
attributeBindings: ["href"],
tagClass: function() {
return "tag-" + this.get("tagRecord.id");
}.property("tagRecord.id"),
@computed("tagRecord.id")
tagClass(tagRecordId) {
return "tag-" + tagRecordId;
},
href: function() {
return Discourse.getURL("/tags/" + this.get("tagRecord.id"));
}.property("tagRecord.id")
@computed("tagRecord.id")
href(tagRecordId) {
return Discourse.getURL("/tags/" + tagRecordId);
}
});

View File

@ -1,18 +1,21 @@
import { propertyEqual } from "discourse/lib/computed";
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({
tagName: "li",
classNameBindings: ["active", "tabClassName"],
tabClassName: function() {
return "edit-category-" + this.get("tab");
}.property("tab"),
@computed("tab")
tabClassName(tab) {
return "edit-category-" + tab;
},
active: propertyEqual("selectedTab", "tab"),
title: function() {
return I18n.t("category." + this.get("tab").replace("-", "_"));
}.property("tab"),
@computed("tab")
title(tab) {
return I18n.t("category." + tab.replace("-", "_"));
},
didInsertElement() {
this._super(...arguments);

View File

@ -1,9 +1,12 @@
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({
classNames: ["controls"],
label: function() {
return I18n.t(this.get("labelKey"));
}.property("labelKey"),
@computed("labelKey")
label(labelKey) {
return I18n.t(labelKey);
},
change() {
const warning = this.get("warning");

View File

@ -1,4 +1,5 @@
import DiscourseURL from "discourse/lib/url";
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({
tagName: "a",
@ -10,17 +11,19 @@ export default Ember.Component.extend({
],
attributeBindings: ["href"],
href: function() {
@computed("tagId", "category")
href(tagId, category) {
var url = "/tags";
if (this.get("category")) {
url += this.get("category.url");
if (category) {
url += category.url;
}
return url + "/" + this.get("tagId");
}.property("tagId", "category"),
return url + "/" + tagId;
},
tagClass: function() {
return "tag-" + this.get("tagId");
}.property("tagId"),
@computed("tagId")
tagClass(tagId) {
return "tag-" + tagId;
},
click(e) {
e.preventDefault();

View File

@ -38,7 +38,13 @@ export default Ember.TextField.extend({
},
@computed("placeholderKey")
placeholder(placeholderKey) {
return placeholderKey ? I18n.t(placeholderKey) : "";
placeholder: {
get() {
if (this._placeholder) return this._placeholder;
return this.placeholderKey ? I18n.t(this.placeholderKey) : "";
},
set(value) {
return (this._placeholder = value);
}
}
});

View File

@ -1,10 +1,12 @@
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({
classNames: ["top-title-buttons"],
periods: function() {
const period = this.get("period");
@computed("period")
periods(period) {
return this.site.get("periods").filter(p => p !== period);
}.property("period"),
},
actions: {
changePeriod(p) {

View File

@ -1,4 +1,7 @@
import { observes } from "ember-addons/ember-computed-decorators";
import {
default as computed,
observes
} from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({
tagName: "table",
@ -16,25 +19,25 @@ export default Ember.Component.extend({
this.refreshLastVisited();
}.on("init"),
toggleInTitle: function() {
return !this.get("bulkSelectEnabled") && this.get("canBulkSelect");
}.property("bulkSelectEnabled"),
@computed("bulkSelectEnabled")
toggleInTitle(bulkSelectEnabled) {
return !bulkSelectEnabled && this.get("canBulkSelect");
},
sortable: function() {
@computed
sortable() {
return !!this.get("changeSort");
}.property(),
},
skipHeader: function() {
return this.site.mobileView;
}.property(),
@computed("order")
showLikes(order) {
return order === "likes";
},
showLikes: function() {
return this.get("order") === "likes";
}.property("order"),
showOpLikes: function() {
return this.get("order") === "op_likes";
}.property("order"),
@computed("order")
showOpLikes(order) {
return order === "op_likes";
},
@observes("topics.[]")
topicsAdded() {

View File

@ -2,6 +2,7 @@ import { iconHTML } from "discourse-common/lib/icon-library";
import { bufferedRender } from "discourse-common/lib/buffered-render";
import { escapeExpression } from "discourse/lib/utilities";
import TopicStatusIcons from "discourse/helpers/topic-status-icons";
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend(
bufferedRender({
@ -26,9 +27,10 @@ export default Ember.Component.extend(
return false;
},
canAct: function() {
return Discourse.User.current() && !this.get("disableActions");
}.property("disableActions"),
@computed("disableActions")
canAct(disableActions) {
return Discourse.User.current() && !disableActions;
},
buildBuffer(buffer) {
const canAct = this.get("canAct");

View File

@ -1,14 +1,18 @@
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({
tagName: "span",
showGrantCount: function() {
return this.get("count") && this.get("count") > 1;
}.property("count"),
@computed("count")
showGrantCount(count) {
return count && count > 1;
},
badgeUrl: function() {
@computed("badge", "user")
badgeUrl() {
// NOTE: I tried using a link-to helper here but the queryParams mean it fails
var username = this.get("user.username_lower") || "";
username = username !== "" ? "?username=" + username : "";
return this.get("badge.url") + username;
}.property("badge", "user")
}
});

View File

@ -1,10 +1,12 @@
import { fmt } from "discourse/lib/computed";
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({
classNameBindings: [":user-field", "field.field_type"],
layoutName: fmt("field.field_type", "components/user-fields/%@"),
noneLabel: function() {
@computed
noneLabel() {
return "user_fields.none";
}.property()
}
});

View File

@ -1,7 +1,10 @@
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend({
faqOverriden: Ember.computed.gt("siteSettings.faq_url.length", 0),
contactInfo: function() {
@computed
contactInfo() {
if (this.siteSettings.contact_url) {
return I18n.t("about.contact_info", {
contact_info:
@ -18,5 +21,5 @@ export default Ember.Controller.extend({
} else {
return null;
}
}.property()
}
});

View File

@ -1,6 +1,9 @@
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend({
badgeGroups: function() {
var sorted = _.sortBy(this.get("model"), function(badge) {
@computed("model")
badgeGroups(model) {
var sorted = _.sortBy(model, function(badge) {
var pos = badge.get("badge_grouping.position");
var type = badge.get("badge_type_id");
var name = badge.get("name");
@ -31,5 +34,5 @@ export default Ember.Controller.extend({
}
return grouped;
}.property("model")
}
});

View File

@ -12,9 +12,10 @@ export default Ember.Controller.extend(BadgeSelectController, {
application: Ember.inject.controller(),
hiddenSetTitle: true,
filteredList: function() {
return this.get("userBadgesAll").filterBy("badge.allow_title", true);
}.property("userBadgesAll"),
@computed("userBadgesAll")
filteredList(userBadgesAll) {
return userBadgesAll.filterBy("badge.allow_title", true);
},
@computed("username")
user(username) {

View File

@ -39,6 +39,7 @@ function loadDraft(store, opts) {
((draft.title && draft.title !== "") || (draft.reply && draft.reply !== ""))
) {
const composer = store.createRecord("composer");
composer.open({
draftKey,
draftSequence,
@ -301,14 +302,12 @@ export default Ember.Controller.extend({
}
},
showWarning: function() {
@computed("model.creatingPrivateMessage", "model.targetUsernames")
showWarning(creatingPrivateMessage, usernames) {
if (!Discourse.User.currentProp("staff")) {
return false;
}
var usernames = this.get("model.targetUsernames");
var hasTargetGroups = this.get("model.hasTargetGroups");
// We need exactly one user to issue a warning
if (
Ember.isEmpty(usernames) ||
@ -317,8 +316,8 @@ export default Ember.Controller.extend({
) {
return false;
}
return this.get("model.creatingPrivateMessage");
}.property("model.creatingPrivateMessage", "model.targetUsernames"),
return creatingPrivateMessage;
},
@computed("model.topic")
draftTitle(topic) {
@ -1102,15 +1101,13 @@ export default Ember.Controller.extend({
$(".d-editor-input").autocomplete({ cancel: true });
},
canEdit: function() {
return (
this.get("model.action") === "edit" &&
Discourse.User.current().get("can_edit")
);
}.property("model.action"),
@computed("model.action")
canEdit(action) {
return action === "edit" && Discourse.User.current().get("can_edit");
},
visible: function() {
var state = this.get("model.composeState");
@computed("model.composeState")
visible(state) {
return state && state !== "closed";
}.property("model.composeState")
}
});

View File

@ -1,7 +1,10 @@
import { ajax } from "discourse/lib/ajax";
import ModalFunctionality from "discourse/mixins/modal-functionality";
import { setting } from "discourse/lib/computed";
import { on } from "ember-addons/ember-computed-decorators";
import {
default as computed,
on
} from "ember-addons/ember-computed-decorators";
import { emailValid } from "discourse/lib/utilities";
import InputValidation from "discourse/models/input-validation";
import PasswordValidation from "discourse/mixins/password-validation";
@ -51,7 +54,16 @@ export default Ember.Controller.extend(
this._createUserFields();
},
submitDisabled: function() {
@computed(
"passwordRequired",
"nameValidation.failed",
"emailValidation.failed",
"usernameValidation.failed",
"passwordValidation.failed",
"userFieldsValidation.failed",
"formSubmitted"
)
submitDisabled() {
if (!this.get("emailValidation.failed") && !this.get("passwordRequired"))
return false; // 3rd party auth
if (this.get("formSubmitted")) return true;
@ -62,51 +74,44 @@ export default Ember.Controller.extend(
if (this.get("userFieldsValidation.failed")) return true;
return false;
}.property(
"passwordRequired",
"nameValidation.failed",
"emailValidation.failed",
"usernameValidation.failed",
"passwordValidation.failed",
"userFieldsValidation.failed",
"formSubmitted"
),
},
usernameRequired: Ember.computed.not("authOptions.omit_username"),
fullnameRequired: function() {
@computed
fullnameRequired() {
return (
this.get("siteSettings.full_name_required") ||
this.get("siteSettings.enable_names")
);
}.property(),
},
passwordRequired: function() {
return Ember.isEmpty(this.get("authOptions.auth_provider"));
}.property("authOptions.auth_provider"),
@computed("authOptions.auth_provider")
passwordRequired(authProvider) {
return Ember.isEmpty(authProvider);
},
disclaimerHtml: function() {
@computed
disclaimerHtml() {
return I18n.t("create_account.disclaimer", {
tos_link: this.get("siteSettings.tos_url") || Discourse.getURL("/tos"),
privacy_link:
this.get("siteSettings.privacy_policy_url") ||
Discourse.getURL("/privacy")
});
}.property(),
},
// Check the email address
emailValidation: function() {
@computed("accountEmail", "rejectedEmails.[]")
emailValidation(email, rejectedEmails) {
// If blank, fail without a reason
let email;
if (Ember.isEmpty(this.get("accountEmail"))) {
if (Ember.isEmpty(email)) {
return InputValidation.create({
failed: true
});
}
email = this.get("accountEmail");
if (this.get("rejectedEmails").includes(email)) {
if (rejectedEmails.includes(email)) {
return InputValidation.create({
failed: true,
reason: I18n.t("user.email.invalid")
@ -138,14 +143,15 @@ export default Ember.Controller.extend(
failed: true,
reason: I18n.t("user.email.invalid")
});
}.property("accountEmail", "rejectedEmails.[]"),
},
emailValidated: function() {
@computed("accountEmail", "authOptions.email", "authOptions.email_valid")
emailValidated() {
return (
this.get("authOptions.email") === this.get("accountEmail") &&
this.get("authOptions.email_valid")
);
}.property("accountEmail", "authOptions.email", "authOptions.email_valid"),
},
authProviderDisplayName(providerName) {
const matchingProvider = findAll().find(provider => {
@ -178,9 +184,10 @@ export default Ember.Controller.extend(
}.observes("emailValidation", "accountEmail"),
// Determines whether at least one login button is enabled
hasAtLeastOneLoginButton: function() {
@computed
hasAtLeastOneLoginButton() {
return findAll(this.siteSettings).length > 0;
}.property(),
},
@on("init")
fetchConfirmationValue() {

View File

@ -5,6 +5,7 @@ import { endWith } from "discourse/lib/computed";
import showModal from "discourse/lib/show-modal";
import { userPath } from "discourse/lib/url";
import TopicList from "discourse/models/topic-list";
import computed from "ember-addons/ember-computed-decorators";
const controllerOpts = {
discovery: Ember.inject.controller(),
@ -96,26 +97,24 @@ const controllerOpts = {
return filter.match(new RegExp(filterType + "$", "gi")) ? true : false;
},
showDismissRead: function() {
return (
this.isFilterPage(this.get("model.filter"), "unread") &&
this.get("model.topics.length") > 0
);
}.property("model.filter", "model.topics.length"),
@computed("model.filter", "model.topics.length")
showDismissRead(filter, topicsLength) {
return this.isFilterPage(filter, "unread") && topicsLength > 0;
},
showResetNew: function() {
return (
this.get("model.filter") === "new" && this.get("model.topics.length") > 0
);
}.property("model.filter", "model.topics.length"),
@computed("model.filter", "model.topics.length")
showResetNew(filter, topicsLength) {
return filter === "new" && topicsLength > 0;
},
showDismissAtTop: function() {
@computed("model.filter", "model.topics.length")
showDismissAtTop(filter, topicsLength) {
return (
(this.isFilterPage(this.get("model.filter"), "new") ||
this.isFilterPage(this.get("model.filter"), "unread")) &&
this.get("model.topics.length") >= 15
(this.isFilterPage(filter, "new") ||
this.isFilterPage(filter, "unread")) &&
topicsLength >= 15
);
}.property("model.filter", "model.topics.length"),
},
hasTopics: Ember.computed.gt("model.topics.length", 0),
allLoaded: Ember.computed.empty("model.more_topics_url"),
@ -128,10 +127,9 @@ const controllerOpts = {
weekly: Ember.computed.equal("period", "weekly"),
daily: Ember.computed.equal("period", "daily"),
footerMessage: function() {
if (!this.get("allLoaded")) {
return;
}
@computed("allLoaded", "model.topics.length")
footerMessage(allLoaded, topicsLength) {
if (!allLoaded) return;
const category = this.get("category");
if (category) {
@ -140,7 +138,7 @@ const controllerOpts = {
});
} else {
const split = (this.get("model.filter") || "").split("/");
if (this.get("model.topics.length") === 0) {
if (topicsLength === 0) {
return I18n.t("topics.none." + split[0], {
category: split[1]
});
@ -150,14 +148,11 @@ const controllerOpts = {
});
}
}
}.property("allLoaded", "model.topics.length"),
},
footerEducation: function() {
if (
!this.get("allLoaded") ||
this.get("model.topics.length") > 0 ||
!this.currentUser
) {
@computed("allLoaded", "model.topics.length")
footerEducation(allLoaded, topicsLength) {
if (!allLoaded || topicsLength > 0 || !this.currentUser) {
return;
}
@ -173,7 +168,7 @@ const controllerOpts = {
`${this.currentUser.get("username_lower")}/preferences`
)
});
}.property("allLoaded", "model.topics.length")
}
};
Object.keys(queryParams).forEach(function(p) {

View File

@ -1,6 +1,7 @@
import ModalFunctionality from "discourse/mixins/modal-functionality";
import DiscourseURL from "discourse/lib/url";
import { extractError } from "discourse/lib/ajax-error";
import computed from "ember-addons/ember-computed-decorators";
// Modal for editing / creating a category
export default Ember.Controller.extend(ModalFunctionality, {
@ -28,39 +29,44 @@ export default Ember.Controller.extend(ModalFunctionality, {
}
}.observes("model.description"),
title: function() {
if (this.get("model.id")) {
@computed("model.id", "model.name")
title(id, name) {
if (id) {
return I18n.t("category.edit_dialog_title", {
categoryName: this.get("model.name")
categoryName: name
});
}
return I18n.t("category.create");
}.property("model.id", "model.name"),
},
titleChanged: function() {
this.set("modal.title", this.get("title"));
}.observes("title"),
disabled: function() {
if (this.get("saving") || this.get("deleting")) return true;
if (!this.get("model.name")) return true;
if (!this.get("model.color")) return true;
@computed("saving", "model.name", "model.color", "deleting")
disabled(saving, name, color, deleting) {
if (saving || deleting) return true;
if (!name) return true;
if (!color) return true;
return false;
}.property("saving", "model.name", "model.color", "deleting"),
},
deleteDisabled: function() {
return this.get("deleting") || this.get("saving") || false;
}.property("disabled", "saving", "deleting"),
@computed("saving", "deleting")
deleteDisabled(saving, deleting) {
return deleting || saving || false;
},
categoryName: function() {
const name = this.get("name") || "";
@computed("name")
categoryName(name) {
name = name || "";
return name.trim().length > 0 ? name : I18n.t("preview");
}.property("name"),
},
saveLabel: function() {
if (this.get("saving")) return "saving";
return this.get("model.id") ? "category.save" : "category.create";
}.property("saving", "model.id"),
@computed("saving", "model.id")
saveLabel(saving, id) {
if (saving) return "saving";
return id ? "category.save" : "category.create";
},
actions: {
saveCategory() {

View File

@ -1,3 +1,5 @@
import computed from "ember-addons/ember-computed-decorators";
var ButtonBackBright = {
classes: "btn-primary",
action: "back",
@ -25,13 +27,14 @@ export default Ember.Controller.extend({
thrown: null,
lastTransition: null,
@computed
isNetwork: function() {
// never made it on the wire
if (this.get("thrown.readyState") === 0) return true;
// timed out
if (this.get("thrown.jqTextStatus") === "timeout") return true;
return false;
}.property(),
},
isNotFound: Ember.computed.equal("thrown.status", 404),
isForbidden: Ember.computed.equal("thrown.status", 403),
@ -48,7 +51,8 @@ export default Ember.Controller.extend({
this.set("loading", false);
}.on("init"),
reason: function() {
@computed("isNetwork", "isServer", "isUnknown")
reason() {
if (this.get("isNetwork")) {
return I18n.t("errors.reasons.network");
} else if (this.get("isServer")) {
@ -61,11 +65,12 @@ export default Ember.Controller.extend({
// TODO
return I18n.t("errors.reasons.unknown");
}
}.property("isNetwork", "isServer", "isUnknown"),
},
requestUrl: Ember.computed.alias("thrown.requestedUrl"),
desc: function() {
@computed("networkFixed", "isNetwork", "isServer", "isUnknown")
desc() {
if (this.get("networkFixed")) {
return I18n.t("errors.desc.network_fixed");
} else if (this.get("isNetwork")) {
@ -80,9 +85,10 @@ export default Ember.Controller.extend({
// TODO
return I18n.t("errors.desc.unknown");
}
}.property("networkFixed", "isNetwork", "isServer", "isUnknown"),
},
enabledButtons: function() {
@computed("networkFixed", "isNetwork", "isServer", "isUnknown")
enabledButtons() {
if (this.get("networkFixed")) {
return [ButtonLoadPage];
} else if (this.get("isNetwork")) {
@ -90,7 +96,7 @@ export default Ember.Controller.extend({
} else {
return [ButtonBackBright, ButtonTryAgain];
}
}.property("networkFixed", "isNetwork", "isServer", "isUnknown"),
},
actions: {
back: function() {

View File

@ -39,7 +39,8 @@ export default Ember.Controller.extend(ModalFunctionality, {
return flagTopic ? "flagging_topic.title" : "flagging.title";
},
flagsAvailable: function() {
@computed("post", "flagTopic", "model.actions_summary.@each.can_act")
flagsAvailable() {
if (!this.get("flagTopic")) {
// flagging post
let flagsAvailable = this.get("model.flagsAvailable");
@ -71,16 +72,18 @@ export default Ember.Controller.extend(ModalFunctionality, {
});
});
}
}.property("post", "flagTopic", "model.actions_summary.@each.can_act"),
},
staffFlagsAvailable: function() {
@computed("post", "flagTopic", "model.actions_summary.@each.can_act")
staffFlagsAvailable() {
return (
this.get("model.flagsAvailable") &&
this.get("model.flagsAvailable").length > 1
);
}.property("post", "flagTopic", "model.actions_summary.@each.can_act"),
},
submitEnabled: function() {
@computed("selected.is_custom_flag", "message.length")
submitEnabled() {
const selected = this.get("selected");
if (!selected) return false;
@ -92,7 +95,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
);
}
return true;
}.property("selected.is_custom_flag", "message.length"),
},
submitDisabled: Ember.computed.not("submitEnabled"),

View File

@ -284,17 +284,18 @@ export default Ember.Controller.extend(ModalFunctionality, {
}
},
authMessage: function() {
if (Ember.isEmpty(this.get("authenticate"))) return "";
@computed("authenticate")
authMessage(authenticate) {
if (Ember.isEmpty(authenticate)) return "";
const method = findAll(
this.siteSettings,
this.capabilities,
this.isMobileDevice
).findBy("name", this.get("authenticate"));
).findBy("name", authenticate);
if (method) {
return method.get("message");
}
}.property("authenticate"),
},
authenticationComplete(options) {
const self = this;

View File

@ -1,9 +1,11 @@
import NavigationDefaultController from "discourse/controllers/navigation/default";
import computed from "ember-addons/ember-computed-decorators";
export default NavigationDefaultController.extend({
discoveryCategories: Ember.inject.controller("discovery/categories"),
draft: function() {
@computed("discoveryCategories.model", "discoveryCategories.model.draft")
draft() {
return this.get("discoveryCategories.model.draft");
}.property("discoveryCategories.model", "discoveryCategories.model.draft")
}
});

View File

@ -1,8 +1,11 @@
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend({
discovery: Ember.inject.controller(),
discoveryTopics: Ember.inject.controller("discovery/topics"),
@computed("discoveryTopics.model", "discoveryTopics.model.draft")
draft: function() {
return this.get("discoveryTopics.model.draft");
}.property("discoveryTopics.model", "discoveryTopics.model.draft")
}
});

View File

@ -1,8 +1,11 @@
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend({
saving: false,
newBio: null,
saveButtonText: function() {
return this.get("saving") ? I18n.t("saving") : I18n.t("user.change");
}.property("saving")
@computed("saving")
saveButtonText(saving) {
return saving ? I18n.t("saving") : I18n.t("user.change");
}
});

View File

@ -77,9 +77,10 @@ export default Ember.Controller.extend(PreferencesTabController, {
});
},
userSelectableThemes: function() {
@computed
userSelectableThemes() {
return listThemes(this.site);
}.property(),
},
@computed("userSelectableThemes")
showThemeSelector(themes) {

View File

@ -26,13 +26,14 @@ export default Ember.Controller.extend(ModalFunctionality, Ember.Evented, {
"categoriesSorting"
),
showApplyAll: function() {
@computed("categoriesBuffered.@each.hasBufferedChanges")
showApplyAll() {
let anyChanged = false;
this.get("categoriesBuffered").forEach(bc => {
anyChanged = anyChanged || bc.get("hasBufferedChanges");
});
return anyChanged;
}.property("categoriesBuffered.@each.hasBufferedChanges"),
},
moveDir(cat, dir) {
const cats = this.get("categoriesOrdered");

View File

@ -1,7 +1,9 @@
import ModalFunctionality from "discourse/mixins/modal-functionality";
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend(ModalFunctionality, {
showGoogleSearch: function() {
@computed
showGoogleSearch() {
return !Discourse.SiteSettings.login_required;
}.property()
}
});

View File

@ -16,12 +16,12 @@ export default Ember.Controller.extend({
pmTaggingEnabled: Ember.computed.alias("site.can_tag_pms"),
tagId: null,
showNewPM: function() {
@computed("user.viewingSelf")
showNewPM(viewingSelf) {
return (
this.get("user.viewingSelf") &&
Discourse.User.currentProp("can_send_private_messages")
viewingSelf && Discourse.User.currentProp("can_send_private_messages")
);
}.property("user.viewingSelf"),
},
@computed("selected.[]", "bulkSelectEnabled")
hasSelection(selected, bulkSelectEnabled) {

View File

@ -1,4 +1,5 @@
import addonFmt from "ember-addons/fmt";
/**
Returns whether two properties are equal to each other.
@ -7,10 +8,11 @@ import addonFmt from "ember-addons/fmt";
@params {String} p2 the second property
@return {Function} computedProperty function
**/
export function propertyEqual(p1, p2) {
return Ember.computed(function() {
return Ember.computed(p1, p2, function() {
return this.get(p1) === this.get(p2);
}).property(p1, p2);
});
}
/**
@ -22,21 +24,21 @@ export function propertyEqual(p1, p2) {
@return {Function} computedProperty function
**/
export function propertyNotEqual(p1, p2) {
return Ember.computed(function() {
return Ember.computed(p1, p2, function() {
return this.get(p1) !== this.get(p2);
}).property(p1, p2);
});
}
export function propertyGreaterThan(p1, p2) {
return Ember.computed(function() {
return Ember.computed(p1, p2, function() {
return this.get(p1) > this.get(p2);
}).property(p1, p2);
});
}
export function propertyLessThan(p1, p2) {
return Ember.computed(function() {
return Ember.computed(p1, p2, function() {
return this.get(p1) < this.get(p2);
}).property(p1, p2);
});
}
/**

View File

@ -1,11 +1,12 @@
import Badge from "discourse/models/badge";
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Mixin.create({
saving: false,
saved: false,
selectableUserBadges: function() {
let items = this.get("filteredList");
@computed("filteredList")
selectableUserBadges(items) {
items = _.uniq(items, false, function(e) {
return e.get("badge.name");
});
@ -15,18 +16,16 @@ export default Ember.Mixin.create({
})
);
return items;
}.property("filteredList"),
},
savingStatus: function() {
if (this.get("saving")) {
return I18n.t("saving");
} else {
return I18n.t("save");
}
}.property("saving"),
@computed("saving")
savingStatus(saving) {
return saving ? I18n.t("saving") : I18n.t("save");
},
selectedUserBadge: function() {
const selectedUserBadgeId = parseInt(this.get("selectedUserBadgeId"));
@computed("selectedUserBadgeId")
selectedUserBadge(selectedUserBadgeId) {
selectedUserBadgeId = parseInt(selectedUserBadgeId);
let selectedUserBadge = null;
this.get("selectableUserBadges").forEach(function(userBadge) {
if (userBadge.get("id") === selectedUserBadgeId) {
@ -34,7 +33,7 @@ export default Ember.Mixin.create({
}
});
return selectedUserBadge;
}.property("selectedUserBadgeId"),
},
disableSave: Ember.computed.alias("saving")
});

View File

@ -3,9 +3,7 @@ import RestModel from "discourse/models/rest";
import { popupAjaxError } from "discourse/lib/ajax-error";
export default RestModel.extend({
canToggle: function() {
return this.get("can_undo") || this.get("can_act");
}.property("can_undo", "can_act"),
canToggle: Ember.computed.or("can_undo", "can_act"),
// Remove it
removeAction: function() {

View File

@ -1,13 +1,15 @@
import { ajax } from "discourse/lib/ajax";
import BadgeGrouping from "discourse/models/badge-grouping";
import RestModel from "discourse/models/rest";
import computed from "ember-addons/ember-computed-decorators";
const Badge = RestModel.extend({
newBadge: Ember.computed.none("id"),
url: function() {
@computed
url() {
return Discourse.getURL(`/badges/${this.get("id")}/${this.get("slug")}`);
}.property(),
},
/**
Update this badge with the response returned by the server on save.
@ -31,10 +33,11 @@ const Badge = RestModel.extend({
}
},
badgeTypeClassName: function() {
const type = this.get("badge_type.name") || "";
@computed("badge_type.name")
badgeTypeClassName(type) {
type = type || "";
return "badge-type-" + type.toLowerCase();
}.property("badge_type.name"),
},
/**
Save and update the badge from the server's response.

View File

@ -77,9 +77,10 @@ const Composer = RestModel.extend({
draftSaving: false,
draftSaved: false,
archetypes: function() {
@computed
archetypes() {
return this.site.get("archetypes");
}.property(),
},
@computed("action")
sharedDraft: action => action === CREATE_SHARED_DRAFT,
@ -184,9 +185,10 @@ const Composer = RestModel.extend({
.property()
.volatile(),
archetype: function() {
return this.get("archetypes").findBy("id", this.get("archetypeId"));
}.property("archetypeId"),
@computed("archetypeId")
archetype(archetypeId) {
return this.get("archetypes").findBy("id", archetypeId);
},
archetypeChanged: function() {
return this.set("metaData", Ember.Object.create());
@ -377,30 +379,27 @@ const Composer = RestModel.extend({
);
},
titleLengthValid: function() {
if (
this.user.get("admin") &&
this.get("post.static_doc") &&
this.get("titleLength") > 0
)
return true;
if (this.get("titleLength") < this.get("minimumTitleLength")) return false;
return this.get("titleLength") <= this.siteSettings.max_topic_title_length;
}.property("minimumTitleLength", "titleLength", "post.static_doc"),
@computed("minimumTitleLength", "titleLength", "post.static_doc")
titleLengthValid(minTitleLength, titleLength, staticDoc) {
if (this.user.get("admin") && staticDoc && titleLength > 0) return true;
if (titleLength < minTitleLength) return false;
return titleLength <= this.siteSettings.max_topic_title_length;
},
hasMetaData: function() {
const metaData = this.get("metaData");
@computed("metaData")
hasMetaData(metaData) {
return metaData ? Ember.isEmpty(Ember.keys(this.get("metaData"))) : false;
}.property("metaData"),
},
/**
Did the user make changes to the reply?
@property replyDirty
**/
replyDirty: function() {
return this.get("reply") !== this.get("originalText");
}.property("reply", "originalText"),
@computed("reply", "originalText")
replyDirty(reply, originalText) {
return reply !== originalText;
},
/**
Did the user make changes to the topic title?
@ -417,9 +416,10 @@ const Composer = RestModel.extend({
@property missingTitleCharacters
**/
missingTitleCharacters: function() {
return this.get("minimumTitleLength") - this.get("titleLength");
}.property("minimumTitleLength", "titleLength"),
@computed("minimumTitleLength", "titleLength")
missingTitleCharacters(minimumTitleLength, titleLength) {
return minimumTitleLength - titleLength;
},
/**
Minimum number of characters for a title to be valid.
@ -474,23 +474,25 @@ const Composer = RestModel.extend({
@property titleLength
**/
titleLength: function() {
const title = this.get("title") || "";
@computed("title")
titleLength(title) {
title = title || "";
return title.replace(/\s+/gim, " ").trim().length;
}.property("title"),
},
/**
Computes the length of the reply minus the quote(s) and non-significant whitespaces
@property replyLength
**/
replyLength: function() {
let reply = this.get("reply") || "";
@computed("reply")
replyLength(reply) {
reply = reply || "";
while (Quote.REGEXP.test(reply)) {
reply = reply.replace(Quote.REGEXP, "");
}
return reply.replace(/\s+/gim, " ").trim().length;
}.property("reply"),
},
_setupComposer: function() {
this.set("archetypeId", this.site.get("default_archetype"));

View File

@ -1,8 +1,11 @@
import computed from "ember-addons/ember-computed-decorators";
const PermissionType = Discourse.Model.extend({
description: function() {
@computed("id")
description(id) {
var key = "";
switch (this.get("id")) {
switch (id) {
case 1:
key = "full";
break;
@ -14,7 +17,7 @@ const PermissionType = Discourse.Model.extend({
break;
}
return I18n.t("permission_types." + key);
}.property("id")
}
});
PermissionType.FULL = 1;

View File

@ -17,16 +17,17 @@ const Post = RestModel.extend({
return Discourse.SiteSettings;
},
shareUrl: function() {
@computed("url")
shareUrl(url) {
const user = Discourse.User.current();
const userSuffix = user ? "?u=" + user.get("username_lower") : "";
if (this.get("firstPost")) {
return this.get("topic.url") + userSuffix;
} else {
return this.get("url") + userSuffix;
return url + userSuffix;
}
}.property("url"),
},
new_user: Ember.computed.equal("trust_level", 0),
firstPost: Ember.computed.equal("post_number", 1),
@ -36,36 +37,31 @@ const Post = RestModel.extend({
deleted: Ember.computed.or("deleted_at", "deletedViaTopic"),
notDeleted: Ember.computed.not("deleted"),
showName: function() {
const name = this.get("name");
@computed("name", "username")
showName(name, username) {
return (
name &&
name !== this.get("username") &&
Discourse.SiteSettings.display_name_on_posts
name && name !== username && Discourse.SiteSettings.display_name_on_posts
);
}.property("name", "username"),
},
postDeletedBy: function() {
if (this.get("firstPost")) {
return this.get("topic.deleted_by");
}
return this.get("deleted_by");
}.property("firstPost", "deleted_by", "topic.deleted_by"),
@computed("firstPost", "deleted_by", "topic.deleted_by")
postDeletedBy(firstPost, deletedBy, topicDeletedBy) {
return firstPost ? topicDeletedBy : deletedBy;
},
postDeletedAt: function() {
if (this.get("firstPost")) {
return this.get("topic.deleted_at");
}
return this.get("deleted_at");
}.property("firstPost", "deleted_at", "topic.deleted_at"),
@computed("firstPost", "deleted_at", "topic.deleted_at")
postDeletedAt(firstPost, deletedAt, topicDeletedAt) {
return firstPost ? topicDeletedAt : deletedAt;
},
url: function() {
@computed("post_number", "topic_id", "topic.slug")
url(postNr, topicId, slug) {
return postUrl(
this.get("topic.slug") || this.get("topic_slug"),
this.get("topic_id") || this.get("topic.id"),
this.get("post_number")
slug || this.get("topic_slug"),
topicId || this.get("topic.id"),
postNr
);
}.property("post_number", "topic_id", "topic.slug"),
},
// Don't drop the /1
@computed("post_number", "url")

View File

@ -1,3 +1,5 @@
import computed from "ember-addons/ember-computed-decorators";
export default Ember.ArrayProxy.extend({
loading: false,
loadingMore: false,
@ -12,9 +14,10 @@ export default Ember.ArrayProxy.extend({
__type: null,
resultSetMeta: null,
canLoadMore: function() {
return this.get("length") < this.get("totalRows");
}.property("totalRows", "length"),
@computed("totalRows", "length")
canLoadMore(totalRows, length) {
return length < totalRows;
},
loadMore() {
const loadMoreUrl = this.get("loadMoreUrl");

View File

@ -1,4 +1,6 @@
import { ajax } from "discourse/lib/ajax";
import computed from "ember-addons/ember-computed-decorators";
/**
A model representing a Topic's details that aren't always present, such as a list of participants.
When showing topics in lists and such this information should not be required.
@ -29,15 +31,15 @@ const TopicDetails = RestModel.extend({
this.set("loaded", true);
},
notificationReasonText: function() {
let level = this.get("notification_level");
@computed("notification_level", "notifications_reason_id")
notificationReasonText(level, reason) {
if (typeof level !== "number") {
level = 1;
}
let localeString = `topic.notifications.reasons.${level}`;
if (typeof this.get("notifications_reason_id") === "number") {
const tmp = localeString + "_" + this.get("notifications_reason_id");
if (typeof reason === "number") {
const tmp = localeString + "_" + reason;
// some sane protection for missing translations of edge cases
if (I18n.lookup(tmp)) {
localeString = tmp;
@ -55,7 +57,7 @@ const TopicDetails = RestModel.extend({
basePath: Discourse.BaseUri
});
}
}.property("notification_level", "notifications_reason_id"),
},
updateNotifications(v) {
this.set("notification_level", v);

View File

@ -1,23 +1,24 @@
import RestModel from "discourse/models/rest";
import UserAction from "discourse/models/user-action";
import { i18n } from "discourse/lib/computed";
import computed from "ember-addons/ember-computed-decorators";
export default RestModel.extend({
isPM: function() {
const actionType = this.get("action_type");
@computed("action_type")
isPM(actionType) {
return (
actionType === UserAction.TYPES.messages_sent ||
actionType === UserAction.TYPES.messages_received
);
}.property("action_type"),
},
description: i18n("action_type", "user_action_groups.%@"),
isResponse: function() {
const actionType = this.get("action_type");
@computed("action_type")
isResponse(actionType) {
return (
actionType === UserAction.TYPES.replies ||
actionType === UserAction.TYPES.quotes
);
}.property("action_type")
}
});

View File

@ -164,16 +164,7 @@ const UserAction = RestModel.extend({
}
},
children: function() {
const g = this.get("childGroups");
let rval = [];
if (g) {
rval = [g.likes, g.stars, g.edits, g.bookmarks].filter(function(i) {
return i.get("items") && i.get("items").length > 0;
});
}
return rval;
}.property(
@computed(
"childGroups",
"childGroups.likes.items",
"childGroups.likes.items.[]",
@ -183,7 +174,17 @@ const UserAction = RestModel.extend({
"childGroups.edits.items.[]",
"childGroups.bookmarks.items",
"childGroups.bookmarks.items.[]"
),
)
children() {
const g = this.get("childGroups");
let rval = [];
if (g) {
rval = [g.likes, g.stars, g.edits, g.bookmarks].filter(function(i) {
return i.get("items") && i.get("items").length > 0;
});
}
return rval;
},
switchToActing() {
this.setProperties({

View File

@ -1,12 +1,14 @@
import { ajax } from "discourse/lib/ajax";
import Badge from "discourse/models/badge";
import computed from "ember-addons/ember-computed-decorators";
const UserBadge = Discourse.Model.extend({
@computed
postUrl: function() {
if (this.get("topic_title")) {
return "/t/-/" + this.get("topic_id") + "/" + this.get("post_number");
}
}.property(), // avoid the extra bindings for now
}, // avoid the extra bindings for now
revoke() {
return ajax("/user_badges/" + this.get("id"), {

View File

@ -3,6 +3,7 @@ import { url } from "discourse/lib/computed";
import RestModel from "discourse/models/rest";
import UserAction from "discourse/models/user-action";
import { emojiUnescape } from "discourse/lib/text";
import computed from "ember-addons/ember-computed-decorators";
export default RestModel.extend({
loaded: false,
@ -11,8 +12,8 @@ export default RestModel.extend({
this.setProperties({ itemsLoaded: 0, content: [] });
}.on("init"),
filterParam: function() {
const filter = this.get("filter");
@computed("filter")
filterParam(filter) {
if (filter === Discourse.UserAction.TYPES.replies) {
return [UserAction.TYPES.replies, UserAction.TYPES.quotes].join(",");
}
@ -22,7 +23,7 @@ export default RestModel.extend({
}
return filter;
}.property("filter"),
},
baseUrl: url(
"itemsLoaded",
@ -45,9 +46,10 @@ export default RestModel.extend({
return this.findItems();
},
noContent: function() {
@computed("loaded", "content.[]")
noContent() {
return this.get("loaded") && this.get("content").length === 0;
}.property("loaded", "content.[]"),
},
remove(userAction) {
// 1) remove the user action from the child groups

View File

@ -1,5 +1,8 @@
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Object.extend({
@computed
isLastVisited: function() {
return this.get("lastVisitedTopic") === this.get("topic");
}.property()
}
});

View File

@ -17,7 +17,7 @@
bulkSelectEnabled=bulkSelectEnabled
canBulkSelect=canBulkSelect
selected=selected
skipHeader=skipHeader
skipHeader=site.mobileView
tagsForUser=tagsForUser}}
{{else}}
{{#unless loadingMore}}

View File

@ -1,4 +1,4 @@
{{#unless skipHeader}}
{{#unless site.mobileView}}
<thead>
{{raw "topic-list-header"
canBulkSelect=canBulkSelect