DEV: reduces memory footprint of tests - step 1 (#7591)

This commit is contained in:
Joffrey JAFFEUX 2019-05-28 12:15:12 +02:00 committed by GitHub
parent 07b80d491b
commit 6decdfce5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 655 additions and 430 deletions

View File

@ -1,5 +1,10 @@
export default Ember.Controller.extend({
logs: [],
adminBackups: Ember.inject.controller(),
status: Ember.computed.alias("adminBackups.model")
status: Ember.computed.alias("adminBackups.model"),
init() {
this._super(...arguments);
this.logs = [];
}
});

View File

@ -1,6 +1,10 @@
export default Ember.Controller.extend({
titleSorting: ["title"],
emailTemplates: null,
sortedTemplates: Ember.computed.sort("emailTemplates", "titleSorting"),
sortedTemplates: Ember.computed.sort("emailTemplates", "titleSorting")
init() {
this._super(...arguments);
this.titleSorting = ["title"];
}
});

View File

@ -1,7 +1,12 @@
import { ajax } from "discourse/lib/ajax";
export default Ember.Controller.extend({
sortedEmojis: Ember.computed.sort("model", "emojiSorting"),
emojiSorting: ["name"],
init() {
this._super(...arguments);
this.emojiSorting = ["name"];
},
actions: {
emojiUploaded(emoji) {

View File

@ -6,10 +6,14 @@ import computed from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend({
loading: false,
filters: null,
userHistoryActions: [],
filtersExists: Ember.computed.gt("filterCount", 0),
init() {
this._super(...arguments);
this.userHistoryActions = [];
},
filterActionIdChanged: function() {
const filterActionId = this.filterActionId;
if (filterActionId) {

View File

@ -5,12 +5,19 @@ export default Ember.Controller.extend({
period: DEFAULT_PERIOD,
searchType: "all",
searchTypeOptions: [
{
id: "all",
name: I18n.t("admin.logs.search_logs.types.all_search_types")
},
{ id: "header", name: I18n.t("admin.logs.search_logs.types.header") },
{ id: "full_page", name: I18n.t("admin.logs.search_logs.types.full_page") }
]
init() {
this._super(...arguments);
this.searchTypeOptions = [
{
id: "all",
name: I18n.t("admin.logs.search_logs.types.all_search_types")
},
{ id: "header", name: I18n.t("admin.logs.search_logs.types.header") },
{
id: "full_page",
name: I18n.t("admin.logs.search_logs.types.full_page")
}
];
}
});

View File

@ -6,16 +6,23 @@ export default Ember.Controller.extend({
period: DEFAULT_PERIOD,
searchType: "all",
searchTypeOptions: [
{
id: "all",
name: I18n.t("admin.logs.search_logs.types.all_search_types")
},
{ id: "header", name: I18n.t("admin.logs.search_logs.types.header") },
{ id: "full_page", name: I18n.t("admin.logs.search_logs.types.full_page") },
{
id: "click_through_only",
name: I18n.t("admin.logs.search_logs.types.click_through_only")
}
]
init() {
this._super(...arguments);
this.searchTypeOptions = [
{
id: "all",
name: I18n.t("admin.logs.search_logs.types.all_search_types")
},
{ id: "header", name: I18n.t("admin.logs.search_logs.types.header") },
{
id: "full_page",
name: I18n.t("admin.logs.search_logs.types.full_page")
},
{
id: "click_through_only",
name: I18n.t("admin.logs.search_logs.types.click_through_only")
}
];
}
});

View File

@ -7,9 +7,13 @@ export default Ember.Controller.extend(GrantBadgeController, {
user: Ember.computed.alias("adminUser.model"),
userBadges: Ember.computed.alias("model"),
allBadges: Ember.computed.alias("badges"),
sortedBadges: Ember.computed.sort("model", "badgeSortOrder"),
badgeSortOrder: ["granted_at:desc"],
init() {
this._super(...arguments);
this.badgeSortOrder = ["granted_at:desc"];
},
@computed("model", "model.[]", "model.expandedBadges.[]")
groupedBadges() {

View File

@ -5,10 +5,14 @@ const MAX_FIELDS = 20;
export default Ember.Controller.extend({
fieldTypes: null,
createDisabled: Ember.computed.gte("model.length", MAX_FIELDS),
fieldSortOrder: ["position"],
sortedFields: Ember.computed.sort("model", "fieldSortOrder"),
init() {
this._super(...arguments);
this.fieldSortOrder = ["position"];
},
actions: {
createField() {
const f = this.store.createRecord("user-field", {

View File

@ -4,9 +4,14 @@ import computed from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend({
pingDisabled: false,
incomingEventIds: [],
incomingCount: Ember.computed.alias("incomingEventIds.length"),
init() {
this._super(...arguments);
this.incomingEventIds = [];
},
@computed("incomingCount")
hasIncoming(incomingCount) {
return incomingCount > 0;

View File

@ -121,13 +121,18 @@ export default Ember.Controller.extend(ModalFunctionality, {
urlPlaceholder: "https://github.com/discourse/sample_theme",
advancedVisible: false,
themesController: Ember.inject.controller("adminCustomizeThemes"),
createTypes: [
{ name: I18n.t("admin.customize.theme.theme"), value: THEMES },
{ name: I18n.t("admin.customize.theme.component"), value: COMPONENTS }
],
selectedType: Ember.computed.alias("themesController.currentTab"),
component: Ember.computed.equal("selectedType", COMPONENTS),
init() {
this._super(...arguments);
this.createTypes = [
{ name: I18n.t("admin.customize.theme.theme"), value: THEMES },
{ name: I18n.t("admin.customize.theme.component"), value: COMPONENTS }
];
},
@computed("themesController.installedThemes")
themes(installedThemes) {
return POPULAR_THEMES.map(t => {

View File

@ -3,10 +3,13 @@ import computed from "ember-addons/ember-computed-decorators";
export default Ember.Mixin.create({
queryParams: ["period"],
period: "monthly",
availablePeriods: ["yearly", "quarterly", "monthly", "weekly"],
init() {
this._super(...arguments);
this.availablePeriods = ["yearly", "quarterly", "monthly", "weekly"];
},
@computed("period")
startDate(period) {

View File

@ -6,13 +6,13 @@ import { escapeExpression } from "discourse/lib/utilities";
import highlightSyntax from "discourse/lib/highlight-syntax";
const THEME_UPLOAD_VAR = 2;
const FIELDS_IDS = [0, 1, 5];
export const THEMES = "themes";
export const COMPONENTS = "components";
const SETTINGS_TYPE_ID = 5;
const Theme = RestModel.extend({
FIELDS_IDS: [0, 1, 5],
isActive: Ember.computed.or("default", "user_selectable"),
isPendingUpdates: Ember.computed.gt("remote_theme.commits_behind", 0),
hasEditedFields: Ember.computed.gt("editedFields.length", 0),
@ -118,7 +118,7 @@ const Theme = RestModel.extend({
let hash = {};
fields.forEach(field => {
if (!field.type_id || this.FIELDS_IDS.includes(field.type_id)) {
if (!field.type_id || FIELDS_IDS.includes(field.type_id)) {
hash[this.getKey(field)] = field;
}
});

View File

@ -4,7 +4,12 @@ import Category from "discourse/models/category";
import computed from "ember-addons/ember-computed-decorators";
export default buildCategoryPanel("general", {
foregroundColors: ["FFFFFF", "000000"],
init() {
this._super(...arguments);
this.foregroundColors = ["FFFFFF", "000000"];
},
canSelectParentCategory: Ember.computed.not(
"category.isUncategorizedCategory"
),

View File

@ -7,7 +7,12 @@ export default DropdownSelectBoxComponent.extend({
showFullTitle: false,
allowInitialValueMutation: false,
allowAutoSelectFirst: false,
headerIcon: ["wrench"],
init() {
this._super(...arguments);
this.headerIcon = ["wrench"];
},
autoHighlight() {},

View File

@ -1,32 +1,42 @@
import { default as computed } from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({
visibilityLevelOptions: [
{
name: I18n.t("admin.groups.manage.interaction.visibility_levels.public"),
value: 0
},
{
name: I18n.t("admin.groups.manage.interaction.visibility_levels.members"),
value: 1
},
{
name: I18n.t("admin.groups.manage.interaction.visibility_levels.staff"),
value: 2
},
{
name: I18n.t("admin.groups.manage.interaction.visibility_levels.owners"),
value: 3
}
],
init() {
this._super(...arguments);
aliasLevelOptions: [
{ name: I18n.t("groups.alias_levels.nobody"), value: 0 },
{ name: I18n.t("groups.alias_levels.only_admins"), value: 1 },
{ name: I18n.t("groups.alias_levels.mods_and_admins"), value: 2 },
{ name: I18n.t("groups.alias_levels.members_mods_and_admins"), value: 3 },
{ name: I18n.t("groups.alias_levels.everyone"), value: 99 }
],
this.visibilityLevelOptions = [
{
name: I18n.t(
"admin.groups.manage.interaction.visibility_levels.public"
),
value: 0
},
{
name: I18n.t(
"admin.groups.manage.interaction.visibility_levels.members"
),
value: 1
},
{
name: I18n.t("admin.groups.manage.interaction.visibility_levels.staff"),
value: 2
},
{
name: I18n.t(
"admin.groups.manage.interaction.visibility_levels.owners"
),
value: 3
}
];
this.aliasLevelOptions = [
{ name: I18n.t("groups.alias_levels.nobody"), value: 0 },
{ name: I18n.t("groups.alias_levels.only_admins"), value: 1 },
{ name: I18n.t("groups.alias_levels.mods_and_admins"), value: 2 },
{ name: I18n.t("groups.alias_levels.members_mods_and_admins"), value: 3 },
{ name: I18n.t("groups.alias_levels.everyone"), value: 99 }
];
},
@computed("siteSettings.email_in", "model.automatic", "currentUser.admin")
showEmailSettings(emailIn, automatic, isAdmin) {

View File

@ -1,16 +1,20 @@
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({
trustLevelOptions: [
{
name: I18n.t("admin.groups.manage.membership.trust_levels_none"),
value: 0
},
{ name: 1, value: 1 },
{ name: 2, value: 2 },
{ name: 3, value: 3 },
{ name: 4, value: 4 }
],
init() {
this._super(...arguments);
this.trustLevelOptions = [
{
name: I18n.t("admin.groups.manage.membership.trust_levels_none"),
value: 0
},
{ name: 1, value: 1 },
{ name: 2, value: 2 },
{ name: 3, value: 3 },
{ name: 4, value: 4 }
];
},
@computed("model.visibility_level", "model.public_admission")
disableMembershipRequestSetting(visibility_level, publicAdmission) {

View File

@ -31,44 +31,47 @@ const IN_OPTIONS_MAPPING = { images: "with" };
export default Ember.Component.extend({
classNames: ["search-advanced-options"],
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.watching"), value: "watching" },
{ name: I18n.t("search.advanced.filters.tracking"), value: "tracking" },
{ name: I18n.t("search.advanced.filters.bookmarks"), value: "bookmarks" }
],
inOptionsForAll: [
{ name: I18n.t("search.advanced.filters.first"), value: "first" },
{ name: I18n.t("search.advanced.filters.pinned"), value: "pinned" },
{ name: I18n.t("search.advanced.filters.unpinned"), value: "unpinned" },
{ name: I18n.t("search.advanced.filters.wiki"), value: "wiki" },
{ name: I18n.t("search.advanced.filters.images"), value: "images" }
],
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.archived"), value: "archived" },
{ name: I18n.t("search.advanced.statuses.noreplies"), value: "noreplies" },
{
name: I18n.t("search.advanced.statuses.single_user"),
value: "single_user"
}
],
postTimeOptions: [
{ name: I18n.t("search.advanced.post.time.before"), value: "before" },
{ name: I18n.t("search.advanced.post.time.after"), value: "after" }
],
init() {
this._super(...arguments);
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.watching"), value: "watching" },
{ name: I18n.t("search.advanced.filters.tracking"), value: "tracking" },
{ name: I18n.t("search.advanced.filters.bookmarks"), value: "bookmarks" }
];
this.inOptionsForAll = [
{ name: I18n.t("search.advanced.filters.first"), value: "first" },
{ name: I18n.t("search.advanced.filters.pinned"), value: "pinned" },
{ name: I18n.t("search.advanced.filters.unpinned"), value: "unpinned" },
{ name: I18n.t("search.advanced.filters.wiki"), value: "wiki" },
{ name: I18n.t("search.advanced.filters.images"), value: "images" }
];
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.archived"), value: "archived" },
{
name: I18n.t("search.advanced.statuses.noreplies"),
value: "noreplies"
},
{
name: I18n.t("search.advanced.statuses.single_user"),
value: "single_user"
}
];
this.postTimeOptions = [
{ name: I18n.t("search.advanced.post.time.before"), value: "before" },
{ name: I18n.t("search.advanced.post.time.after"), value: "after" }
];
this._init();
Ember.run.scheduleOnce("afterRender", () => {
this._update();
});
Ember.run.scheduleOnce("afterRender", () => this._update());
},
@observes("searchTerm")

View File

@ -88,69 +88,92 @@ export default Ember.Component.extend({
Ember.run.scheduleOnce("afterRender", this, this._focusUrl);
},
_mouseDownHandler(event) {
if (!this.element || this.isDestroying || this.isDestroyed) {
return;
}
// Use mousedown instead of click so this event is handled before routing occurs when a
// link is clicked (which is a click event) while the share dialog is showing.
if ($(this.element).has(event.target).length !== 0) {
return;
}
this.send("close");
return true;
},
_clickHandler(event) {
if (!this.element || this.isDestroying || this.isDestroyed) {
return;
}
// if they want to open in a new tab, let it so
if (wantsNewWindow(event)) {
return true;
}
event.preventDefault();
const $currentTarget = $(event.currentTarget);
const url = $currentTarget.data("share-url");
const postNumber = $currentTarget.data("post-number");
const postId = $currentTarget.closest("article").data("post-id");
const date = $currentTarget.children().data("time");
this.setProperties({ postNumber, date, postId });
// use native webshare only when the user clicks on the "chain" icon
if (!$currentTarget.hasClass("post-date")) {
nativeShare({ url }).then(null, () => this._showUrl($currentTarget, url));
} else {
this._showUrl($currentTarget, url);
}
return false;
},
_keydownHandler(event) {
if (!this.element || this.isDestroying || this.isDestroyed) {
return;
}
if (event.keyCode === 27) {
this.send("close");
}
},
_shareUrlHandler(url, $target) {
this._showUrl($target, url);
},
didInsertElement() {
this._super(...arguments);
const $html = $("html");
$html.on("mousedown.outside-share-link", e => {
// Use mousedown instead of click so this event is handled before routing occurs when a
// link is clicked (which is a click event) while the share dialog is showing.
if (this.$().has(e.target).length !== 0) {
return;
}
this.send("close");
return true;
});
$html.on("mousedown.outside-share-link", this._mouseDownHandler.bind(this));
$html.on(
"click.discourse-share-link",
"button[data-share-url], .post-info .post-date[data-share-url]",
e => {
// if they want to open in a new tab, let it so
if (wantsNewWindow(e)) {
return true;
}
e.preventDefault();
const $currentTarget = $(e.currentTarget);
const url = $currentTarget.data("share-url");
const postNumber = $currentTarget.data("post-number");
const postId = $currentTarget.closest("article").data("post-id");
const date = $currentTarget.children().data("time");
this.setProperties({ postNumber, date, postId });
// use native webshare only when the user clicks on the "chain" icon
if (!$currentTarget.hasClass("post-date")) {
nativeShare({ url }).then(null, () =>
this._showUrl($currentTarget, url)
);
} else {
this._showUrl($currentTarget, url);
}
return false;
}
this._clickHandler.bind(this)
);
$html.on("keydown.share-view", e => {
if (e.keyCode === 27) {
this.send("close");
}
});
$html.on("keydown.share-view", this._keydownHandler);
this.appEvents.on("share:url", (url, $target) =>
this._showUrl($target, url)
);
this.appEvents.on("share:url", this._shareUrlHandler);
},
willDestroyElement() {
this._super(...arguments);
$("html")
.off("click.discourse-share-link")
.off("mousedown.outside-share-link")
.off("keydown.share-view");
.off("click.discourse-share-link", this._clickHandler)
.off("mousedown.outside-share-link", this._mouseDownHandler)
.off("keydown.share-view", this._keydownHandler);
this.appEvents.off("share:url", this._shareUrlHandler);
},
actions: {

View File

@ -5,9 +5,14 @@ export default DropdownSelectBoxComponent.extend({
classNames: "tags-admin-dropdown",
showFullTitle: false,
allowInitialValueMutation: false,
headerIcon: ["bars", "caret-down"],
actionsMapping: null,
init() {
this._super(...arguments);
this.headerIcon = ["bars", "caret-down"];
},
autoHighlight() {},
computeContent() {

View File

@ -13,8 +13,13 @@ export default Ember.Controller.extend(
loading: true,
saving: false,
selectedBadgeId: null,
allBadges: [],
userBadges: [],
init() {
this._super(...arguments);
this.allBadges = [];
this.userBadges = [];
},
@computed("topicController.selectedPosts")
post() {

View File

@ -16,9 +16,19 @@ export default Ember.Controller.extend(ModalFunctionality, {
existingTopic: Ember.computed.equal("selection", "existing_topic"),
newMessage: Ember.computed.equal("selection", "new_message"),
existingMessage: Ember.computed.equal("selection", "existing_message"),
moveTypes: ["newTopic", "existingTopic", "newMessage", "existingMessage"],
participants: null,
init() {
this._super(...arguments);
this.saveAttrNames = [
"newTopic",
"existingTopic",
"newMessage",
"existingMessage"
];
},
topicController: Ember.inject.controller("topic"),
selectedPostsCount: Ember.computed.alias(
"topicController.selectedPostsCount"

View File

@ -16,7 +16,11 @@ export default Ember.Controller.extend(
CanCheckEmails,
PreferencesTabController,
{
saveAttrNames: ["name", "title"],
init() {
this._super(...arguments);
this.saveAttrNames = ["name", "title"];
},
canEditName: setting("enable_names"),
canSaveUser: true,

View File

@ -3,12 +3,16 @@ import { popupAjaxError } from "discourse/lib/ajax-error";
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend(PreferencesTabController, {
saveAttrNames: [
"muted_category_ids",
"watched_category_ids",
"tracked_category_ids",
"watched_first_post_category_ids"
],
init() {
this._super(...arguments);
this.saveAttrNames = [
"muted_category_ids",
"watched_category_ids",
"tracked_category_ids",
"watched_first_post_category_ids"
];
},
@computed(
"model.watchedCategories",

View File

@ -18,17 +18,45 @@ export default Ember.Controller.extend(PreferencesTabController, {
EMAIL_LEVELS.ONLY_WHEN_AWAY
),
saveAttrNames: [
"email_level",
"email_messages_level",
"mailing_list_mode",
"mailing_list_mode_frequency",
"email_digests",
"email_in_reply_to",
"email_previous_replies",
"digest_after_minutes",
"include_tl0_in_digests"
],
init() {
this._super(...arguments);
this.saveAttrNames = [
"email_level",
"email_messages_level",
"mailing_list_mode",
"mailing_list_mode_frequency",
"email_digests",
"email_in_reply_to",
"email_previous_replies",
"digest_after_minutes",
"include_tl0_in_digests"
];
this.previousRepliesOptions = [
{ name: I18n.t("user.email_previous_replies.always"), value: 0 },
{ name: I18n.t("user.email_previous_replies.unless_emailed"), value: 1 },
{ name: I18n.t("user.email_previous_replies.never"), value: 2 }
];
this.emailLevelOptions = [
{ name: I18n.t("user.email_level.always"), value: EMAIL_LEVELS.ALWAYS },
{
name: I18n.t("user.email_level.only_when_away"),
value: EMAIL_LEVELS.ONLY_WHEN_AWAY
},
{ name: I18n.t("user.email_level.never"), value: EMAIL_LEVELS.NEVER }
];
this.digestFrequencies = [
{ name: I18n.t("user.email_digests.every_30_minutes"), value: 30 },
{ name: I18n.t("user.email_digests.every_hour"), value: 60 },
{ name: I18n.t("user.email_digests.daily"), value: 1440 },
{ name: I18n.t("user.email_digests.weekly"), value: 10080 },
{ name: I18n.t("user.email_digests.every_month"), value: 43200 },
{ name: I18n.t("user.email_digests.every_six_months"), value: 259200 }
];
},
@computed()
frequencyEstimate() {
@ -50,30 +78,6 @@ export default Ember.Controller.extend(PreferencesTabController, {
];
},
previousRepliesOptions: [
{ name: I18n.t("user.email_previous_replies.always"), value: 0 },
{ name: I18n.t("user.email_previous_replies.unless_emailed"), value: 1 },
{ name: I18n.t("user.email_previous_replies.never"), value: 2 }
],
emailLevelOptions: [
{ name: I18n.t("user.email_level.always"), value: EMAIL_LEVELS.ALWAYS },
{
name: I18n.t("user.email_level.only_when_away"),
value: EMAIL_LEVELS.ONLY_WHEN_AWAY
},
{ name: I18n.t("user.email_level.never"), value: EMAIL_LEVELS.NEVER }
],
digestFrequencies: [
{ name: I18n.t("user.email_digests.every_30_minutes"), value: 30 },
{ name: I18n.t("user.email_digests.every_hour"), value: 60 },
{ name: I18n.t("user.email_digests.daily"), value: 1440 },
{ name: I18n.t("user.email_digests.weekly"), value: 10080 },
{ name: I18n.t("user.email_digests.every_month"), value: 43200 },
{ name: I18n.t("user.email_digests.every_six_months"), value: 259200 }
],
@computed()
emailFrequencyInstructions() {
if (this.siteSettings.email_time_window_mins) {

View File

@ -3,67 +3,89 @@ import { NotificationLevels } from "discourse/lib/notification-levels";
import { popupAjaxError } from "discourse/lib/ajax-error";
export default Ember.Controller.extend(PreferencesTabController, {
saveAttrNames: [
"muted_usernames",
"ignored_usernames",
"new_topic_duration_minutes",
"auto_track_topics_after_msecs",
"notification_level_when_replying",
"like_notification_frequency",
"allow_private_messages"
],
init() {
this._super(...arguments);
likeNotificationFrequencies: [
{ name: I18n.t("user.like_notification_frequency.always"), value: 0 },
{
name: I18n.t("user.like_notification_frequency.first_time_and_daily"),
value: 1
},
{ name: I18n.t("user.like_notification_frequency.first_time"), value: 2 },
{ name: I18n.t("user.like_notification_frequency.never"), value: 3 }
],
this.saveAttrNames = [
"muted_usernames",
"ignored_usernames",
"new_topic_duration_minutes",
"auto_track_topics_after_msecs",
"notification_level_when_replying",
"like_notification_frequency",
"allow_private_messages"
];
autoTrackDurations: [
{ name: I18n.t("user.auto_track_options.never"), value: -1 },
{ name: I18n.t("user.auto_track_options.immediately"), value: 0 },
{ name: I18n.t("user.auto_track_options.after_30_seconds"), value: 30000 },
{ name: I18n.t("user.auto_track_options.after_1_minute"), value: 60000 },
{ name: I18n.t("user.auto_track_options.after_2_minutes"), value: 120000 },
{ name: I18n.t("user.auto_track_options.after_3_minutes"), value: 180000 },
{ name: I18n.t("user.auto_track_options.after_4_minutes"), value: 240000 },
{ name: I18n.t("user.auto_track_options.after_5_minutes"), value: 300000 },
{ name: I18n.t("user.auto_track_options.after_10_minutes"), value: 600000 }
],
this.likeNotificationFrequencies = [
{ name: I18n.t("user.like_notification_frequency.always"), value: 0 },
{
name: I18n.t("user.like_notification_frequency.first_time_and_daily"),
value: 1
},
{ name: I18n.t("user.like_notification_frequency.first_time"), value: 2 },
{ name: I18n.t("user.like_notification_frequency.never"), value: 3 }
];
notificationLevelsForReplying: [
{
name: I18n.t("topic.notifications.watching.title"),
value: NotificationLevels.WATCHING
},
{
name: I18n.t("topic.notifications.tracking.title"),
value: NotificationLevels.TRACKING
},
{
name: I18n.t("topic.notifications.regular.title"),
value: NotificationLevels.REGULAR
}
],
this.autoTrackDurations = [
{ name: I18n.t("user.auto_track_options.never"), value: -1 },
{ name: I18n.t("user.auto_track_options.immediately"), value: 0 },
{
name: I18n.t("user.auto_track_options.after_30_seconds"),
value: 30000
},
{ name: I18n.t("user.auto_track_options.after_1_minute"), value: 60000 },
{
name: I18n.t("user.auto_track_options.after_2_minutes"),
value: 120000
},
{
name: I18n.t("user.auto_track_options.after_3_minutes"),
value: 180000
},
{
name: I18n.t("user.auto_track_options.after_4_minutes"),
value: 240000
},
{
name: I18n.t("user.auto_track_options.after_5_minutes"),
value: 300000
},
{
name: I18n.t("user.auto_track_options.after_10_minutes"),
value: 600000
}
];
considerNewTopicOptions: [
{ name: I18n.t("user.new_topic_duration.not_viewed"), value: -1 },
{ name: I18n.t("user.new_topic_duration.after_1_day"), value: 60 * 24 },
{ name: I18n.t("user.new_topic_duration.after_2_days"), value: 60 * 48 },
{
name: I18n.t("user.new_topic_duration.after_1_week"),
value: 7 * 60 * 24
},
{
name: I18n.t("user.new_topic_duration.after_2_weeks"),
value: 2 * 7 * 60 * 24
},
{ name: I18n.t("user.new_topic_duration.last_here"), value: -2 }
],
this.notificationLevelsForReplying = [
{
name: I18n.t("topic.notifications.watching.title"),
value: NotificationLevels.WATCHING
},
{
name: I18n.t("topic.notifications.tracking.title"),
value: NotificationLevels.TRACKING
},
{
name: I18n.t("topic.notifications.regular.title"),
value: NotificationLevels.REGULAR
}
];
this.considerNewTopicOptions = [
{ name: I18n.t("user.new_topic_duration.not_viewed"), value: -1 },
{ name: I18n.t("user.new_topic_duration.after_1_day"), value: 60 * 24 },
{ name: I18n.t("user.new_topic_duration.after_2_days"), value: 60 * 48 },
{
name: I18n.t("user.new_topic_duration.after_1_week"),
value: 7 * 60 * 24
},
{
name: I18n.t("user.new_topic_duration.after_2_weeks"),
value: 2 * 7 * 60 * 24
},
{ name: I18n.t("user.new_topic_duration.last_here"), value: -2 }
];
},
actions: {
save() {

View File

@ -4,16 +4,20 @@ import { popupAjaxError } from "discourse/lib/ajax-error";
import { cookAsync } from "discourse/lib/text";
export default Ember.Controller.extend(PreferencesTabController, {
saveAttrNames: [
"bio_raw",
"website",
"location",
"custom_fields",
"user_fields",
"profile_background_upload_url",
"card_background_upload_url",
"date_of_birth"
],
init() {
this._super(...arguments);
this.saveAttrNames = [
"bio_raw",
"website",
"location",
"custom_fields",
"user_fields",
"profile_background_upload_url",
"card_background_upload_url",
"date_of_birth"
];
},
@computed("model.user_fields.@each.value")
userFields() {

View File

@ -3,12 +3,16 @@ import { popupAjaxError } from "discourse/lib/ajax-error";
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend(PreferencesTabController, {
saveAttrNames: [
"muted_tags",
"tracked_tags",
"watched_tags",
"watching_first_post_tags"
],
init() {
this._super(...arguments);
this.saveAttrNames = [
"muted_tags",
"tracked_tags",
"watched_tags",
"watching_first_post_tags"
];
},
@computed(
"model.watched_tags.[]",

View File

@ -4,10 +4,16 @@ import showModal from "discourse/lib/show-modal";
import User from "discourse/models/user";
export default Ember.Controller.extend(PreferencesTabController, {
saveAttrNames: ["muted_usernames", "ignored_usernames"],
ignoredUsernames: Ember.computed.alias("model.ignored_usernames"),
userIsMemberOrAbove: Ember.computed.gte("model.trust_level", 2),
ignoredEnabled: Ember.computed.or("userIsMemberOrAbove", "model.staff"),
init() {
this._super(...arguments);
this.saveAttrNames = ["muted_usernames", "ignored_usernames"];
},
actions: {
ignoredUsernamesChanged(previous, current) {
if (current.length > previous.length) {

View File

@ -9,6 +9,12 @@ import {
import Ember from "ember";
export default Ember.Controller.extend(ModalFunctionality, Ember.Evented, {
init() {
this._super(...arguments);
this.categoriesSorting = ["position"];
},
@on("init")
_fixOrder() {
this.fixIndices();
@ -20,7 +26,6 @@ export default Ember.Controller.extend(ModalFunctionality, Ember.Evented, {
return categories.map(c => bufProxy.create({ content: c }));
},
categoriesSorting: ["position"],
categoriesOrdered: Ember.computed.sort(
"categoriesBuffered",
"categoriesSorting"

View File

@ -4,7 +4,6 @@ import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
export default Ember.Controller.extend({
sortProperties: ["totalCount:desc", "id"],
sortedByCount: true,
sortedByName: false,
@ -12,6 +11,12 @@ export default Ember.Controller.extend({
groupedByCategory: Ember.computed.notEmpty("model.extras.categories"),
groupedByTagGroup: Ember.computed.notEmpty("model.extras.tag_groups"),
init() {
this._super(...arguments);
this.sortProperties = ["totalCount:desc", "id"];
},
@computed("groupedByCategory", "groupedByTagGroup")
otherTagsTitleKey(groupedByCategory, groupedByTagGroup) {
if (!groupedByCategory && !groupedByTagGroup) {

View File

@ -2,5 +2,10 @@ export default Ember.Controller.extend({
user: Ember.inject.controller(),
username: Ember.computed.alias("user.model.username_lower"),
sortedBadges: Ember.computed.sort("model", "badgeSortOrder"),
badgeSortOrder: ["badge.badge_type.sort_order", "badge.name"]
init() {
this._super(...arguments);
this.badgeSortOrder = ["badge.badge_type.sort_order", "badge.name"];
}
});

View File

@ -6,11 +6,16 @@ export default Ember.Controller.extend({
hideCategory: false,
showPosters: false,
newIncoming: [],
incomingCount: 0,
channel: null,
tagsForUser: null,
init() {
this._super(...arguments);
this.newIncoming = [];
},
_showFooter: function() {
this.set("application.showFooter", !this.get("model.canLoadMore"));
}.observes("model.canLoadMore"),

View File

@ -1,11 +1,10 @@
import { ajax } from "discourse/lib/ajax";
// We use this class to track how long posts in a topic are on the screen.
const PAUSE_UNLESS_SCROLLED = 1000 * 60 * 3;
const MAX_TRACKING_TIME = 1000 * 60 * 6;
const ANON_MAX_TOPIC_IDS = 5;
const getTime = () => new Date().getTime();
export default class {
constructor(topicTrackingState, siteSettings, session, currentUser) {
this.topicTrackingState = topicTrackingState;
@ -27,7 +26,7 @@ export default class {
// Create an interval timer if we don't have one.
if (!this._interval) {
this._interval = setInterval(() => this.tick(), 1000);
$(window).on("scroll.screentrack", () => this.scrolled());
$(window).on("scroll.screentrack", this.scrolled.bind(this));
}
this._topicId = topicId;
@ -40,7 +39,7 @@ export default class {
return;
}
$(window).off("scroll.screentrack");
$(window).off("scroll.screentrack", this.scrolled);
this.tick();
this.flush();
this.reset();
@ -61,7 +60,7 @@ export default class {
// Reset our timers
reset() {
const now = getTime();
const now = this._getTime();
this._lastTick = now;
this._lastScrolled = now;
this._lastFlush = 0;
@ -75,7 +74,7 @@ export default class {
}
scrolled() {
this._lastScrolled = getTime();
this._lastScrolled = this._getTime();
}
registerAnonCallback(cb) {
@ -225,4 +224,8 @@ export default class {
});
}
}
_getTime() {
return (this._time = this._time || new Date().getTime());
}
}

View File

@ -14,7 +14,12 @@ const Group = RestModel.extend({
limit: 50,
offset: 0,
user_count: 0,
owners: [],
init() {
this._super(...arguments);
this.owners = [];
},
hasOwners: Ember.computed.notEmpty("owners"),

View File

@ -8,6 +8,12 @@ import PreloadStore from "preload-store";
const Site = RestModel.extend({
isReadOnly: Ember.computed.alias("is_readonly"),
init() {
this._super(...arguments);
this.topicCountDesc = ["topic_count:desc"];
},
@computed("notification_types")
notificationLookup(notificationTypes) {
const result = [];
@ -24,7 +30,6 @@ const Site = RestModel.extend({
return postActionTypes.filterBy("is_flag", true);
},
topicCountDesc: ["topic_count:desc"],
categoriesByCount: Ember.computed.sort("categories", "topicCountDesc"),
collectUserFields(fields) {

View File

@ -5,7 +5,12 @@ export default DropdownSelectBoxComponent.extend({
classNames: "categories-admin-dropdown",
showFullTitle: false,
allowInitialValueMutation: false,
headerIcon: ["bars"],
init() {
this._super(...arguments);
this.headerIcon = ["bars"];
},
autoHighlight() {},

View File

@ -2,9 +2,15 @@ import DropdownSelectBoxComponent from "select-kit/components/dropdown-select-bo
export default DropdownSelectBoxComponent.extend({
classNames: "group-members-dropdown",
headerIcon: ["bars"],
showFullTitle: false,
allowInitialValueMutation: false,
init() {
this._super(...arguments);
this.headerIcon = ["bars"];
},
autoHighlight() {},
computeContent() {

View File

@ -18,137 +18,149 @@ export default Ember.Mixin.create({
willDestroyElement() {
this._super(...arguments);
$(document).off("mousedown.select-kit");
$(document).off("mousedown.select-kit", this._mouseDownHandler);
if (this.$header().length) {
this.$header()
.off("blur.select-kit")
.off("focus.select-kit")
.off("keypress.select-kit")
.off("keydown.select-kit");
.off("blur.select-kit", this._blurHeaderHandler)
.off("focus.select-kit", this._focusHeaderHandler)
.off("keydown.select-kit", this._keydownHeaderHandler)
.off("keypress.select-kit", this._keypressHeaderHandler);
}
if (this.$filterInput().length) {
this.$filterInput()
.off("change.select-kit")
.off("keydown.select-kit")
.off("keypress.select-kit")
.off("focusout.select-kit");
.off("change.select-kit", this._changeFilterInputHandler)
.off("keydown.select-kit", this._keydownFilterInputHandler)
.off("keypress.select-kit", this._keypressFilterInputHandler)
.off("focusout.select-kit", this._focusoutFilterInputHandler);
}
},
_mouseDownHandler(event) {
if (!this.element || this.isDestroying || this.isDestroyed) {
return true;
}
if (Ember.$.contains(this.element, event.target)) {
event.stopPropagation();
if (!this.renderedBodyOnce) return;
if (!this.isFocused) return;
} else {
this.didClickOutside(event);
}
},
_blurHeaderHandler() {
if (!this.isExpanded && this.isFocused) {
this.close();
}
},
_focusHeaderHandler(event) {
this.set("isFocused", true);
this._destroyEvent(event);
},
_keydownHeaderHandler(event) {
if (document.activeElement !== this.$header()[0]) return event;
const keyCode = event.keyCode || event.which;
if (keyCode === this.keys.TAB && event.shiftKey) {
this.unfocus(event);
}
if (keyCode === this.keys.TAB && !event.shiftKey) this.tabFromHeader(event);
if (Ember.isEmpty(this.filter) && keyCode === this.keys.BACKSPACE)
this.backspaceFromHeader(event);
if (keyCode === this.keys.ESC) this.escapeFromHeader(event);
if (keyCode === this.keys.ENTER) this.enterFromHeader(event);
if ([this.keys.UP, this.keys.DOWN].includes(keyCode))
this.upAndDownFromHeader(event);
if (
Ember.isEmpty(this.filter) &&
[this.keys.LEFT, this.keys.RIGHT].includes(keyCode)
) {
this.leftAndRightFromHeader(event);
}
return event;
},
_keypressHeaderHandler(event) {
const keyCode = event.keyCode || event.which;
if (keyCode === this.keys.ENTER) return true;
if (keyCode === this.keys.TAB) return true;
this.expand(event);
if (this.filterable || this.autoFilterable) {
this.set("renderedFilterOnce", true);
}
Ember.run.schedule("afterRender", () => {
this.$filterInput()
.focus()
.val(this.$filterInput().val() + String.fromCharCode(keyCode));
});
return false;
},
_keydownFilterInputHandler(event) {
const keyCode = event.keyCode || event.which;
if (
Ember.isEmpty(this.filter) &&
keyCode === this.keys.BACKSPACE &&
typeof this.didPressBackspaceFromFilter === "function"
) {
this.didPressBackspaceFromFilter(event);
}
if (keyCode === this.keys.TAB && event.shiftKey) {
this.unfocus(event);
}
if (keyCode === this.keys.TAB && !event.shiftKey) this.tabFromFilter(event);
if (keyCode === this.keys.ESC) this.escapeFromFilter(event);
if (keyCode === this.keys.ENTER) this.enterFromFilter(event);
if ([this.keys.UP, this.keys.DOWN].includes(keyCode))
this.upAndDownFromFilter(event);
if (
Ember.isEmpty(this.filter) &&
[this.keys.LEFT, this.keys.RIGHT].includes(keyCode)
) {
this.leftAndRightFromFilter(event);
}
},
_changeFilterInputHandler(event) {
this.send("onFilterComputedContent", $(event.target).val());
},
_keypressFilterInputHandler(event) {
event.stopPropagation();
},
_focusoutFilterInputHandler(event) {
this.onFilterInputFocusout(event);
},
didInsertElement() {
this._super(...arguments);
$(document).on("mousedown.select-kit", event => {
if (!this.element || this.isDestroying || this.isDestroyed) {
return true;
}
if (Ember.$.contains(this.element, event.target)) {
event.stopPropagation();
if (!this.renderedBodyOnce) return;
if (!this.isFocused) return;
} else {
this.didClickOutside(event);
}
return true;
});
$(document).on("mousedown.select-kit", this._mouseDownHandler);
this.$header()
.on("blur.select-kit", () => {
if (!this.isExpanded && this.isFocused) {
this.close();
}
})
.on("focus.select-kit", event => {
this.set("isFocused", true);
this._destroyEvent(event);
})
.on("keydown.select-kit", event => {
if (document.activeElement !== this.$header()[0]) return event;
const keyCode = event.keyCode || event.which;
if (keyCode === this.keys.TAB && event.shiftKey) {
this.unfocus(event);
}
if (keyCode === this.keys.TAB && !event.shiftKey)
this.tabFromHeader(event);
if (Ember.isEmpty(this.filter) && keyCode === this.keys.BACKSPACE)
this.backspaceFromHeader(event);
if (keyCode === this.keys.ESC) this.escapeFromHeader(event);
if (keyCode === this.keys.ENTER) this.enterFromHeader(event);
if ([this.keys.UP, this.keys.DOWN].includes(keyCode))
this.upAndDownFromHeader(event);
if (
Ember.isEmpty(this.filter) &&
[this.keys.LEFT, this.keys.RIGHT].includes(keyCode)
) {
this.leftAndRightFromHeader(event);
}
return event;
})
.on("keypress.select-kit", event => {
const keyCode = event.keyCode || event.which;
if (keyCode === this.keys.ENTER) return true;
if (keyCode === this.keys.TAB) return true;
this.expand(event);
if (this.filterable || this.autoFilterable) {
this.set("renderedFilterOnce", true);
}
Ember.run.schedule("afterRender", () => {
this.$filterInput()
.focus()
.val(this.$filterInput().val() + String.fromCharCode(keyCode));
});
return false;
});
.on("blur.select-kit", this._blurHeaderHandler.bind(this))
.on("focus.select-kit", this._focusHeaderHandler.bind(this))
.on("keydown.select-kit", this._keydownHeaderHandler.bind(this))
.on("keypress.select-kit", this._keypressHeaderHandler);
this.$filterInput()
.on("change.select-kit", event => {
this.send("onFilterComputedContent", $(event.target).val());
})
.on("keypress.select-kit", event => {
event.stopPropagation();
})
.on("focusout.select-kit", event => {
this.onFilterInputFocusout(event);
})
.on("keydown.select-kit", event => {
const keyCode = event.keyCode || event.which;
if (
Ember.isEmpty(this.filter) &&
keyCode === this.keys.BACKSPACE &&
typeof this.didPressBackspaceFromFilter === "function"
) {
this.didPressBackspaceFromFilter(event);
}
if (keyCode === this.keys.TAB && event.shiftKey) {
this.unfocus(event);
}
if (keyCode === this.keys.TAB && !event.shiftKey)
this.tabFromFilter(event);
if (keyCode === this.keys.ESC) this.escapeFromFilter(event);
if (keyCode === this.keys.ENTER) this.enterFromFilter(event);
if ([this.keys.UP, this.keys.DOWN].includes(keyCode))
this.upAndDownFromFilter(event);
if (
Ember.isEmpty(this.filter) &&
[this.keys.LEFT, this.keys.RIGHT].includes(keyCode)
) {
this.leftAndRightFromFilter(event);
}
});
.on("change.select-kit", this._changeFilterInputHandler.bind(this))
.on("keypress.select-kit", this._keypressFilterInputHandler)
.on("focusout.select-kit", this._focusoutFilterInputHandler.bind(this))
.on("keydown.select-kit", this._keydownFilterInputHandler.bind(this));
},
didPressTab(event) {

View File

@ -64,6 +64,7 @@ QUnit.module("lib:keyboard-shortcuts", {
afterEach() {
$("#qunit-scratch").html("");
testMouseTrap = undefined;
}
});

View File

@ -65,8 +65,6 @@ d.write(
"<style>#ember-testing-container { position: absolute; background: white; bottom: 0; right: 0; width: 640px; height: 384px; overflow: auto; z-index: 9999; border: 1px solid #ccc; } #ember-testing { zoom: 50%; }</style>"
);
Ember.Test.adapter = window.QUnitAdapter.create();
Discourse.rootElement = "#ember-testing";
Discourse.setupForTesting();
Discourse.injectTestHelpers();

View File

@ -2,28 +2,27 @@
// except for the little snippet from StackOverflow
//
// http://stackoverflow.com/questions/263743/how-to-get-caret-position-in-textarea
var clone, getCaret;
getCaret = function(el) {
var r, rc, re;
if (el.selectionStart) {
return el.selectionStart;
} else if (document.selection) {
el.focus();
r = document.selection.createRange();
if (!r) return 0;
re = el.createTextRange();
rc = re.duplicate();
re.moveToBookmark(r.getBookmark());
rc.setEndPoint("EndToStart", re);
return rc.text.length;
}
return 0;
};
var clone = null;
clone = null;
$.fn.caret = function(elem) {
var getCaret = function(el) {
var r, rc, re;
if (el.selectionStart) {
return el.selectionStart;
} else if (document.selection) {
el.focus();
r = document.selection.createRange();
if (!r) return 0;
re = el.createTextRange();
rc = re.duplicate();
re.moveToBookmark(r.getBookmark());
rc.setEndPoint("EndToStart", re);
return rc.text.length;
}
return 0;
};
$.fn.caret = function() {
return getCaret(this[0]);
return getCaret(elem || this[0]);
};
/**
@ -99,7 +98,7 @@ $.fn.caretPosition = function(options) {
pos =
options && (options.pos || options.pos === 0)
? options.pos
: getCaret(textarea[0]);
: $.caret(textarea[0]);
val = textarea.val().replace("\r", "");
if (options && options.key) {