2
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2025-09-06 10:50:21 +08:00

DEV: introduces prettier for es6 files

This commit is contained in:
Joffrey JAFFEUX 2018-06-15 17:03:24 +02:00 committed by GitHub
parent c7ee70941e
commit 03a7d532cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
1162 changed files with 60667 additions and 29659 deletions

View file

@ -1,9 +1,11 @@
import RestAdapter from 'discourse/adapters/rest'; import RestAdapter from "discourse/adapters/rest";
export default function buildPluginAdapter(pluginName) { export default function buildPluginAdapter(pluginName) {
return RestAdapter.extend({ return RestAdapter.extend({
pathFor(store, type, findArgs) { pathFor(store, type, findArgs) {
return "/admin/plugins/" + pluginName + this._super(store, type, findArgs); return (
"/admin/plugins/" + pluginName + this._super(store, type, findArgs)
);
} }
}); });
} }

View file

@ -1,4 +1,4 @@
import RestAdapter from 'discourse/adapters/rest'; import RestAdapter from "discourse/adapters/rest";
export default RestAdapter.extend({ export default RestAdapter.extend({
basePath() { basePath() {

View file

@ -1,4 +1,4 @@
import RestAdapter from 'discourse/adapters/rest'; import RestAdapter from "discourse/adapters/rest";
export default RestAdapter.extend({ export default RestAdapter.extend({
pathFor() { pathFor() {

View file

@ -1,4 +1,4 @@
import RestAdapter from 'discourse/adapters/rest'; import RestAdapter from "discourse/adapters/rest";
export default RestAdapter.extend({ export default RestAdapter.extend({
pathFor(store, type, findArgs) { pathFor(store, type, findArgs) {
@ -17,20 +17,20 @@ export default RestAdapter.extend({
hasMore: pa.conversation.has_more, hasMore: pa.conversation.has_more,
response: { response: {
excerpt: pa.conversation.response.excerpt, excerpt: pa.conversation.response.excerpt,
user: helper.lookup('user', pa.conversation.response.user_id) user: helper.lookup("user", pa.conversation.response.user_id)
} }
}; };
if (pa.conversation.reply) { if (pa.conversation.reply) {
conversation.reply = { conversation.reply = {
excerpt: pa.conversation.reply.excerpt, excerpt: pa.conversation.reply.excerpt,
user: helper.lookup('user', pa.conversation.reply.user_id) user: helper.lookup("user", pa.conversation.reply.user_id)
}; };
} }
conversations.push(conversation); conversations.push(conversation);
} }
}); });
flag.set('conversations', conversations); flag.set("conversations", conversations);
}); });
return results; return results;

View file

@ -1,2 +1,2 @@
import CustomizationBase from 'admin/adapters/customization-base'; import CustomizationBase from "admin/adapters/customization-base";
export default CustomizationBase; export default CustomizationBase;

View file

@ -1,4 +1,4 @@
import RestAdapter from 'discourse/adapters/rest'; import RestAdapter from "discourse/adapters/rest";
export default RestAdapter.extend({ export default RestAdapter.extend({
basePath() { basePath() {
@ -7,7 +7,9 @@ export default RestAdapter.extend({
afterFindAll(results) { afterFindAll(results) {
let map = {}; let map = {};
results.forEach(theme => {map[theme.id] = theme;}); results.forEach(theme => {
map[theme.id] = theme;
});
results.forEach(theme => { results.forEach(theme => {
let mapped = theme.get("child_themes") || []; let mapped = theme.get("child_themes") || [];
mapped = mapped.map(t => map[t.id]); mapped = mapped.map(t => map[t.id]);

View file

@ -1,2 +1,2 @@
import CustomizationBase from 'admin/adapters/customization-base'; import CustomizationBase from "admin/adapters/customization-base";
export default CustomizationBase; export default CustomizationBase;

View file

@ -1,7 +1,7 @@
import RESTAdapter from 'discourse/adapters/rest'; import RESTAdapter from "discourse/adapters/rest";
export default RESTAdapter.extend({ export default RESTAdapter.extend({
basePath() { basePath() {
return '/admin/api/'; return "/admin/api/";
} }
}); });

View file

@ -1,7 +1,7 @@
import RESTAdapter from 'discourse/adapters/rest'; import RESTAdapter from "discourse/adapters/rest";
export default RESTAdapter.extend({ export default RESTAdapter.extend({
basePath() { basePath() {
return '/admin/api/'; return "/admin/api/";
} }
}); });

View file

@ -1,37 +1,37 @@
import loadScript from 'discourse/lib/load-script'; import loadScript from "discourse/lib/load-script";
import { observes } from 'ember-addons/ember-computed-decorators'; import { observes } from "ember-addons/ember-computed-decorators";
const LOAD_ASYNC = !Ember.testing; const LOAD_ASYNC = !Ember.testing;
export default Ember.Component.extend({ export default Ember.Component.extend({
mode: 'css', mode: "css",
classNames: ['ace-wrapper'], classNames: ["ace-wrapper"],
_editor: null, _editor: null,
_skipContentChangeEvent: null, _skipContentChangeEvent: null,
disabled: false, disabled: false,
@observes('editorId') @observes("editorId")
editorIdChanged() { editorIdChanged() {
if (this.get('autofocus')) { if (this.get("autofocus")) {
this.send('focus'); this.send("focus");
} }
}, },
@observes('content') @observes("content")
contentChanged() { contentChanged() {
if (this._editor && !this._skipContentChangeEvent) { if (this._editor && !this._skipContentChangeEvent) {
this._editor.getSession().setValue(this.get('content')); this._editor.getSession().setValue(this.get("content"));
} }
}, },
@observes('mode') @observes("mode")
modeChanged() { modeChanged() {
if (LOAD_ASYNC && this._editor && !this._skipContentChangeEvent) { if (LOAD_ASYNC && this._editor && !this._skipContentChangeEvent) {
this._editor.getSession().setMode("ace/mode/" + this.get('mode')); this._editor.getSession().setMode("ace/mode/" + this.get("mode"));
} }
}, },
@observes('disabled') @observes("disabled")
disabledStateChanged() { disabledStateChanged() {
this.changeDisabledState(); this.changeDisabledState();
}, },
@ -39,7 +39,7 @@ export default Ember.Component.extend({
changeDisabledState() { changeDisabledState() {
const editor = this._editor; const editor = this._editor;
if (editor) { if (editor) {
const disabled = this.get('disabled'); const disabled = this.get("disabled");
editor.setOptions({ editor.setOptions({
readOnly: disabled, readOnly: disabled,
highlightActiveLine: !disabled, highlightActiveLine: !disabled,
@ -56,12 +56,11 @@ export default Ember.Component.extend({
} }
if (this.appEvents) { if (this.appEvents) {
// xxx: don't run during qunit tests // xxx: don't run during qunit tests
this.appEvents.off('ace:resize', this, this.resize); this.appEvents.off("ace:resize", this, this.resize);
} }
$(window).off('ace:resize'); $(window).off("ace:resize");
}.on("willDestroyElement"),
}.on('willDestroyElement'),
resize() { resize() {
if (this._editor) { if (this._editor) {
@ -73,37 +72,41 @@ export default Ember.Component.extend({
this._super(); this._super();
loadScript("/javascripts/ace/ace.js", { scriptTag: true }).then(() => { loadScript("/javascripts/ace/ace.js", { scriptTag: true }).then(() => {
window.ace.require(['ace/ace'], loadedAce => { window.ace.require(["ace/ace"], loadedAce => {
if (!this.element || this.isDestroying || this.isDestroyed) { return; } if (!this.element || this.isDestroying || this.isDestroyed) {
const editor = loadedAce.edit(this.$('.ace')[0]); return;
}
const editor = loadedAce.edit(this.$(".ace")[0]);
if (LOAD_ASYNC) { if (LOAD_ASYNC) {
editor.setTheme("ace/theme/chrome"); editor.setTheme("ace/theme/chrome");
} }
editor.setShowPrintMargin(false); editor.setShowPrintMargin(false);
editor.setOptions({fontSize: "14px"}); editor.setOptions({ fontSize: "14px" });
if (LOAD_ASYNC) { if (LOAD_ASYNC) {
editor.getSession().setMode("ace/mode/" + this.get('mode')); editor.getSession().setMode("ace/mode/" + this.get("mode"));
} }
editor.on('change', () => { editor.on("change", () => {
this._skipContentChangeEvent = true; this._skipContentChangeEvent = true;
this.set('content', editor.getSession().getValue()); this.set("content", editor.getSession().getValue());
this._skipContentChangeEvent = false; this._skipContentChangeEvent = false;
}); });
editor.$blockScrolling = Infinity; editor.$blockScrolling = Infinity;
editor.renderer.setScrollMargin(10,10); editor.renderer.setScrollMargin(10, 10);
this.$().data('editor', editor); this.$().data("editor", editor);
this._editor = editor; this._editor = editor;
this.changeDisabledState(); this.changeDisabledState();
$(window).off('ace:resize').on('ace:resize', ()=>{ $(window)
this.appEvents.trigger('ace:resize'); .off("ace:resize")
}); .on("ace:resize", () => {
this.appEvents.trigger("ace:resize");
});
if (this.appEvents) { if (this.appEvents) {
// xxx: don't run during qunit tests // xxx: don't run during qunit tests
this.appEvents.on('ace:resize', ()=>this.resize()); this.appEvents.on("ace:resize", () => this.resize());
} }
if (this.get("autofocus")) { if (this.get("autofocus")) {

View file

@ -1,57 +1,64 @@
import debounce from 'discourse/lib/debounce'; import debounce from "discourse/lib/debounce";
import { renderSpinner } from 'discourse/helpers/loading-spinner'; import { renderSpinner } from "discourse/helpers/loading-spinner";
import { escapeExpression } from 'discourse/lib/utilities'; import { escapeExpression } from "discourse/lib/utilities";
import { bufferedRender } from 'discourse-common/lib/buffered-render'; import { bufferedRender } from "discourse-common/lib/buffered-render";
export default Ember.Component.extend(bufferedRender({ export default Ember.Component.extend(
classNames: ["admin-backups-logs"], bufferedRender({
classNames: ["admin-backups-logs"],
init() { init() {
this._super(); this._super();
this._reset(); this._reset();
}, },
_reset() { _reset() {
this.setProperties({ formattedLogs: "", index: 0 }); this.setProperties({ formattedLogs: "", index: 0 });
}, },
_scrollDown() { _scrollDown() {
const $div = this.$()[0]; const $div = this.$()[0];
$div.scrollTop = $div.scrollHeight; $div.scrollTop = $div.scrollHeight;
}, },
_updateFormattedLogs: debounce(function() { _updateFormattedLogs: debounce(function() {
const logs = this.get("logs"); const logs = this.get("logs");
if (logs.length === 0) { if (logs.length === 0) {
this._reset(); // reset the cached logs whenever the model is reset this._reset(); // reset the cached logs whenever the model is reset
} else { } else {
// do the log formatting only once for HELLish performance // do the log formatting only once for HELLish performance
let formattedLogs = this.get("formattedLogs"); let formattedLogs = this.get("formattedLogs");
for (let i = this.get("index"), length = logs.length; i < length; i++) { for (let i = this.get("index"), length = logs.length; i < length; i++) {
const date = logs[i].get("timestamp"), const date = logs[i].get("timestamp"),
message = escapeExpression(logs[i].get("message")); message = escapeExpression(logs[i].get("message"));
formattedLogs += "[" + date + "] " + message + "\n"; formattedLogs += "[" + date + "] " + message + "\n";
}
// update the formatted logs & cache index
this.setProperties({
formattedLogs: formattedLogs,
index: logs.length
});
// force rerender
this.rerenderBuffer();
} }
// update the formatted logs & cache index Ember.run.scheduleOnce("afterRender", this, this._scrollDown);
this.setProperties({ formattedLogs: formattedLogs, index: logs.length }); }, 150)
// force rerender .observes("logs.[]")
this.rerenderBuffer(); .on("init"),
}
Ember.run.scheduleOnce('afterRender', this, this._scrollDown);
}, 150).observes("logs.[]").on('init'),
buildBuffer(buffer) { buildBuffer(buffer) {
const formattedLogs = this.get("formattedLogs"); const formattedLogs = this.get("formattedLogs");
if (formattedLogs && formattedLogs.length > 0) { if (formattedLogs && formattedLogs.length > 0) {
buffer.push("<pre>"); buffer.push("<pre>");
buffer.push(formattedLogs); buffer.push(formattedLogs);
buffer.push("</pre>"); buffer.push("</pre>");
} else { } else {
buffer.push("<p>" + I18n.t("admin.backups.logs.none") + "</p>"); buffer.push("<p>" + I18n.t("admin.backups.logs.none") + "</p>");
}
// add a loading indicator
if (this.get("status.isOperationRunning")) {
buffer.push(renderSpinner("small"));
}
} }
// add a loading indicator })
if (this.get("status.isOperationRunning")) { );
buffer.push(renderSpinner('small'));
}
}
}));

View file

@ -1,33 +1,37 @@
import { iconHTML } from 'discourse-common/lib/icon-library'; import { iconHTML } from "discourse-common/lib/icon-library";
import { bufferedRender } from 'discourse-common/lib/buffered-render'; import { bufferedRender } from "discourse-common/lib/buffered-render";
export default Ember.Component.extend(bufferedRender({ export default Ember.Component.extend(
tagName: 'th', bufferedRender({
classNames: ['sortable'], tagName: "th",
rerenderTriggers: ['order', 'ascending'], classNames: ["sortable"],
rerenderTriggers: ["order", "ascending"],
buildBuffer(buffer) { buildBuffer(buffer) {
const icon = this.get('icon'); const icon = this.get("icon");
if (icon) { if (icon) {
buffer.push(iconHTML(icon)); buffer.push(iconHTML(icon));
}
buffer.push(I18n.t(this.get("i18nKey")));
if (this.get("field") === this.get("order")) {
buffer.push(
iconHTML(this.get("ascending") ? "chevron-up" : "chevron-down")
);
}
},
click() {
const currentOrder = this.get("order");
const field = this.get("field");
if (currentOrder === field) {
this.set("ascending", this.get("ascending") ? null : true);
} else {
this.setProperties({ order: field, ascending: null });
}
} }
})
buffer.push(I18n.t(this.get('i18nKey'))); );
if (this.get('field') === this.get('order')) {
buffer.push(iconHTML(this.get('ascending') ? 'chevron-up' : 'chevron-down'));
}
},
click() {
const currentOrder = this.get('order');
const field = this.get('field');
if (currentOrder === field) {
this.set('ascending', this.get('ascending') ? null : true);
} else {
this.setProperties({ order: field, ascending: null });
}
}
}));

View file

@ -1,3 +1,3 @@
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: ['row'] classNames: ["row"]
}); });

View file

@ -1,49 +1,56 @@
import loadScript from 'discourse/lib/load-script'; import loadScript from "discourse/lib/load-script";
import { number } from 'discourse/lib/formatter'; import { number } from "discourse/lib/formatter";
export default Ember.Component.extend({ export default Ember.Component.extend({
tagName: 'canvas', tagName: "canvas",
refreshChart(){ refreshChart() {
const ctx = this.$()[0].getContext("2d"); const ctx = this.$()[0].getContext("2d");
const model = this.get("model"); const model = this.get("model");
const rawData = this.get("model.data"); const rawData = this.get("model.data");
var data = { var data = {
labels: rawData.map(r => r.x), labels: rawData.map(r => r.x),
datasets: [{ datasets: [
data: rawData.map(r => r.y), {
label: model.get('title'), data: rawData.map(r => r.y),
backgroundColor: "rgba(200,220,240,0.3)", label: model.get("title"),
borderColor: "#08C" backgroundColor: "rgba(200,220,240,0.3)",
}] borderColor: "#08C"
}
]
}; };
const config = { const config = {
type: 'line', type: "line",
data: data, data: data,
options: { options: {
responsive: true, responsive: true,
tooltips: { tooltips: {
callbacks: { callbacks: {
title: (context) => moment(context[0].xLabel, "YYYY-MM-DD").format("LL") title: context =>
moment(context[0].xLabel, "YYYY-MM-DD").format("LL")
} }
}, },
scales: { scales: {
yAxes: [{ yAxes: [
display: true, {
ticks: { display: true,
callback: (label) => number(label), ticks: {
suggestedMin: 0 callback: label => number(label),
suggestedMin: 0
}
} }
}] ]
} }
}, }
}; };
this._chart = new window.Chart(ctx, config); this._chart = new window.Chart(ctx, config);
}, },
didInsertElement(){ didInsertElement() {
loadScript("/javascripts/Chart.min.js").then(() => this.refreshChart.apply(this)); loadScript("/javascripts/Chart.min.js").then(() =>
this.refreshChart.apply(this)
);
} }
}); });

View file

@ -1,3 +1,3 @@
export default Ember.Component.extend({ export default Ember.Component.extend({
tagName: '' tagName: ""
}); });

View file

@ -1,6 +1,9 @@
export default Ember.Component.extend({ export default Ember.Component.extend({
allTime: true, allTime: true,
tagName: 'tr', tagName: "tr",
reverseColors: Ember.computed.match('report.type', /^(time_to_first_response|topics_with_no_response)$/), reverseColors: Ember.computed.match(
classNameBindings: ['reverseColors'] "report.type",
/^(time_to_first_response|topics_with_no_response)$/
),
classNameBindings: ["reverseColors"]
}); });

View file

@ -1,3 +1,3 @@
export default Ember.Component.extend({ export default Ember.Component.extend({
tagName: 'tr' tagName: "tr"
}); });

View file

@ -1,3 +1,3 @@
export default Ember.Component.extend({ export default Ember.Component.extend({
tagName: 'tr' tagName: "tr"
}); });

View file

@ -1,97 +1,111 @@
import UserField from 'admin/models/user-field'; import UserField from "admin/models/user-field";
import { bufferedProperty } from 'discourse/mixins/buffered-content'; import { bufferedProperty } from "discourse/mixins/buffered-content";
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
import { propertyEqual } from 'discourse/lib/computed'; import { propertyEqual } from "discourse/lib/computed";
export default Ember.Component.extend(bufferedProperty('userField'), { export default Ember.Component.extend(bufferedProperty("userField"), {
editing: Ember.computed.empty('userField.id'), editing: Ember.computed.empty("userField.id"),
classNameBindings: [':user-field'], classNameBindings: [":user-field"],
cantMoveUp: propertyEqual('userField', 'firstField'), cantMoveUp: propertyEqual("userField", "firstField"),
cantMoveDown: propertyEqual('userField', 'lastField'), cantMoveDown: propertyEqual("userField", "lastField"),
userFieldsDescription: function() { userFieldsDescription: function() {
return I18n.t('admin.user_fields.description'); return I18n.t("admin.user_fields.description");
}.property(), }.property(),
bufferedFieldType: function() { bufferedFieldType: function() {
return UserField.fieldTypeById(this.get('buffered.field_type')); return UserField.fieldTypeById(this.get("buffered.field_type"));
}.property('buffered.field_type'), }.property("buffered.field_type"),
_focusOnEdit: function() { _focusOnEdit: function() {
if (this.get('editing')) { if (this.get("editing")) {
Ember.run.scheduleOnce('afterRender', this, '_focusName'); Ember.run.scheduleOnce("afterRender", this, "_focusName");
} }
}.observes('editing').on('didInsertElement'), }
.observes("editing")
.on("didInsertElement"),
_focusName: function() { _focusName: function() {
$('.user-field-name').select(); $(".user-field-name").select();
}, },
fieldName: function() { fieldName: function() {
return UserField.fieldTypeById(this.get('userField.field_type')).get('name'); return UserField.fieldTypeById(this.get("userField.field_type")).get(
}.property('userField.field_type'), "name"
);
}.property("userField.field_type"),
flags: function() { flags: function() {
const ret = []; const ret = [];
if (this.get('userField.editable')) { if (this.get("userField.editable")) {
ret.push(I18n.t('admin.user_fields.editable.enabled')); ret.push(I18n.t("admin.user_fields.editable.enabled"));
} }
if (this.get('userField.required')) { if (this.get("userField.required")) {
ret.push(I18n.t('admin.user_fields.required.enabled')); ret.push(I18n.t("admin.user_fields.required.enabled"));
} }
if (this.get('userField.show_on_profile')) { if (this.get("userField.show_on_profile")) {
ret.push(I18n.t('admin.user_fields.show_on_profile.enabled')); ret.push(I18n.t("admin.user_fields.show_on_profile.enabled"));
} }
if (this.get('userField.show_on_user_card')) { if (this.get("userField.show_on_user_card")) {
ret.push(I18n.t('admin.user_fields.show_on_user_card.enabled')); ret.push(I18n.t("admin.user_fields.show_on_user_card.enabled"));
} }
return ret.join(', '); return ret.join(", ");
}.property('userField.editable', 'userField.required', 'userField.show_on_profile', 'userField.show_on_user_card'), }.property(
"userField.editable",
"userField.required",
"userField.show_on_profile",
"userField.show_on_user_card"
),
actions: { actions: {
save() { save() {
const self = this; const self = this;
const buffered = this.get('buffered'); const buffered = this.get("buffered");
const attrs = buffered.getProperties('name', const attrs = buffered.getProperties(
'description', "name",
'field_type', "description",
'editable', "field_type",
'required', "editable",
'show_on_profile', "required",
'show_on_user_card', "show_on_profile",
'options'); "show_on_user_card",
"options"
);
this.get('userField').save(attrs).then(function() { this.get("userField")
self.set('editing', false); .save(attrs)
self.commitBuffer(); .then(function() {
}).catch(popupAjaxError); self.set("editing", false);
self.commitBuffer();
})
.catch(popupAjaxError);
}, },
moveUp() { moveUp() {
this.sendAction('moveUpAction', this.get('userField')); this.sendAction("moveUpAction", this.get("userField"));
}, },
moveDown() { moveDown() {
this.sendAction('moveDownAction', this.get('userField')); this.sendAction("moveDownAction", this.get("userField"));
}, },
edit() { edit() {
this.set('editing', true); this.set("editing", true);
}, },
destroy() { destroy() {
this.sendAction('destroyAction', this.get('userField')); this.sendAction("destroyAction", this.get("userField"));
}, },
cancel() { cancel() {
const id = this.get('userField.id'); const id = this.get("userField.id");
if (Ember.isEmpty(id)) { if (Ember.isEmpty(id)) {
this.sendAction('destroyAction', this.get('userField')); this.sendAction("destroyAction", this.get("userField"));
} else { } else {
this.rollbackBuffer(); this.rollbackBuffer();
this.set('editing', false); this.set("editing", false);
} }
} }
} }

View file

@ -1,19 +1,28 @@
import { iconHTML } from 'discourse-common/lib/icon-library'; import { iconHTML } from "discourse-common/lib/icon-library";
import { bufferedRender } from 'discourse-common/lib/buffered-render'; import { bufferedRender } from "discourse-common/lib/buffered-render";
export default Ember.Component.extend(bufferedRender({ export default Ember.Component.extend(
classNames: ['watched-word'], bufferedRender({
classNames: ["watched-word"],
buildBuffer(buffer) { buildBuffer(buffer) {
buffer.push(iconHTML('times')); buffer.push(iconHTML("times"));
buffer.push(' ' + this.get('word.word')); buffer.push(" " + this.get("word.word"));
}, },
click() { click() {
this.get('word').destroy().then(() => { this.get("word")
this.sendAction('action', this.get('word')); .destroy()
}).catch(e => { .then(() => {
bootbox.alert(I18n.t("generic_error_with_reason", {error: `http: ${e.status} - ${e.body}`})); this.sendAction("action", this.get("word"));
});; })
} .catch(e => {
})); bootbox.alert(
I18n.t("generic_error_with_reason", {
error: `http: ${e.status} - ${e.body}`
})
);
});
}
})
);

View file

@ -1,38 +1,40 @@
import computed from 'ember-addons/ember-computed-decorators'; import computed from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: ['hook-event'], classNames: ["hook-event"],
typeName: Ember.computed.alias('type.name'), typeName: Ember.computed.alias("type.name"),
@computed('typeName') @computed("typeName")
name(typeName) { name(typeName) {
return I18n.t(`admin.web_hooks.${typeName}_event.name`); return I18n.t(`admin.web_hooks.${typeName}_event.name`);
}, },
@computed('typeName') @computed("typeName")
details(typeName) { details(typeName) {
return I18n.t(`admin.web_hooks.${typeName}_event.details`); return I18n.t(`admin.web_hooks.${typeName}_event.details`);
}, },
@computed('model.[]', 'typeName') @computed("model.[]", "typeName")
eventTypeExists(eventTypes, typeName) { eventTypeExists(eventTypes, typeName) {
return eventTypes.any(event => event.name === typeName); return eventTypes.any(event => event.name === typeName);
}, },
@computed('eventTypeExists') @computed("eventTypeExists")
enabled: { enabled: {
get(eventTypeExists) { get(eventTypeExists) {
return eventTypeExists; return eventTypeExists;
}, },
set(value, eventTypeExists) { set(value, eventTypeExists) {
const type = this.get('type'); const type = this.get("type");
const model = this.get('model'); const model = this.get("model");
// add an association when not exists // add an association when not exists
if (value !== eventTypeExists) { if (value !== eventTypeExists) {
if (value) { if (value) {
model.addObject(type); model.addObject(type);
} else { } else {
model.removeObjects(model.filter(eventType => eventType.name === type.name)); model.removeObjects(
model.filter(eventType => eventType.name === type.name)
);
} }
} }

View file

@ -1,78 +1,92 @@
import computed from 'ember-addons/ember-computed-decorators'; import computed from "ember-addons/ember-computed-decorators";
import { ajax } from 'discourse/lib/ajax'; import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
import { ensureJSON, plainJSON, prettyJSON } from 'discourse/lib/formatter'; import { ensureJSON, plainJSON, prettyJSON } from "discourse/lib/formatter";
export default Ember.Component.extend({ export default Ember.Component.extend({
tagName: 'li', tagName: "li",
expandDetails: null, expandDetails: null,
@computed('model.status') @computed("model.status")
statusColorClasses(status) { statusColorClasses(status) {
if (!status) return ''; if (!status) return "";
if (status >= 200 && status <= 299) { if (status >= 200 && status <= 299) {
return 'text-successful'; return "text-successful";
} else { } else {
return 'text-danger'; return "text-danger";
} }
}, },
@computed('model.created_at') @computed("model.created_at")
createdAt(createdAt) { createdAt(createdAt) {
return moment(createdAt).format('YYYY-MM-DD HH:mm:ss'); return moment(createdAt).format("YYYY-MM-DD HH:mm:ss");
}, },
@computed('model.duration') @computed("model.duration")
completion(duration) { completion(duration) {
const seconds = Math.floor(duration / 10.0) / 100.0; const seconds = Math.floor(duration / 10.0) / 100.0;
return I18n.t('admin.web_hooks.events.completed_in', { count: seconds }); return I18n.t("admin.web_hooks.events.completed_in", { count: seconds });
}, },
actions: { actions: {
redeliver() { redeliver() {
return bootbox.confirm(I18n.t('admin.web_hooks.events.redeliver_confirm'), I18n.t('no_value'), I18n.t('yes_value'), result => { return bootbox.confirm(
if (result) { I18n.t("admin.web_hooks.events.redeliver_confirm"),
ajax(`/admin/api/web_hooks/${this.get('model.web_hook_id')}/events/${this.get('model.id')}/redeliver`, { type: 'POST' }).then(json => { I18n.t("no_value"),
this.set('model', json.web_hook_event); I18n.t("yes_value"),
}).catch(popupAjaxError); result => {
if (result) {
ajax(
`/admin/api/web_hooks/${this.get(
"model.web_hook_id"
)}/events/${this.get("model.id")}/redeliver`,
{ type: "POST" }
)
.then(json => {
this.set("model", json.web_hook_event);
})
.catch(popupAjaxError);
}
} }
}); );
}, },
toggleRequest() { toggleRequest() {
const expandDetailsKey = 'request'; const expandDetailsKey = "request";
if (this.get('expandDetails') !== expandDetailsKey) { if (this.get("expandDetails") !== expandDetailsKey) {
let headers = _.extend({ let headers = _.extend(
'Request URL': this.get('model.request_url'), {
'Request method': 'POST' "Request URL": this.get("model.request_url"),
}, ensureJSON(this.get('model.headers'))); "Request method": "POST"
},
ensureJSON(this.get("model.headers"))
);
this.setProperties({ this.setProperties({
headers: plainJSON(headers), headers: plainJSON(headers),
body: prettyJSON(this.get('model.payload')), body: prettyJSON(this.get("model.payload")),
expandDetails: expandDetailsKey, expandDetails: expandDetailsKey,
bodyLabel: I18n.t('admin.web_hooks.events.payload') bodyLabel: I18n.t("admin.web_hooks.events.payload")
}); });
} else { } else {
this.set('expandDetails', null); this.set("expandDetails", null);
} }
}, },
toggleResponse() { toggleResponse() {
const expandDetailsKey = 'response'; const expandDetailsKey = "response";
if (this.get('expandDetails') !== expandDetailsKey) { if (this.get("expandDetails") !== expandDetailsKey) {
this.setProperties({ this.setProperties({
headers: plainJSON(this.get('model.response_headers')), headers: plainJSON(this.get("model.response_headers")),
body: this.get('model.response_body'), body: this.get("model.response_body"),
expandDetails: expandDetailsKey, expandDetails: expandDetailsKey,
bodyLabel: I18n.t('admin.web_hooks.events.body') bodyLabel: I18n.t("admin.web_hooks.events.body")
}); });
} else { } else {
this.set('expandDetails', null); this.set("expandDetails", null);
} }
} }
} }
}); });

View file

@ -1,28 +1,32 @@
import computed from 'ember-addons/ember-computed-decorators'; import computed from "ember-addons/ember-computed-decorators";
import { iconHTML } from 'discourse-common/lib/icon-library'; import { iconHTML } from "discourse-common/lib/icon-library";
import { bufferedRender } from 'discourse-common/lib/buffered-render'; import { bufferedRender } from "discourse-common/lib/buffered-render";
export default Ember.Component.extend(bufferedRender({ export default Ember.Component.extend(
classes: ["text-muted", "text-danger", "text-successful"], bufferedRender({
icons: ["circle-o", "times-circle", "circle"], classes: ["text-muted", "text-danger", "text-successful"],
icons: ["circle-o", "times-circle", "circle"],
@computed('deliveryStatuses', 'model.last_delivery_status') @computed("deliveryStatuses", "model.last_delivery_status")
status(deliveryStatuses, lastDeliveryStatus) { status(deliveryStatuses, lastDeliveryStatus) {
return deliveryStatuses.find(s => s.id === lastDeliveryStatus); return deliveryStatuses.find(s => s.id === lastDeliveryStatus);
}, },
@computed('status.id', 'icons') @computed("status.id", "icons")
icon(statusId, icons) { icon(statusId, icons) {
return icons[statusId - 1]; return icons[statusId - 1];
}, },
@computed('status.id', 'classes') @computed("status.id", "classes")
class(statusId, classes) { class(statusId, classes) {
return classes[statusId - 1]; return classes[statusId - 1];
}, },
buildBuffer(buffer) { buildBuffer(buffer) {
buffer.push(iconHTML(this.get('icon'), { class: this.get('class') })); buffer.push(iconHTML(this.get("icon"), { class: this.get("class") }));
buffer.push(I18n.t(`admin.web_hooks.delivery_status.${this.get('status.name')}`)); buffer.push(
} I18n.t(`admin.web_hooks.delivery_status.${this.get("status.name")}`)
})); );
}
})
);

View file

@ -1,11 +1,11 @@
export default Ember.Component.extend({ export default Ember.Component.extend({
didInsertElement() { didInsertElement() {
this._super(); this._super();
$('body').addClass('admin-interface'); $("body").addClass("admin-interface");
}, },
willDestroyElement() { willDestroyElement() {
this._super(); this._super();
$('body').removeClass('admin-interface'); $("body").removeClass("admin-interface");
} }
}); });

View file

@ -1,3 +1,3 @@
export default Ember.Component.extend({ export default Ember.Component.extend({
tagName: '' tagName: ""
}); });

View file

@ -1,4 +1,4 @@
import {default as loadScript, loadCSS } from 'discourse/lib/load-script'; import { default as loadScript, loadCSS } from "discourse/lib/load-script";
/** /**
An input field for a color. An input field for a color.
@ -8,35 +8,43 @@ import {default as loadScript, loadCSS } from 'discourse/lib/load-script';
@params valid is a boolean indicating if the input field is a valid color. @params valid is a boolean indicating if the input field is a valid color.
**/ **/
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: ['color-picker'], classNames: ["color-picker"],
hexValueChanged: function() { hexValueChanged: function() {
var hex = this.get('hexValue'); var hex = this.get("hexValue");
let $text = this.$('input.hex-input'); let $text = this.$("input.hex-input");
if (this.get('valid')) { if (this.get("valid")) {
$text.attr('style', 'color: ' + (this.get('brightnessValue') > 125 ? 'black' : 'white') + '; background-color: #' + hex + ';'); $text.attr(
"style",
"color: " +
(this.get("brightnessValue") > 125 ? "black" : "white") +
"; background-color: #" +
hex +
";"
);
if (this.get('pickerLoaded')) { if (this.get("pickerLoaded")) {
this.$('.picker').spectrum({color: "#" + this.get('hexValue')}); this.$(".picker").spectrum({ color: "#" + this.get("hexValue") });
} }
} else { } else {
$text.attr('style', ''); $text.attr("style", "");
} }
}.observes('hexValue', 'brightnessValue', 'valid'), }.observes("hexValue", "brightnessValue", "valid"),
didInsertElement() { didInsertElement() {
loadScript('/javascripts/spectrum.js').then(()=>{ loadScript("/javascripts/spectrum.js").then(() => {
loadCSS('/javascripts/spectrum.css').then(()=>{ loadCSS("/javascripts/spectrum.css").then(() => {
Em.run.schedule('afterRender', ()=>{ Em.run.schedule("afterRender", () => {
this.$('.picker').spectrum({color: "#" + this.get('hexValue')}) this.$(".picker")
.on("change.spectrum", (me, color)=>{ .spectrum({ color: "#" + this.get("hexValue") })
this.set('hexValue', color.toHexString().replace("#","")); .on("change.spectrum", (me, color) => {
}); this.set("hexValue", color.toHexString().replace("#", ""));
this.set('pickerLoaded', true); });
this.set("pickerLoaded", true);
}); });
}); });
}); });
Em.run.schedule('afterRender', ()=>{ Em.run.schedule("afterRender", () => {
this.hexValueChanged(); this.hexValueChanged();
}); });
} }

View file

@ -9,11 +9,12 @@ export default Ember.Component.extend(AsyncReport, {
let payload = this.buildPayload(["total", "prev30Days"]); let payload = this.buildPayload(["total", "prev30Days"]);
return Ember.RSVP.Promise.all(this.get("dataSources").map(dataSource => { return Ember.RSVP.Promise.all(
return ajax(dataSource, payload) this.get("dataSources").map(dataSource => {
.then(response => { return ajax(dataSource, payload).then(response => {
this.get("reports").pushObject(this.loadReport(response.report)); this.get("reports").pushObject(this.loadReport(response.report));
}); });
})); })
);
} }
}); });

View file

@ -1,7 +1,7 @@
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import AsyncReport from "admin/mixins/async-report"; import AsyncReport from "admin/mixins/async-report";
import Report from "admin/models/report"; import Report from "admin/models/report";
import { number } from 'discourse/lib/formatter'; import { number } from "discourse/lib/formatter";
import loadScript from "discourse/lib/load-script"; import loadScript from "discourse/lib/load-script";
import { registerTooltip, unregisterTooltip } from "discourse/lib/tooltip"; import { registerTooltip, unregisterTooltip } from "discourse/lib/tooltip";
@ -9,9 +9,8 @@ function collapseWeekly(data, average) {
let aggregate = []; let aggregate = [];
let bucket, i; let bucket, i;
let offset = data.length % 7; let offset = data.length % 7;
for(i = offset; i < data.length; i++) { for (i = offset; i < data.length; i++) {
if (bucket && i % 7 === offset) {
if (bucket && (i % 7 === offset)) {
if (average) { if (average) {
bucket.y = parseFloat((bucket.y / 7.0).toFixed(2)); bucket.y = parseFloat((bucket.y / 7.0).toFixed(2));
} }
@ -59,12 +58,13 @@ export default Ember.Component.extend(AsyncReport, {
this._chart = null; this._chart = null;
} }
return Ember.RSVP.Promise.all(this.get("dataSources").map(dataSource => { return Ember.RSVP.Promise.all(
return ajax(dataSource, payload) this.get("dataSources").map(dataSource => {
.then(response => { return ajax(dataSource, payload).then(response => {
this.get("reports").pushObject(this.loadReport(response.report)); this.get("reports").pushObject(this.loadReport(response.report));
}); });
})); })
);
}, },
loadReport(report, previousReport) { loadReport(report, previousReport) {
@ -77,7 +77,9 @@ export default Ember.Component.extend(AsyncReport, {
if (previousReport && previousReport.color.length) { if (previousReport && previousReport.color.length) {
report.color = previousReport.color; report.color = previousReport.color;
} else { } else {
const dataSourceNameIndex = this.get("dataSourceNames").split(",").indexOf(report.type); const dataSourceNameIndex = this.get("dataSourceNames")
.split(",")
.indexOf(report.type);
report.color = this.pickColorAtIndex(dataSourceNameIndex); report.color = this.pickColorAtIndex(dataSourceNameIndex);
} }
@ -94,13 +96,17 @@ export default Ember.Component.extend(AsyncReport, {
const reportsForPeriod = this.get("reportsForPeriod"); const reportsForPeriod = this.get("reportsForPeriod");
const labels = Ember.makeArray(reportsForPeriod.get("firstObject.data")).map(d => d.x); const labels = Ember.makeArray(
reportsForPeriod.get("firstObject.data")
).map(d => d.x);
const data = { const data = {
labels, labels,
datasets: reportsForPeriod.map(report => { datasets: reportsForPeriod.map(report => {
return { return {
data: Ember.makeArray(report.data).map(d => Math.round(parseFloat(d.y))), data: Ember.makeArray(report.data).map(d =>
Math.round(parseFloat(d.y))
),
backgroundColor: "rgba(200,220,240,0.3)", backgroundColor: "rgba(200,220,240,0.3)",
borderColor: report.color borderColor: report.color
}; };
@ -129,7 +135,8 @@ export default Ember.Component.extend(AsyncReport, {
options: { options: {
tooltips: { tooltips: {
callbacks: { callbacks: {
title: (context) => moment(context[0].xLabel, "YYYY-MM-DD").format("LL") title: context =>
moment(context[0].xLabel, "YYYY-MM-DD").format("LL")
} }
}, },
legend: { legend: {
@ -146,20 +153,24 @@ export default Ember.Component.extend(AsyncReport, {
} }
}, },
scales: { scales: {
yAxes: [{ yAxes: [
display: true, {
ticks: { callback: (label) => number(label) } display: true,
}], ticks: { callback: label => number(label) }
xAxes: [{
display: true,
gridLines: { display: false },
type: "time",
time: {
parser: "YYYY-MM-DD"
} }
}], ],
xAxes: [
{
display: true,
gridLines: { display: false },
type: "time",
time: {
parser: "YYYY-MM-DD"
}
}
]
} }
}, }
}; };
} }
}); });

View file

@ -9,11 +9,12 @@ export default Ember.Component.extend(AsyncReport, {
let payload = this.buildPayload(["total", "prev30Days"]); let payload = this.buildPayload(["total", "prev30Days"]);
return Ember.RSVP.Promise.all(this.get("dataSources").map(dataSource => { return Ember.RSVP.Promise.all(
return ajax(dataSource, payload) this.get("dataSources").map(dataSource => {
.then(response => { return ajax(dataSource, payload).then(response => {
this.get("reports").pushObject(this.loadReport(response.report)); this.get("reports").pushObject(this.loadReport(response.report));
}); });
})); })
);
} }
}); });

View file

@ -1,63 +1,79 @@
import { bufferedProperty } from 'discourse/mixins/buffered-content'; import { bufferedProperty } from "discourse/mixins/buffered-content";
import computed from 'ember-addons/ember-computed-decorators'; import computed from "ember-addons/ember-computed-decorators";
import { on, observes } from 'ember-addons/ember-computed-decorators'; import { on, observes } from "ember-addons/ember-computed-decorators";
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
export default Ember.Component.extend(bufferedProperty('host'), { export default Ember.Component.extend(bufferedProperty("host"), {
editToggled: false, editToggled: false,
tagName: 'tr', tagName: "tr",
categoryId: null, categoryId: null,
editing: Ember.computed.or('host.isNew', 'editToggled'), editing: Ember.computed.or("host.isNew", "editToggled"),
@on('didInsertElement') @on("didInsertElement")
@observes('editing') @observes("editing")
_focusOnInput() { _focusOnInput() {
Ember.run.schedule('afterRender', () => { this.$('.host-name').focus(); }); Ember.run.schedule("afterRender", () => {
this.$(".host-name").focus();
});
}, },
@computed('buffered.host', 'host.isSaving') @computed("buffered.host", "host.isSaving")
cantSave(host, isSaving) { cantSave(host, isSaving) {
return isSaving || Ember.isEmpty(host); return isSaving || Ember.isEmpty(host);
}, },
actions: { actions: {
edit() { edit() {
this.set('categoryId', this.get('host.category.id')); this.set("categoryId", this.get("host.category.id"));
this.set('editToggled', true); this.set("editToggled", true);
}, },
save() { save() {
if (this.get('cantSave')) { return; } if (this.get("cantSave")) {
return;
}
const props = this.get('buffered').getProperties('host', 'path_whitelist', 'class_name'); const props = this.get("buffered").getProperties(
props.category_id = this.get('categoryId'); "host",
"path_whitelist",
"class_name"
);
props.category_id = this.get("categoryId");
const host = this.get('host'); const host = this.get("host");
host.save(props).then(() => { host
host.set('category', Discourse.Category.findById(this.get('categoryId'))); .save(props)
this.set('editToggled', false); .then(() => {
}).catch(popupAjaxError); host.set(
"category",
Discourse.Category.findById(this.get("categoryId"))
);
this.set("editToggled", false);
})
.catch(popupAjaxError);
}, },
delete() { delete() {
bootbox.confirm(I18n.t('admin.embedding.confirm_delete'), (result) => { bootbox.confirm(I18n.t("admin.embedding.confirm_delete"), result => {
if (result) { if (result) {
this.get('host').destroyRecord().then(() => { this.get("host")
this.sendAction('deleteHost', this.get('host')); .destroyRecord()
}); .then(() => {
this.sendAction("deleteHost", this.get("host"));
});
} }
}); });
}, },
cancel() { cancel() {
const host = this.get('host'); const host = this.get("host");
if (host.get('isNew')) { if (host.get("isNew")) {
this.sendAction('deleteHost', host); this.sendAction("deleteHost", host);
} else { } else {
this.rollbackBuffer(); this.rollbackBuffer();
this.set('editToggled', false); this.set("editToggled", false);
} }
} }
} }

View file

@ -1,22 +1,30 @@
import computed from 'ember-addons/ember-computed-decorators'; import computed from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: ['embed-setting'], classNames: ["embed-setting"],
@computed('field') @computed("field")
inputId(field) { return field.dasherize(); }, inputId(field) {
return field.dasherize();
},
@computed('field') @computed("field")
translationKey(field) { return `admin.embedding.${field}`; }, translationKey(field) {
return `admin.embedding.${field}`;
},
@computed('type') @computed("type")
isCheckbox(type) { return type === "checkbox"; }, isCheckbox(type) {
return type === "checkbox";
},
@computed('value') @computed("value")
checked: { checked: {
get(value) { return !!value; }, get(value) {
return !!value;
},
set(value) { set(value) {
this.set('value', value); this.set("value", value);
return value; return value;
} }
} }

View file

@ -1,3 +1,3 @@
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: ['flag-user-lists'] classNames: ["flag-user-lists"]
}); });

View file

@ -1,3 +1,3 @@
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: ['flagged-post-response'] classNames: ["flagged-post-response"]
}); });

View file

@ -1,3 +1,3 @@
export default Ember.Component.extend({ export default Ember.Component.extend({
tagName: 'h3' tagName: "h3"
}); });

View file

@ -1,21 +1,21 @@
import showModal from 'discourse/lib/show-modal'; import showModal from "discourse/lib/show-modal";
import computed from 'ember-addons/ember-computed-decorators'; import computed from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({ export default Ember.Component.extend({
adminTools: Ember.inject.service(), adminTools: Ember.inject.service(),
expanded: false, expanded: false,
tagName: 'div', tagName: "div",
classNameBindings: [ classNameBindings: [
':flagged-post', ":flagged-post",
'flaggedPost.hidden:hidden-post', "flaggedPost.hidden:hidden-post",
'flaggedPost.deleted' "flaggedPost.deleted"
], ],
canAct: Ember.computed.alias('actableFilter'), canAct: Ember.computed.alias("actableFilter"),
@computed('filter') @computed("filter")
actableFilter(filter) { actableFilter(filter) {
return filter === 'active'; return filter === "active";
}, },
removeAfter(promise) { removeAfter(promise) {
@ -24,7 +24,7 @@ export default Ember.Component.extend({
_spawnModal(name, model, modalClass) { _spawnModal(name, model, modalClass) {
let controller = showModal(name, { model, admin: true, modalClass }); let controller = showModal(name, { model, admin: true, modalClass });
controller.removeAfter = (p) => this.removeAfter(p); controller.removeAfter = p => this.removeAfter(p);
}, },
actions: { actions: {
@ -33,23 +33,25 @@ export default Ember.Component.extend({
}, },
disagree() { disagree() {
this.removeAfter(this.get('flaggedPost').disagreeFlags()); this.removeAfter(this.get("flaggedPost").disagreeFlags());
}, },
defer() { defer() {
this.removeAfter(this.get('flaggedPost').deferFlags()); this.removeAfter(this.get("flaggedPost").deferFlags());
}, },
expand() { expand() {
this.get('flaggedPost').expandHidden().then(() => { this.get("flaggedPost")
this.set('expanded', true); .expandHidden()
}); .then(() => {
this.set("expanded", true);
});
}, },
showModerationHistory() { showModerationHistory() {
this.get('adminTools').showModerationHistory({ this.get("adminTools").showModerationHistory({
filter: 'post', filter: "post",
post_id: this.get('flaggedPost.id') post_id: this.get("flaggedPost.id")
}); });
} }
} }

View file

@ -1,12 +1,10 @@
import { on, observes } from 'ember-addons/ember-computed-decorators'; import { on, observes } from "ember-addons/ember-computed-decorators";
import highlightSyntax from 'discourse/lib/highlight-syntax'; import highlightSyntax from "discourse/lib/highlight-syntax";
export default Ember.Component.extend({ export default Ember.Component.extend({
@on("didInsertElement")
@on('didInsertElement') @observes("code")
@observes('code')
_refresh: function() { _refresh: function() {
highlightSyntax(this.$()); highlightSyntax(this.$());
} }
}); });

View file

@ -1,12 +1,15 @@
import {default as computed, observes} from "ember-addons/ember-computed-decorators"; import {
default as computed,
observes
} from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({ export default Ember.Component.extend({
init(){ init() {
this._super(); this._super();
this.set("checkedInternal", this.get("checked")); this.set("checkedInternal", this.get("checked"));
}, },
classNames: ['inline-edit'], classNames: ["inline-edit"],
@observes("checked") @observes("checked")
checkedChanged() { checkedChanged() {
@ -20,15 +23,15 @@ export default Ember.Component.extend({
@computed("checked", "checkedInternal") @computed("checked", "checkedInternal")
changed(checked, checkedInternal) { changed(checked, checkedInternal) {
return (!!checked) !== (!!checkedInternal); return !!checked !== !!checkedInternal;
}, },
actions: { actions: {
cancelled(){ cancelled() {
this.set("checkedInternal", this.get("checked")); this.set("checkedInternal", this.get("checked"));
}, },
finished(){ finished() {
this.set("checked", this.get("checkedInternal")); this.set("checked", this.get("checkedInternal"));
this.sendAction(); this.sendAction();
} }

View file

@ -1,15 +1,17 @@
import { ajax } from 'discourse/lib/ajax'; import { ajax } from "discourse/lib/ajax";
import AdminUser from 'admin/models/admin-user'; import AdminUser from "admin/models/admin-user";
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: ["ip-lookup"], classNames: ["ip-lookup"],
city: function () { city: function() {
return [ return [
this.get("location.city"), this.get("location.city"),
this.get("location.region"), this.get("location.region"),
this.get("location.country") this.get("location.country")
].filter(Boolean).join(", "); ]
.filter(Boolean)
.join(", ");
}.property("location.{city,region,country}"), }.property("location.{city,region,country}"),
otherAccountsToDelete: function() { otherAccountsToDelete: function() {
@ -20,14 +22,14 @@ export default Ember.Component.extend({
}.property("other_accounts", "totalOthersWithSameIP"), }.property("other_accounts", "totalOthersWithSameIP"),
actions: { actions: {
lookup: function () { lookup: function() {
var self = this; var self = this;
this.set("show", true); this.set("show", true);
if (!this.get("location")) { if (!this.get("location")) {
ajax("/admin/users/ip-info", { ajax("/admin/users/ip-info", {
data: { ip: this.get("ip") } data: { ip: this.get("ip") }
}).then(function (location) { }).then(function(location) {
self.set("location", Em.Object.create(location)); self.set("location", Em.Object.create(location));
}); });
} }
@ -36,50 +38,57 @@ export default Ember.Component.extend({
this.set("otherAccountsLoading", true); this.set("otherAccountsLoading", true);
var data = { var data = {
"ip": this.get("ip"), ip: this.get("ip"),
"exclude": this.get("userId"), exclude: this.get("userId"),
"order": "trust_level DESC" order: "trust_level DESC"
}; };
ajax("/admin/users/total-others-with-same-ip", { data }).then(function (result) { ajax("/admin/users/total-others-with-same-ip", { data }).then(function(
result
) {
self.set("totalOthersWithSameIP", result.total); self.set("totalOthersWithSameIP", result.total);
}); });
AdminUser.findAll("active", data).then(function (users) { AdminUser.findAll("active", data).then(function(users) {
self.setProperties({ self.setProperties({
other_accounts: users, other_accounts: users,
otherAccountsLoading: false, otherAccountsLoading: false
}); });
}); });
} }
}, },
hide: function () { hide: function() {
this.set("show", false); this.set("show", false);
}, },
deleteOtherAccounts: function() { deleteOtherAccounts: function() {
var self = this; var self = this;
bootbox.confirm(I18n.t("ip_lookup.confirm_delete_other_accounts"), I18n.t("no_value"), I18n.t("yes_value"), function (confirmed) { bootbox.confirm(
if (confirmed) { I18n.t("ip_lookup.confirm_delete_other_accounts"),
self.setProperties({ I18n.t("no_value"),
other_accounts: null, I18n.t("yes_value"),
otherAccountsLoading: true, function(confirmed) {
totalOthersWithSameIP: null if (confirmed) {
}); self.setProperties({
other_accounts: null,
otherAccountsLoading: true,
totalOthersWithSameIP: null
});
ajax("/admin/users/delete-others-with-same-ip.json", { ajax("/admin/users/delete-others-with-same-ip.json", {
type: "DELETE", type: "DELETE",
data: { data: {
"ip": self.get("ip"), ip: self.get("ip"),
"exclude": self.get("userId"), exclude: self.get("userId"),
"order": "trust_level DESC" order: "trust_level DESC"
} }
}).then(function() { }).then(function() {
self.send("lookup"); self.send("lookup");
}); });
}
} }
}); );
} }
} }
}); });

View file

@ -1,3 +1,3 @@
export default Ember.Component.extend({ export default Ember.Component.extend({
tagName: 'tr', tagName: "tr"
}); });

View file

@ -1,6 +1,6 @@
import computed from 'ember-addons/ember-computed-decorators'; import computed from "ember-addons/ember-computed-decorators";
const ACTIONS = ['delete', 'edit', 'none']; const ACTIONS = ["delete", "edit", "none"];
export default Ember.Component.extend({ export default Ember.Component.extend({
postAction: null, postAction: null,
postEdit: null, postEdit: null,
@ -12,19 +12,19 @@ export default Ember.Component.extend({
}); });
}, },
editing: Ember.computed.equal('postAction', 'edit'), editing: Ember.computed.equal("postAction", "edit"),
actions: { actions: {
penaltyChanged() { penaltyChanged() {
let postAction = this.get('postAction'); let postAction = this.get("postAction");
// If we switch to edit mode, jump to the edit textarea // If we switch to edit mode, jump to the edit textarea
if (postAction === 'edit') { if (postAction === "edit") {
Ember.run.scheduleOnce('afterRender', () => { Ember.run.scheduleOnce("afterRender", () => {
let $elem = this.$(); let $elem = this.$();
let body = $elem.closest('.modal-body'); let body = $elem.closest(".modal-body");
body.scrollTop(body.height()); body.scrollTop(body.height());
$elem.find('.post-editor').focus(); $elem.find(".post-editor").focus();
}); });
} }
} }

View file

@ -1,45 +1,58 @@
import Permalink from 'admin/models/permalink'; import Permalink from "admin/models/permalink";
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: ['permalink-form'], classNames: ["permalink-form"],
formSubmitted: false, formSubmitted: false,
permalinkType: 'topic_id', permalinkType: "topic_id",
permalinkTypes: function() { permalinkTypes: function() {
return [ return [
{id: 'topic_id', name: I18n.t('admin.permalink.topic_id')}, { id: "topic_id", name: I18n.t("admin.permalink.topic_id") },
{id: 'post_id', name: I18n.t('admin.permalink.post_id')}, { id: "post_id", name: I18n.t("admin.permalink.post_id") },
{id: 'category_id', name: I18n.t('admin.permalink.category_id')}, { id: "category_id", name: I18n.t("admin.permalink.category_id") },
{id: 'external_url', name: I18n.t('admin.permalink.external_url')} { id: "external_url", name: I18n.t("admin.permalink.external_url") }
]; ];
}.property(), }.property(),
permalinkTypePlaceholder: function() { permalinkTypePlaceholder: function() {
return 'admin.permalink.' + this.get('permalinkType'); return "admin.permalink." + this.get("permalinkType");
}.property('permalinkType'), }.property("permalinkType"),
actions: { actions: {
submit: function() { submit: function() {
if (!this.get('formSubmitted')) { if (!this.get("formSubmitted")) {
const self = this; const self = this;
self.set('formSubmitted', true); self.set("formSubmitted", true);
const permalink = Permalink.create({url: self.get('url'), permalink_type: self.get('permalinkType'), permalink_type_value: self.get('permalink_type_value')}); const permalink = Permalink.create({
permalink.save().then(function(result) { url: self.get("url"),
self.set('url', ''); permalink_type: self.get("permalinkType"),
self.set('permalink_type_value', ''); permalink_type_value: self.get("permalink_type_value")
self.set('formSubmitted', false);
self.sendAction('action', Permalink.create(result.permalink));
Em.run.schedule('afterRender', function() { self.$('.permalink-url').focus(); });
}, function(e) {
self.set('formSubmitted', false);
let error;
if (e.responseJSON && e.responseJSON.errors) {
error = I18n.t("generic_error_with_reason", {error: e.responseJSON.errors.join('. ')});
} else {
error = I18n.t("generic_error");
}
bootbox.alert(error, function() { self.$('.permalink-url').focus(); });
}); });
permalink.save().then(
function(result) {
self.set("url", "");
self.set("permalink_type_value", "");
self.set("formSubmitted", false);
self.sendAction("action", Permalink.create(result.permalink));
Em.run.schedule("afterRender", function() {
self.$(".permalink-url").focus();
});
},
function(e) {
self.set("formSubmitted", false);
let error;
if (e.responseJSON && e.responseJSON.errors) {
error = I18n.t("generic_error_with_reason", {
error: e.responseJSON.errors.join(". ")
});
} else {
error = I18n.t("generic_error");
}
bootbox.alert(error, function() {
self.$(".permalink-url").focus();
});
}
);
} }
} }
}, },
@ -47,10 +60,11 @@ export default Ember.Component.extend({
didInsertElement: function() { didInsertElement: function() {
var self = this; var self = this;
self._super(); self._super();
Em.run.schedule('afterRender', function() { Em.run.schedule("afterRender", function() {
self.$('.external-url').keydown(function(e) { self.$(".external-url").keydown(function(e) {
if (e.keyCode === 13) { // enter key if (e.keyCode === 13) {
self.send('submit'); // enter key
self.send("submit");
} }
}); });
}); });

View file

@ -1,5 +1,5 @@
import { iconHTML } from 'discourse-common/lib/icon-library'; import { iconHTML } from "discourse-common/lib/icon-library";
import { bufferedRender } from 'discourse-common/lib/buffered-render'; import { bufferedRender } from "discourse-common/lib/buffered-render";
/*global Resumable:true */ /*global Resumable:true */
@ -13,111 +13,119 @@ import { bufferedRender } from 'discourse-common/lib/buffered-render';
uploadText="UPLOAD" uploadText="UPLOAD"
}} }}
**/ **/
export default Ember.Component.extend(bufferedRender({ export default Ember.Component.extend(
tagName: "button", bufferedRender({
classNames: ["btn", "ru"], tagName: "button",
classNameBindings: ["isUploading"], classNames: ["btn", "ru"],
attributeBindings: ["translatedTitle:title"], classNameBindings: ["isUploading"],
attributeBindings: ["translatedTitle:title"],
resumable: null, resumable: null,
isUploading: false, isUploading: false,
progress: 0, progress: 0,
rerenderTriggers: ['isUploading', 'progress'], rerenderTriggers: ["isUploading", "progress"],
translatedTitle: function() { translatedTitle: function() {
const title = this.get('title'); const title = this.get("title");
return title ? I18n.t(title) : this.get('text'); return title ? I18n.t(title) : this.get("text");
}.property('title', 'text'), }.property("title", "text"),
text: function() { text: function() {
if (this.get("isUploading")) { if (this.get("isUploading")) {
return this.get("progress") + " %"; return this.get("progress") + " %";
} else { } else {
return this.get("uploadText"); return this.get("uploadText");
} }
}.property("isUploading", "progress"), }.property("isUploading", "progress"),
buildBuffer(buffer) { buildBuffer(buffer) {
const icon = this.get("isUploading") ? "times" : "upload"; const icon = this.get("isUploading") ? "times" : "upload";
buffer.push(iconHTML(icon)); buffer.push(iconHTML(icon));
buffer.push("<span class='ru-label'>" + this.get("text") + "</span>"); buffer.push("<span class='ru-label'>" + this.get("text") + "</span>");
buffer.push("<span class='ru-progress' style='width:" + this.get("progress") + "%'></span>"); buffer.push(
}, "<span class='ru-progress' style='width:" +
this.get("progress") +
"%'></span>"
);
},
click: function() {
if (this.get("isUploading")) {
this.resumable.cancel();
var self = this;
Em.run.later(function() {
self._reset();
});
return false;
} else {
return true;
}
},
_reset: function() {
this.setProperties({ isUploading: false, progress: 0 });
},
_initialize: function() {
this.resumable = new Resumable({
target: Discourse.getURL(this.get("target")),
maxFiles: 1, // only 1 file at a time
headers: {
"X-CSRF-Token": $("meta[name='csrf-token']").attr("content")
}
});
click: function() {
if (this.get("isUploading")) {
this.resumable.cancel();
var self = this; var self = this;
Em.run.later(function() { self._reset(); });
return false;
} else {
return true;
}
},
_reset: function() { this.resumable.on("fileAdded", function() {
this.setProperties({ isUploading: false, progress: 0 }); // automatically upload the selected file
}, self.resumable.upload();
// mark as uploading
_initialize: function() { Em.run.later(function() {
this.resumable = new Resumable({ self.set("isUploading", true);
target: Discourse.getURL(this.get("target")), });
maxFiles: 1, // only 1 file at a time
headers: { "X-CSRF-Token": $("meta[name='csrf-token']").attr("content") }
});
var self = this;
this.resumable.on("fileAdded", function() {
// automatically upload the selected file
self.resumable.upload();
// mark as uploading
Em.run.later(function() {
self.set("isUploading", true);
}); });
});
this.resumable.on("fileProgress", function(file) { this.resumable.on("fileProgress", function(file) {
// update progress // update progress
Em.run.later(function() { Em.run.later(function() {
self.set("progress", parseInt(file.progress() * 100, 10)); self.set("progress", parseInt(file.progress() * 100, 10));
});
}); });
});
this.resumable.on("fileSuccess", function(file) { this.resumable.on("fileSuccess", function(file) {
Em.run.later(function() { Em.run.later(function() {
// mark as not uploading anymore // mark as not uploading anymore
self._reset(); self._reset();
// fire an event to allow the parent route to reload its model // fire an event to allow the parent route to reload its model
self.sendAction("success", file.fileName); self.sendAction("success", file.fileName);
});
}); });
});
this.resumable.on("fileError", function(file, message) { this.resumable.on("fileError", function(file, message) {
Em.run.later(function() { Em.run.later(function() {
// mark as not uploading anymore // mark as not uploading anymore
self._reset(); self._reset();
// fire an event to allow the parent route to display the error message // fire an event to allow the parent route to display the error message
self.sendAction("error", file.fileName, message); self.sendAction("error", file.fileName, message);
});
}); });
}); }.on("init"),
}.on("init"), _assignBrowse: function() {
var self = this;
Em.run.schedule("afterRender", function() {
self.resumable.assignBrowse(self.$());
});
}.on("didInsertElement"),
_assignBrowse: function() { _teardown: function() {
var self = this; if (this.resumable) {
Em.run.schedule("afterRender", function() { this.resumable.cancel();
self.resumable.assignBrowse(self.$()); this.resumable = null;
}); }
}.on("didInsertElement"), }.on("willDestroyElement")
})
_teardown: function() { );
if (this.resumable) {
this.resumable.cancel();
this.resumable = null;
}
}.on("willDestroyElement")
}));

View file

@ -1,13 +1,13 @@
import computed from 'ember-addons/ember-computed-decorators'; import computed from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: ['controls'], classNames: ["controls"],
buttonDisabled: Ember.computed.or('model.isSaving', 'saveDisabled'), buttonDisabled: Ember.computed.or("model.isSaving", "saveDisabled"),
@computed('model.isSaving') @computed("model.isSaving")
savingText(saving) { savingText(saving) {
return saving ? 'saving' : 'save'; return saving ? "saving" : "save";
}, },
actions: { actions: {

View file

@ -9,14 +9,14 @@
as an argument. as an argument.
**/ **/
import ScreenedIpAddress from 'admin/models/screened-ip-address'; import ScreenedIpAddress from "admin/models/screened-ip-address";
import computed from 'ember-addons/ember-computed-decorators'; import computed from "ember-addons/ember-computed-decorators";
import { on } from 'ember-addons/ember-computed-decorators'; import { on } from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: ['screened-ip-address-form'], classNames: ["screened-ip-address-form"],
formSubmitted: false, formSubmitted: false,
actionName: 'block', actionName: "block",
@computed @computed
adminWhitelistEnabled() { adminWhitelistEnabled() {
@ -27,51 +27,71 @@ export default Ember.Component.extend({
actionNames(adminWhitelistEnabled) { actionNames(adminWhitelistEnabled) {
if (adminWhitelistEnabled) { if (adminWhitelistEnabled) {
return [ return [
{id: 'block', name: I18n.t('admin.logs.screened_ips.actions.block')}, { id: "block", name: I18n.t("admin.logs.screened_ips.actions.block") },
{id: 'do_nothing', name: I18n.t('admin.logs.screened_ips.actions.do_nothing')}, {
{id: 'allow_admin', name: I18n.t('admin.logs.screened_ips.actions.allow_admin')} id: "do_nothing",
name: I18n.t("admin.logs.screened_ips.actions.do_nothing")
},
{
id: "allow_admin",
name: I18n.t("admin.logs.screened_ips.actions.allow_admin")
}
]; ];
} else { } else {
return [ return [
{id: 'block', name: I18n.t('admin.logs.screened_ips.actions.block')}, { id: "block", name: I18n.t("admin.logs.screened_ips.actions.block") },
{id: 'do_nothing', name: I18n.t('admin.logs.screened_ips.actions.do_nothing')} {
id: "do_nothing",
name: I18n.t("admin.logs.screened_ips.actions.do_nothing")
}
]; ];
} }
}, },
actions: { actions: {
submit() { submit() {
if (!this.get('formSubmitted')) { if (!this.get("formSubmitted")) {
this.set('formSubmitted', true); this.set("formSubmitted", true);
const screenedIpAddress = ScreenedIpAddress.create({ const screenedIpAddress = ScreenedIpAddress.create({
ip_address: this.get('ip_address'), ip_address: this.get("ip_address"),
action_name: this.get('actionName') action_name: this.get("actionName")
});
screenedIpAddress.save().then(result => {
if (result.success) {
this.setProperties({ ip_address: '', formSubmitted: false });
this.sendAction('action', ScreenedIpAddress.create(result.screened_ip_address));
Ember.run.schedule('afterRender', () => this.$('.ip-address-input').focus());
} else {
bootbox.alert(result.errors);
}
}).catch(e => {
this.set('formSubmitted', false);
const msg = (e.jqXHR.responseJSON && e.jqXHR.responseJSON.errors) ?
I18n.t("generic_error_with_reason", {error: e.jqXHR.responseJSON.errors.join('. ')}) :
I18n.t("generic_error");
bootbox.alert(msg, () => this.$('.ip-address-input').focus());
}); });
screenedIpAddress
.save()
.then(result => {
if (result.success) {
this.setProperties({ ip_address: "", formSubmitted: false });
this.sendAction(
"action",
ScreenedIpAddress.create(result.screened_ip_address)
);
Ember.run.schedule("afterRender", () =>
this.$(".ip-address-input").focus()
);
} else {
bootbox.alert(result.errors);
}
})
.catch(e => {
this.set("formSubmitted", false);
const msg =
e.jqXHR.responseJSON && e.jqXHR.responseJSON.errors
? I18n.t("generic_error_with_reason", {
error: e.jqXHR.responseJSON.errors.join(". ")
})
: I18n.t("generic_error");
bootbox.alert(msg, () => this.$(".ip-address-input").focus());
});
} }
} }
}, },
@on("didInsertElement") @on("didInsertElement")
_init() { _init() {
Ember.run.schedule('afterRender', () => { Ember.run.schedule("afterRender", () => {
this.$('.ip-address-input').keydown(e => { this.$(".ip-address-input").keydown(e => {
if (e.keyCode === 13) { if (e.keyCode === 13) {
this.send('submit'); this.send("submit");
} }
}); });
}); });

View file

@ -1,3 +1,3 @@
export default Ember.Component.extend({ export default Ember.Component.extend({
tagName: '' tagName: ""
}); });

View file

@ -1,10 +1,10 @@
import BufferedContent from 'discourse/mixins/buffered-content'; import BufferedContent from "discourse/mixins/buffered-content";
import SiteSetting from 'admin/models/site-setting'; import SiteSetting from "admin/models/site-setting";
import SettingComponent from 'admin/mixins/setting-component'; import SettingComponent from "admin/mixins/setting-component";
export default Ember.Component.extend(BufferedContent, SettingComponent, { export default Ember.Component.extend(BufferedContent, SettingComponent, {
_save() { _save() {
const setting = this.get('buffered'); const setting = this.get("buffered");
return SiteSetting.update(setting.get('setting'), setting.get('value')); return SiteSetting.update(setting.get("setting"), setting.get("value"));
} }
}); });

View file

@ -1,17 +1,17 @@
import computed from "ember-addons/ember-computed-decorators"; import computed from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({ export default Ember.Component.extend({
@computed("value") @computed("value")
enabled: { enabled: {
get(value) { get(value) {
if (Ember.isEmpty(value)) { return false; } if (Ember.isEmpty(value)) {
return false;
}
return value.toString() === "true"; return value.toString() === "true";
}, },
set(value) { set(value) {
this.set("value", value ? "true" : "false"); this.set("value", value ? "true" : "false");
return value; return value;
} }
}, }
}); });

View file

@ -1,7 +1,6 @@
import computed from "ember-addons/ember-computed-decorators"; import computed from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({ export default Ember.Component.extend({
@computed("value") @computed("value")
selectedCategories: { selectedCategories: {
get(value) { get(value) {
@ -12,5 +11,4 @@ export default Ember.Component.extend({
return value; return value;
} }
} }
}); });

View file

@ -1,25 +1,27 @@
import { on } from 'ember-addons/ember-computed-decorators'; import { on } from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: ['site-text'], classNames: ["site-text"],
classNameBindings: ['siteText.overridden'], classNameBindings: ["siteText.overridden"],
@on('didInsertElement') @on("didInsertElement")
highlightTerm() { highlightTerm() {
const term = this.get('term'); const term = this.get("term");
if (term) { if (term) {
this.$('.site-text-id, .site-text-value').highlight(term, {className: 'text-highlight'}); this.$(".site-text-id, .site-text-value").highlight(term, {
className: "text-highlight"
});
} }
this.$('.site-text-value').ellipsis(); this.$(".site-text-value").ellipsis();
}, },
click() { click() {
this.send('edit'); this.send("edit");
}, },
actions: { actions: {
edit() { edit() {
this.sendAction('editAction', this.get('siteText')); this.sendAction("editAction", this.get("siteText"));
} }
} }
}); });

View file

@ -1,20 +1,20 @@
import DiscourseURL from 'discourse/lib/url'; import DiscourseURL from "discourse/lib/url";
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: ['table', 'staff-actions'], classNames: ["table", "staff-actions"],
willDestroyElement() { willDestroyElement() {
this.$().off('click.discourse-staff-logs'); this.$().off("click.discourse-staff-logs");
}, },
didInsertElement() { didInsertElement() {
this._super(); this._super();
this.$().on('click.discourse-staff-logs', '[data-link-post-id]', e => { this.$().on("click.discourse-staff-logs", "[data-link-post-id]", e => {
let postId = $(e.target).attr('data-link-post-id'); let postId = $(e.target).attr("data-link-post-id");
this.store.find('post', postId).then(p => { this.store.find("post", postId).then(p => {
DiscourseURL.routeTo(p.get('url')); DiscourseURL.routeTo(p.get("url"));
}); });
return false; return false;
}); });

View file

@ -1,3 +1,3 @@
export default Ember.Component.extend({ export default Ember.Component.extend({
tagName: '' tagName: ""
}); });

View file

@ -1,9 +1,12 @@
import BufferedContent from 'discourse/mixins/buffered-content'; import BufferedContent from "discourse/mixins/buffered-content";
import SettingComponent from 'admin/mixins/setting-component'; import SettingComponent from "admin/mixins/setting-component";
export default Ember.Component.extend(BufferedContent, SettingComponent, { export default Ember.Component.extend(BufferedContent, SettingComponent, {
layoutName: 'admin/templates/components/site-setting', layoutName: "admin/templates/components/site-setting",
_save() { _save() {
return this.get('model').saveSettings(this.get('setting.setting'), this.get('buffered.value')); return this.get("model").saveSettings(
this.get("setting.setting"),
this.get("buffered.value")
);
} }
}); });

View file

@ -1,5 +1,5 @@
export default Ember.Component.extend({ export default Ember.Component.extend({
classNameBindings: [':value-list'], classNameBindings: [":value-list"],
_enableSorting: function() { _enableSorting: function() {
const self = this; const self = this;
@ -10,16 +10,16 @@ export default Ember.Component.extend({
let over = null; let over = null;
let nodePlacement; let nodePlacement;
this.$().on('dragstart.discourse', '.values .value', function(e) { this.$().on("dragstart.discourse", ".values .value", function(e) {
dragging = e.currentTarget; dragging = e.currentTarget;
e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.effectAllowed = "move";
e.dataTransfer.setData("text/html", e.currentTarget); e.dataTransfer.setData("text/html", e.currentTarget);
}); });
this.$().on('dragend.discourse', '.values .value', function() { this.$().on("dragend.discourse", ".values .value", function() {
Ember.run(function() { Ember.run(function() {
dragging.parentNode.removeChild(placeholder); dragging.parentNode.removeChild(placeholder);
dragging.style.display = 'block'; dragging.style.display = "block";
// Update data // Update data
const from = Number(dragging.dataset.index); const from = Number(dragging.dataset.index);
@ -27,7 +27,7 @@ export default Ember.Component.extend({
if (from < to) to--; if (from < to) to--;
if (nodePlacement === "after") to++; if (nodePlacement === "after") to++;
const collection = self.get('collection'); const collection = self.get("collection");
const fromObj = collection.objectAt(from); const fromObj = collection.objectAt(from);
collection.replace(from, 1); collection.replace(from, 1);
collection.replace(to, 0, [fromObj]); collection.replace(to, 0, [fromObj]);
@ -36,10 +36,12 @@ export default Ember.Component.extend({
return false; return false;
}); });
this.$().on('dragover.discourse', '.values', function(e) { this.$().on("dragover.discourse", ".values", function(e) {
e.preventDefault(); e.preventDefault();
dragging.style.display = 'none'; dragging.style.display = "none";
if (e.target.className === "placeholder") { return; } if (e.target.className === "placeholder") {
return;
}
over = e.target; over = e.target;
const relY = e.originalEvent.clientY - over.offsetTop; const relY = e.originalEvent.clientY - over.offsetTop;
@ -49,54 +51,61 @@ export default Ember.Component.extend({
if (relY > height) { if (relY > height) {
nodePlacement = "after"; nodePlacement = "after";
parent.insertBefore(placeholder, e.target.nextElementSibling); parent.insertBefore(placeholder, e.target.nextElementSibling);
} else if(relY < height) { } else if (relY < height) {
nodePlacement = "before"; nodePlacement = "before";
parent.insertBefore(placeholder, e.target); parent.insertBefore(placeholder, e.target);
} }
}); });
}.on('didInsertElement'), }.on("didInsertElement"),
_removeSorting: function() { _removeSorting: function() {
this.$().off('dragover.discourse').off('dragend.discourse').off('dragstart.discourse'); this.$()
}.on('willDestroyElement'), .off("dragover.discourse")
.off("dragend.discourse")
.off("dragstart.discourse");
}.on("willDestroyElement"),
_setupCollection: function() { _setupCollection: function() {
const values = this.get('values'); const values = this.get("values");
if (this.get('inputType') === "array") { if (this.get("inputType") === "array") {
this.set('collection', values || []); this.set("collection", values || []);
} else { } else {
this.set('collection', (values && values.length) ? values.split("\n") : []); this.set("collection", values && values.length ? values.split("\n") : []);
} }
}.on('init').observes('values'), }
.on("init")
.observes("values"),
_saveValues: function() { _saveValues: function() {
if (this.get('inputType') === "array") { if (this.get("inputType") === "array") {
this.set('values', this.get('collection')); this.set("values", this.get("collection"));
} else { } else {
this.set('values', this.get('collection').join("\n")); this.set("values", this.get("collection").join("\n"));
} }
}, },
inputInvalid: Ember.computed.empty('newValue'), inputInvalid: Ember.computed.empty("newValue"),
keyDown(e) { keyDown(e) {
if (e.keyCode === 13) { if (e.keyCode === 13) {
this.send('addValue'); this.send("addValue");
} }
}, },
actions: { actions: {
addValue() { addValue() {
if (this.get('inputInvalid')) { return; } if (this.get("inputInvalid")) {
return;
}
this.get('collection').addObject(this.get('newValue')); this.get("collection").addObject(this.get("newValue"));
this.set('newValue', ''); this.set("newValue", "");
this._saveValues(); this._saveValues();
}, },
removeValue(value) { removeValue(value) {
const collection = this.get('collection'); const collection = this.get("collection");
collection.removeObject(value); collection.removeObject(value);
this._saveValues(); this._saveValues();
} }

View file

@ -1,65 +1,94 @@
import WatchedWord from 'admin/models/watched-word'; import WatchedWord from "admin/models/watched-word";
import { default as computed, on, observes } from 'ember-addons/ember-computed-decorators'; import {
default as computed,
on,
observes
} from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: ['watched-word-form'], classNames: ["watched-word-form"],
formSubmitted: false, formSubmitted: false,
actionKey: null, actionKey: null,
showMessage: false, showMessage: false,
@computed('regularExpressions') @computed("regularExpressions")
placeholderKey(regularExpressions) { placeholderKey(regularExpressions) {
return "admin.watched_words.form.placeholder" + return (
(regularExpressions ? "_regexp" : ""); "admin.watched_words.form.placeholder" +
(regularExpressions ? "_regexp" : "")
);
}, },
@observes('word') @observes("word")
removeMessage() { removeMessage() {
if (this.get('showMessage') && !Ember.isEmpty(this.get('word'))) { if (this.get("showMessage") && !Ember.isEmpty(this.get("word"))) {
this.set('showMessage', false); this.set("showMessage", false);
} }
}, },
@computed('word') @computed("word")
isUniqueWord(word) { isUniqueWord(word) {
const words = this.get("filteredContent") || []; const words = this.get("filteredContent") || [];
const filtered = words.filter(content => content.action === this.get("actionKey")); const filtered = words.filter(
return filtered.every(content => content.word.toLowerCase() !== word.toLowerCase()); content => content.action === this.get("actionKey")
);
return filtered.every(
content => content.word.toLowerCase() !== word.toLowerCase()
);
}, },
actions: { actions: {
submit() { submit() {
if (!this.get("isUniqueWord")) { if (!this.get("isUniqueWord")) {
this.setProperties({ showMessage: true, message: I18n.t('admin.watched_words.form.exists') }); this.setProperties({
showMessage: true,
message: I18n.t("admin.watched_words.form.exists")
});
return; return;
} }
if (!this.get('formSubmitted')) { if (!this.get("formSubmitted")) {
this.set('formSubmitted', true); this.set("formSubmitted", true);
const watchedWord = WatchedWord.create({ word: this.get('word'), action: this.get('actionKey') }); const watchedWord = WatchedWord.create({
word: this.get("word"),
watchedWord.save().then(result => { action: this.get("actionKey")
this.setProperties({ word: '', formSubmitted: false, showMessage: true, message: I18n.t('admin.watched_words.form.success') });
this.sendAction('action', WatchedWord.create(result));
Ember.run.schedule('afterRender', () => this.$('.watched-word-input').focus());
}).catch(e => {
this.set('formSubmitted', false);
const msg = (e.jqXHR.responseJSON && e.jqXHR.responseJSON.errors) ?
I18n.t("generic_error_with_reason", {error: e.jqXHR.responseJSON.errors.join('. ')}) :
I18n.t("generic_error");
bootbox.alert(msg, () => this.$('.watched-word-input').focus());
}); });
watchedWord
.save()
.then(result => {
this.setProperties({
word: "",
formSubmitted: false,
showMessage: true,
message: I18n.t("admin.watched_words.form.success")
});
this.sendAction("action", WatchedWord.create(result));
Ember.run.schedule("afterRender", () =>
this.$(".watched-word-input").focus()
);
})
.catch(e => {
this.set("formSubmitted", false);
const msg =
e.jqXHR.responseJSON && e.jqXHR.responseJSON.errors
? I18n.t("generic_error_with_reason", {
error: e.jqXHR.responseJSON.errors.join(". ")
})
: I18n.t("generic_error");
bootbox.alert(msg, () => this.$(".watched-word-input").focus());
});
} }
} }
}, },
@on("didInsertElement") @on("didInsertElement")
_init() { _init() {
Ember.run.schedule('afterRender', () => { Ember.run.schedule("afterRender", () => {
this.$('.watched-word-input').keydown(e => { this.$(".watched-word-input").keydown(e => {
if (e.keyCode === 13) { if (e.keyCode === 13) {
this.send('submit'); this.send("submit");
} }
}); });
}); });

View file

@ -2,16 +2,16 @@ import computed from "ember-addons/ember-computed-decorators";
import UploadMixin from "discourse/mixins/upload"; import UploadMixin from "discourse/mixins/upload";
export default Em.Component.extend(UploadMixin, { export default Em.Component.extend(UploadMixin, {
type: 'csv', type: "csv",
classNames: 'watched-words-uploader', classNames: "watched-words-uploader",
uploadUrl: '/admin/logs/watched_words/upload', uploadUrl: "/admin/logs/watched_words/upload",
addDisabled: Em.computed.alias("uploading"), addDisabled: Em.computed.alias("uploading"),
validateUploadedFilesOptions() { validateUploadedFilesOptions() {
return { csvOnly: true }; return { csvOnly: true };
}, },
@computed('actionKey') @computed("actionKey")
data(actionKey) { data(actionKey) {
return { action_key: actionKey }; return { action_key: actionKey };
}, },

View file

@ -1,32 +1,40 @@
import ApiKey from 'admin/models/api-key'; import ApiKey from "admin/models/api-key";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
actions: { actions: {
generateMasterKey() { generateMasterKey() {
ApiKey.generateMasterKey().then(key => this.get('model').pushObject(key)); ApiKey.generateMasterKey().then(key => this.get("model").pushObject(key));
}, },
regenerateKey(key) { regenerateKey(key) {
bootbox.confirm(I18n.t("admin.api.confirm_regen"), I18n.t("no_value"), I18n.t("yes_value"), result => { bootbox.confirm(
if (result) { I18n.t("admin.api.confirm_regen"),
key.regenerate(); I18n.t("no_value"),
I18n.t("yes_value"),
result => {
if (result) {
key.regenerate();
}
} }
}); );
}, },
revokeKey(key) { revokeKey(key) {
bootbox.confirm(I18n.t("admin.api.confirm_revoke"), I18n.t("no_value"), I18n.t("yes_value"), result => { bootbox.confirm(
if (result) { I18n.t("admin.api.confirm_revoke"),
key.revoke().then(() => this.get('model').removeObject(key)); I18n.t("no_value"),
I18n.t("yes_value"),
result => {
if (result) {
key.revoke().then(() => this.get("model").removeObject(key));
}
} }
}); );
} }
}, },
// Has a master key already been generated? // Has a master key already been generated?
hasMasterKey: function() { hasMasterKey: function() {
return !!this.get('model').findBy('user', null); return !!this.get("model").findBy("user", null);
}.property('model.[]') }.property("model.[]")
}); });

View file

@ -1,13 +1,15 @@
import { ajax } from 'discourse/lib/ajax'; import { ajax } from "discourse/lib/ajax";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
adminBackups: Ember.inject.controller(), adminBackups: Ember.inject.controller(),
status: Ember.computed.alias('adminBackups.model'), status: Ember.computed.alias("adminBackups.model"),
uploadLabel: function() { return I18n.t("admin.backups.upload.label"); }.property(), uploadLabel: function() {
return I18n.t("admin.backups.upload.label");
}.property(),
restoreTitle: function() { restoreTitle: function() {
if (!this.get('status.allowRestore')) { if (!this.get("status.allowRestore")) {
return "admin.backups.operations.restore.is_disabled"; return "admin.backups.operations.restore.is_disabled";
} else if (this.get("status.isOperationRunning")) { } else if (this.get("status.isOperationRunning")) {
return "admin.backups.operations.is_running"; return "admin.backups.operations.is_running";
@ -17,7 +19,6 @@ export default Ember.Controller.extend({
}.property("status.{allowRestore,isOperationRunning}"), }.property("status.{allowRestore,isOperationRunning}"),
actions: { actions: {
toggleReadOnlyMode() { toggleReadOnlyMode() {
var self = this; var self = this;
if (!this.site.get("isReadOnly")) { if (!this.site.get("isReadOnly")) {
@ -38,9 +39,8 @@ export default Ember.Controller.extend({
}, },
download(backup) { download(backup) {
let link = backup.get('filename'); let link = backup.get("filename");
ajax("/admin/backups/" + link, { type: "PUT" }) ajax("/admin/backups/" + link, { type: "PUT" }).then(() => {
.then(() => {
bootbox.alert(I18n.t("admin.backups.operations.download.alert")); bootbox.alert(I18n.t("admin.backups.operations.download.alert"));
}); });
} }

View file

@ -1,5 +1,9 @@
export default Ember.Controller.extend({ export default Ember.Controller.extend({
noOperationIsRunning: Ember.computed.not("model.isOperationRunning"), noOperationIsRunning: Ember.computed.not("model.isOperationRunning"),
rollbackEnabled: Ember.computed.and("model.canRollback", "model.restoreEnabled", "noOperationIsRunning"), rollbackEnabled: Ember.computed.and(
"model.canRollback",
"model.restoreEnabled",
"noOperationIsRunning"
),
rollbackDisabled: Ember.computed.not("rollbackEnabled") rollbackDisabled: Ember.computed.not("rollbackEnabled")
}); });

View file

@ -1,108 +1,139 @@
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
import BufferedContent from 'discourse/mixins/buffered-content'; import BufferedContent from "discourse/mixins/buffered-content";
import { propertyNotEqual } from 'discourse/lib/computed'; import { propertyNotEqual } from "discourse/lib/computed";
export default Ember.Controller.extend(BufferedContent, { export default Ember.Controller.extend(BufferedContent, {
adminBadges: Ember.inject.controller(), adminBadges: Ember.inject.controller(),
saving: false, saving: false,
savingStatus: '', savingStatus: "",
badgeTypes: Ember.computed.alias('adminBadges.badgeTypes'), badgeTypes: Ember.computed.alias("adminBadges.badgeTypes"),
badgeGroupings: Ember.computed.alias('adminBadges.badgeGroupings'), badgeGroupings: Ember.computed.alias("adminBadges.badgeGroupings"),
badgeTriggers: Ember.computed.alias('adminBadges.badgeTriggers'), badgeTriggers: Ember.computed.alias("adminBadges.badgeTriggers"),
protectedSystemFields: Ember.computed.alias('adminBadges.protectedSystemFields'), protectedSystemFields: Ember.computed.alias(
"adminBadges.protectedSystemFields"
),
readOnly: Ember.computed.alias('buffered.system'), readOnly: Ember.computed.alias("buffered.system"),
showDisplayName: propertyNotEqual('name', 'displayName'), showDisplayName: propertyNotEqual("name", "displayName"),
hasQuery: function() { hasQuery: function() {
const bQuery = this.get('buffered.query'); const bQuery = this.get("buffered.query");
if (bQuery) { if (bQuery) {
return bQuery.trim().length > 0; return bQuery.trim().length > 0;
} }
const mQuery = this.get('model.query'); const mQuery = this.get("model.query");
return mQuery && mQuery.trim().length > 0; return mQuery && mQuery.trim().length > 0;
}.property('model.query', 'buffered.query'), }.property("model.query", "buffered.query"),
_resetSaving: function() { _resetSaving: function() {
this.set('saving', false); this.set("saving", false);
this.set('savingStatus', ''); this.set("savingStatus", "");
}.observes('model.id'), }.observes("model.id"),
actions: { actions: {
save() { save() {
if (!this.get('saving')) { if (!this.get("saving")) {
let fields = ['allow_title', 'multiple_grant', let fields = [
'listable', 'auto_revoke', "allow_title",
'enabled', 'show_posts', "multiple_grant",
'target_posts', 'name', 'description', "listable",
'long_description', "auto_revoke",
'icon', 'image', 'query', 'badge_grouping_id', "enabled",
'trigger', 'badge_type_id']; "show_posts",
"target_posts",
"name",
"description",
"long_description",
"icon",
"image",
"query",
"badge_grouping_id",
"trigger",
"badge_type_id"
];
if (this.get('buffered.system')){ if (this.get("buffered.system")) {
var protectedFields = this.get('protectedSystemFields'); var protectedFields = this.get("protectedSystemFields");
fields = _.filter(fields, function(f){ fields = _.filter(fields, function(f) {
return !_.include(protectedFields,f); return !_.include(protectedFields, f);
}); });
} }
this.set('saving', true); this.set("saving", true);
this.set('savingStatus', I18n.t('saving')); this.set("savingStatus", I18n.t("saving"));
const boolFields = ['allow_title', 'multiple_grant', const boolFields = [
'listable', 'auto_revoke', "allow_title",
'enabled', 'show_posts', "multiple_grant",
'target_posts' ]; "listable",
"auto_revoke",
"enabled",
"show_posts",
"target_posts"
];
const data = {}; const data = {};
const buffered = this.get('buffered'); const buffered = this.get("buffered");
fields.forEach(function(field){ fields.forEach(function(field) {
var d = buffered.get(field); var d = buffered.get(field);
if (_.include(boolFields, field)) { d = !!d; } if (_.include(boolFields, field)) {
d = !!d;
}
data[field] = d; data[field] = d;
}); });
const newBadge = !this.get('id'); const newBadge = !this.get("id");
const model = this.get('model'); const model = this.get("model");
this.get('model').save(data).then(() => { this.get("model")
if (newBadge) { .save(data)
const adminBadges = this.get('adminBadges.model'); .then(() => {
if (!adminBadges.includes(model)) { if (newBadge) {
adminBadges.pushObject(model); const adminBadges = this.get("adminBadges.model");
if (!adminBadges.includes(model)) {
adminBadges.pushObject(model);
}
this.transitionToRoute("adminBadges.show", model.get("id"));
} else {
this.commitBuffer();
this.set("savingStatus", I18n.t("saved"));
} }
this.transitionToRoute('adminBadges.show', model.get('id')); })
} else { .catch(popupAjaxError)
this.commitBuffer(); .finally(() => {
this.set('savingStatus', I18n.t('saved')); this.set("saving", false);
} this.set("savingStatus", "");
});
}).catch(popupAjaxError).finally(() => {
this.set('saving', false);
this.set('savingStatus', '');
});
} }
}, },
destroy() { destroy() {
const adminBadges = this.get('adminBadges.model'); const adminBadges = this.get("adminBadges.model");
const model = this.get('model'); const model = this.get("model");
if (!model.get('id')) { if (!model.get("id")) {
this.transitionToRoute('adminBadges.index'); this.transitionToRoute("adminBadges.index");
return; return;
} }
return bootbox.confirm(I18n.t("admin.badges.delete_confirm"), I18n.t("no_value"), I18n.t("yes_value"), result => { return bootbox.confirm(
if (result) { I18n.t("admin.badges.delete_confirm"),
model.destroy().then(() => { I18n.t("no_value"),
adminBadges.removeObject(model); I18n.t("yes_value"),
this.transitionToRoute('adminBadges.index'); result => {
}).catch(() => { if (result) {
bootbox.alert(I18n.t('generic_error')); model
}); .destroy()
.then(() => {
adminBadges.removeObject(model);
this.transitionToRoute("adminBadges.index");
})
.catch(() => {
bootbox.alert(I18n.t("generic_error"));
});
}
} }
}); );
} }
} }
}); });

View file

@ -1,7 +1,7 @@
import computed from 'ember-addons/ember-computed-decorators'; import computed from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
@computed("model.colors","onlyOverridden") @computed("model.colors", "onlyOverridden")
colors(allColors, onlyOverridden) { colors(allColors, onlyOverridden) {
if (onlyOverridden) { if (onlyOverridden) {
return allColors.filter(color => color.get("overridden")); return allColors.filter(color => color.get("overridden"));
@ -11,7 +11,6 @@ export default Ember.Controller.extend({
}, },
actions: { actions: {
revert: function(color) { revert: function(color) {
color.revert(); color.revert();
}, },
@ -28,14 +27,20 @@ export default Ember.Controller.extend({
let range = document.createRange(); let range = document.createRange();
range.selectNode(area[0]); range.selectNode(area[0]);
window.getSelection().addRange(range); window.getSelection().addRange(range);
let successful = document.execCommand('copy'); let successful = document.execCommand("copy");
if (successful) { if (successful) {
this.set("model.savingStatus", I18n.t("admin.customize.copied_to_clipboard")); this.set(
"model.savingStatus",
I18n.t("admin.customize.copied_to_clipboard")
);
} else { } else {
this.set("model.savingStatus", I18n.t("admin.customize.copy_to_clipboard_error")); this.set(
"model.savingStatus",
I18n.t("admin.customize.copy_to_clipboard_error")
);
} }
setTimeout(()=>{ setTimeout(() => {
this.set("model.savingStatus", null); this.set("model.savingStatus", null);
}, 2000); }, 2000);
@ -46,29 +51,38 @@ export default Ember.Controller.extend({
}, },
copy() { copy() {
var newColorScheme = Em.copy(this.get('model'), true); var newColorScheme = Em.copy(this.get("model"), true);
newColorScheme.set('name', I18n.t('admin.customize.colors.copy_name_prefix') + ' ' + this.get('model.name')); newColorScheme.set(
newColorScheme.save().then(()=>{ "name",
this.get('allColors').pushObject(newColorScheme); I18n.t("admin.customize.colors.copy_name_prefix") +
this.replaceRoute('adminCustomize.colors.show', newColorScheme); " " +
this.get("model.name")
);
newColorScheme.save().then(() => {
this.get("allColors").pushObject(newColorScheme);
this.replaceRoute("adminCustomize.colors.show", newColorScheme);
}); });
}, },
save: function() { save: function() {
this.get('model').save(); this.get("model").save();
}, },
destroy: function() { destroy: function() {
const model = this.get("model");
const model = this.get('model'); return bootbox.confirm(
return bootbox.confirm(I18n.t("admin.customize.colors.delete_confirm"), I18n.t("no_value"), I18n.t("yes_value"), result => { I18n.t("admin.customize.colors.delete_confirm"),
if (result) { I18n.t("no_value"),
model.destroy().then(()=>{ I18n.t("yes_value"),
this.get('allColors').removeObject(model); result => {
this.replaceRoute('adminCustomize.colors'); if (result) {
}); model.destroy().then(() => {
this.get("allColors").removeObject(model);
this.replaceRoute("adminCustomize.colors");
});
}
} }
}); );
} }
} }
}); });

View file

@ -1,41 +1,43 @@
import showModal from 'discourse/lib/show-modal'; import showModal from "discourse/lib/show-modal";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
baseColorScheme: function() { baseColorScheme: function() {
return this.get('model').findBy('is_base', true); return this.get("model").findBy("is_base", true);
}.property('model.@each.id'), }.property("model.@each.id"),
baseColorSchemes: function() { baseColorSchemes: function() {
return this.get('model').filterBy('is_base', true); return this.get("model").filterBy("is_base", true);
}.property('model.@each.id'), }.property("model.@each.id"),
baseColors: function() { baseColors: function() {
var baseColorsHash = Em.Object.create({}); var baseColorsHash = Em.Object.create({});
_.each(this.get('baseColorScheme.colors'), function(color){ _.each(this.get("baseColorScheme.colors"), function(color) {
baseColorsHash.set(color.get('name'), color); baseColorsHash.set(color.get("name"), color);
}); });
return baseColorsHash; return baseColorsHash;
}.property('baseColorScheme'), }.property("baseColorScheme"),
actions: { actions: {
newColorSchemeWithBase(baseKey) { newColorSchemeWithBase(baseKey) {
const base = this.get('baseColorSchemes').findBy('base_scheme_id', baseKey); const base = this.get("baseColorSchemes").findBy(
"base_scheme_id",
baseKey
);
const newColorScheme = Em.copy(base, true); const newColorScheme = Em.copy(base, true);
newColorScheme.set('name', I18n.t('admin.customize.colors.new_name')); newColorScheme.set("name", I18n.t("admin.customize.colors.new_name"));
newColorScheme.set('base_scheme_id', base.get('base_scheme_id')); newColorScheme.set("base_scheme_id", base.get("base_scheme_id"));
newColorScheme.save().then(()=>{ newColorScheme.save().then(() => {
this.get('model').pushObject(newColorScheme); this.get("model").pushObject(newColorScheme);
newColorScheme.set('savingStatus', null); newColorScheme.set("savingStatus", null);
this.replaceRoute('adminCustomize.colors.show', newColorScheme); this.replaceRoute("adminCustomize.colors.show", newColorScheme);
}); });
}, },
newColorScheme() { newColorScheme() {
showModal('admin-color-scheme-select-base', { model: this.get('baseColorSchemes'), admin: true}); showModal("admin-color-scheme-select-base", {
}, model: this.get("baseColorSchemes"),
admin: true
});
}
} }
}); });

View file

@ -1,38 +1,47 @@
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
import { bufferedProperty } from 'discourse/mixins/buffered-content'; import { bufferedProperty } from "discourse/mixins/buffered-content";
export default Ember.Controller.extend(bufferedProperty('emailTemplate'), { export default Ember.Controller.extend(bufferedProperty("emailTemplate"), {
saved: false, saved: false,
hasMultipleSubjects: function() { hasMultipleSubjects: function() {
const buffered = this.get('buffered'); const buffered = this.get("buffered");
if (buffered.getProperties('subject')['subject']) { if (buffered.getProperties("subject")["subject"]) {
return false; return false;
} else { } else {
return buffered.getProperties('id')['id']; return buffered.getProperties("id")["id"];
} }
}.property("buffered"), }.property("buffered"),
actions: { actions: {
saveChanges() { saveChanges() {
this.set('saved', false); this.set("saved", false);
const buffered = this.get('buffered'); const buffered = this.get("buffered");
this.get('emailTemplate').save(buffered.getProperties('subject', 'body')).then(() => { this.get("emailTemplate")
this.set('saved', true); .save(buffered.getProperties("subject", "body"))
}).catch(popupAjaxError); .then(() => {
this.set("saved", true);
})
.catch(popupAjaxError);
}, },
revertChanges() { revertChanges() {
this.set('saved', false); this.set("saved", false);
bootbox.confirm(I18n.t('admin.customize.email_templates.revert_confirm'), result => { bootbox.confirm(
if (result) { I18n.t("admin.customize.email_templates.revert_confirm"),
this.get('emailTemplate').revert().then(props => { result => {
const buffered = this.get('buffered'); if (result) {
buffered.setProperties(props); this.get("emailTemplate")
this.commitBuffer(); .revert()
}).catch(popupAjaxError); .then(props => {
const buffered = this.get("buffered");
buffered.setProperties(props);
this.commitBuffer();
})
.catch(popupAjaxError);
}
} }
}); );
} }
} }
}); });

View file

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

View file

@ -1,66 +1,91 @@
import { url } from 'discourse/lib/computed'; import { url } from "discourse/lib/computed";
import { default as computed, observes } from 'ember-addons/ember-computed-decorators'; import {
default as computed,
observes
} from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
maximized: false, maximized: false,
section: null, section: null,
editRouteName: 'adminCustomizeThemes.edit', editRouteName: "adminCustomizeThemes.edit",
targets: [ targets: [
{ id: 0, name: 'common' }, { id: 0, name: "common" },
{ id: 1, name: 'desktop' }, { id: 1, name: "desktop" },
{ id: 2, name: 'mobile' }, { id: 2, name: "mobile" },
{ id: 3, name: 'settings' } { id: 3, name: "settings" }
], ],
fieldsForTarget: function (target) { fieldsForTarget: function(target) {
const common = ["scss", "head_tag", "header", "after_header", "body_tag", "footer"]; const common = [
switch(target) { "scss",
case "common": return [...common, "embedded_scss"]; "head_tag",
case "desktop": return common; "header",
case "mobile": return common; "after_header",
case "settings": return ["yaml"]; "body_tag",
"footer"
];
switch (target) {
case "common":
return [...common, "embedded_scss"];
case "desktop":
return common;
case "mobile":
return common;
case "settings":
return ["yaml"];
} }
}, },
@computed('onlyOverridden') @computed("onlyOverridden")
showCommon() { showCommon() {
return this.shouldShow('common'); return this.shouldShow("common");
}, },
@computed('onlyOverridden') @computed("onlyOverridden")
showDesktop() { showDesktop() {
return this.shouldShow('desktop'); return this.shouldShow("desktop");
}, },
@computed('onlyOverridden') @computed("onlyOverridden")
showMobile() { showMobile() {
return this.shouldShow('mobile'); return this.shouldShow("mobile");
}, },
@computed('onlyOverridden', 'model.remote_theme') @computed("onlyOverridden", "model.remote_theme")
showSettings() { showSettings() {
return false; return false;
}, },
@observes('onlyOverridden') @observes("onlyOverridden")
onlyOverriddenChanged() { onlyOverriddenChanged() {
if (this.get('onlyOverridden')) { if (this.get("onlyOverridden")) {
if (!this.get('model').hasEdited(this.get('currentTargetName'), this.get('fieldName'))) { if (
let target = (this.get('showCommon') && 'common') || !this.get("model").hasEdited(
(this.get('showDesktop') && 'desktop') || this.get("currentTargetName"),
(this.get('showMobile') && 'mobile'); this.get("fieldName")
)
) {
let target =
(this.get("showCommon") && "common") ||
(this.get("showDesktop") && "desktop") ||
(this.get("showMobile") && "mobile");
let fields = this.get('model.theme_fields'); let fields = this.get("model.theme_fields");
let field = fields && fields.find(f => (f.target === target)); let field = fields && fields.find(f => f.target === target);
this.replaceRoute(this.get('editRouteName'), this.get('model.id'), target, field && field.name); this.replaceRoute(
this.get("editRouteName"),
this.get("model.id"),
target,
field && field.name
);
} }
} }
}, },
shouldShow(target){ shouldShow(target) {
if(!this.get("onlyOverridden")) { if (!this.get("onlyOverridden")) {
return true; return true;
} }
return this.get("model").hasEdited(target); return this.get("model").hasEdited(target);
@ -69,13 +94,13 @@ export default Ember.Controller.extend({
currentTarget: 0, currentTarget: 0,
setTargetName: function(name) { setTargetName: function(name) {
const target = this.get('targets').find(t => t.name === name); const target = this.get("targets").find(t => t.name === name);
this.set("currentTarget", target && target.id); this.set("currentTarget", target && target.id);
}, },
@computed("currentTarget") @computed("currentTarget")
currentTargetName(id) { currentTargetName(id) {
const target = this.get('targets').find(t => t.id === parseInt(id, 10)); const target = this.get("targets").find(t => t.id === parseInt(id, 10));
return target && target.name; return target && target.name;
}, },
@ -87,7 +112,7 @@ export default Ember.Controller.extend({
@computed("currentTargetName", "fieldName", "saving") @computed("currentTargetName", "fieldName", "saving")
error(target, fieldName) { error(target, fieldName) {
return this.get('model').getError(target, fieldName); return this.get("model").getError(target, fieldName);
}, },
@computed("fieldName", "currentTargetName") @computed("fieldName", "currentTargetName")
@ -116,9 +141,9 @@ export default Ember.Controller.extend({
fields = fields.filter(name => model.hasEdited(targetName, name)); fields = fields.filter(name => model.hasEdited(targetName, name));
} }
return fields.map(name=>{ return fields.map(name => {
let hash = { let hash = {
key: (`admin.customize.theme.${name}.text`), key: `admin.customize.theme.${name}.text`,
name: name name: name
}; };
@ -132,30 +157,36 @@ export default Ember.Controller.extend({
}); });
}, },
previewUrl: url('model.id', '/admin/themes/%@/preview'), previewUrl: url("model.id", "/admin/themes/%@/preview"),
maximizeIcon: function() { maximizeIcon: function() {
return this.get('maximized') ? 'compress' : 'expand'; return this.get("maximized") ? "compress" : "expand";
}.property('maximized'), }.property("maximized"),
saveButtonText: function() { saveButtonText: function() {
return this.get('model.isSaving') ? I18n.t('saving') : I18n.t('admin.customize.save'); return this.get("model.isSaving")
}.property('model.isSaving'), ? I18n.t("saving")
: I18n.t("admin.customize.save");
}.property("model.isSaving"),
saveDisabled: function() { saveDisabled: function() {
return !this.get('model.changed') || this.get('model.isSaving'); return !this.get("model.changed") || this.get("model.isSaving");
}.property('model.changed', 'model.isSaving'), }.property("model.changed", "model.isSaving"),
actions: { actions: {
save() { save() {
this.set('saving', true); this.set("saving", true);
this.get('model').saveChanges("theme_fields").finally(()=>{this.set('saving', false);}); this.get("model")
.saveChanges("theme_fields")
.finally(() => {
this.set("saving", false);
});
}, },
toggleMaximize: function() { toggleMaximize: function() {
this.toggleProperty('maximized'); this.toggleProperty("maximized");
Em.run.next(()=>{ Em.run.next(() => {
this.appEvents.trigger('ace:resize'); this.appEvents.trigger("ace:resize");
}); });
} }
} }

View file

@ -1,63 +1,72 @@
import { default as computed } from 'ember-addons/ember-computed-decorators'; import { default as computed } from "ember-addons/ember-computed-decorators";
import { url } from 'discourse/lib/computed'; import { url } from "discourse/lib/computed";
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
import showModal from 'discourse/lib/show-modal'; import showModal from "discourse/lib/show-modal";
import ThemeSettings from 'admin/models/theme-settings'; import ThemeSettings from "admin/models/theme-settings";
const THEME_UPLOAD_VAR = 2; const THEME_UPLOAD_VAR = 2;
export default Ember.Controller.extend({ export default Ember.Controller.extend({
editRouteName: "adminCustomizeThemes.edit",
editRouteName: 'adminCustomizeThemes.edit',
@computed("model", "allThemes") @computed("model", "allThemes")
parentThemes(model, allThemes) { parentThemes(model, allThemes) {
let parents = allThemes.filter(theme => let parents = allThemes.filter(theme =>
_.contains(theme.get("childThemes"), model)); _.contains(theme.get("childThemes"), model)
);
return parents.length === 0 ? null : parents; return parents.length === 0 ? null : parents;
}, },
@computed("model.theme_fields.@each") @computed("model.theme_fields.@each")
hasEditedFields(fields) { hasEditedFields(fields) {
return fields.any(f=>!Em.isBlank(f.value)); return fields.any(f => !Em.isBlank(f.value));
}, },
@computed('model.theme_fields.@each') @computed("model.theme_fields.@each")
editedDescriptions(fields) { editedDescriptions(fields) {
let descriptions = []; let descriptions = [];
let description = target => { let description = target => {
let current = fields.filter(field => field.target === target && !Em.isBlank(field.value)); let current = fields.filter(
field => field.target === target && !Em.isBlank(field.value)
);
if (current.length > 0) { if (current.length > 0) {
let text = I18n.t('admin.customize.theme.'+target); let text = I18n.t("admin.customize.theme." + target);
let localized = current.map(f=>I18n.t('admin.customize.theme.'+f.name + '.text')); let localized = current.map(f =>
I18n.t("admin.customize.theme." + f.name + ".text")
);
return text + ": " + localized.join(" , "); return text + ": " + localized.join(" , ");
} }
}; };
['common', 'desktop', 'mobile'].forEach(target => { ["common", "desktop", "mobile"].forEach(target => {
descriptions.push(description(target)); descriptions.push(description(target));
}); });
return descriptions.reject(d=>Em.isBlank(d)); return descriptions.reject(d => Em.isBlank(d));
}, },
previewUrl: url('model.id', '/admin/themes/%@/preview'), previewUrl: url("model.id", "/admin/themes/%@/preview"),
@computed("colorSchemeId", "model.color_scheme_id") @computed("colorSchemeId", "model.color_scheme_id")
colorSchemeChanged(colorSchemeId, existingId) { colorSchemeChanged(colorSchemeId, existingId) {
colorSchemeId = colorSchemeId === null ? null : parseInt(colorSchemeId); colorSchemeId = colorSchemeId === null ? null : parseInt(colorSchemeId);
return colorSchemeId !== existingId; return colorSchemeId !== existingId;
}, },
@computed("availableChildThemes", "model.childThemes.@each", "model", "allowChildThemes") @computed(
"availableChildThemes",
"model.childThemes.@each",
"model",
"allowChildThemes"
)
selectableChildThemes(available, childThemes, model, allowChildThemes) { selectableChildThemes(available, childThemes, model, allowChildThemes) {
if (!allowChildThemes && (!childThemes || childThemes.length === 0)) { if (!allowChildThemes && (!childThemes || childThemes.length === 0)) {
return null; return null;
} }
let themes = []; let themes = [];
available.forEach(t=> { available.forEach(t => {
if (!childThemes || (childThemes.indexOf(t) === -1)) { if (!childThemes || childThemes.indexOf(t) === -1) {
themes.push(t); themes.push(t);
}; }
}); });
return themes.length === 0 ? null : themes; return themes.length === 0 ? null : themes;
}, },
@ -90,44 +99,48 @@ export default Ember.Controller.extend({
return settings.length > 0; return settings.length > 0;
}, },
downloadUrl: url('model.id', '/admin/themes/%@'), downloadUrl: url("model.id", "/admin/themes/%@"),
actions: { actions: {
updateToLatest() { updateToLatest() {
this.set("updatingRemote", true); this.set("updatingRemote", true);
this.get("model").updateToLatest() this.get("model")
.updateToLatest()
.catch(popupAjaxError) .catch(popupAjaxError)
.finally(()=>{ .finally(() => {
this.set("updatingRemote", false); this.set("updatingRemote", false);
}); });
}, },
checkForThemeUpdates() { checkForThemeUpdates() {
this.set("updatingRemote", true); this.set("updatingRemote", true);
this.get("model").checkForUpdates() this.get("model")
.checkForUpdates()
.catch(popupAjaxError) .catch(popupAjaxError)
.finally(()=>{ .finally(() => {
this.set("updatingRemote", false); this.set("updatingRemote", false);
}); });
}, },
addUploadModal() { addUploadModal() {
showModal('admin-add-upload', {admin: true, name: ''}); showModal("admin-add-upload", { admin: true, name: "" });
}, },
addUpload(info) { addUpload(info) {
let model = this.get("model"); let model = this.get("model");
model.setField('common', info.name, '', info.upload_id, THEME_UPLOAD_VAR); model.setField("common", info.name, "", info.upload_id, THEME_UPLOAD_VAR);
model.saveChanges('theme_fields').catch(e => popupAjaxError(e)); model.saveChanges("theme_fields").catch(e => popupAjaxError(e));
}, },
cancelChangeScheme() { cancelChangeScheme() {
this.set("colorSchemeId", this.get("model.color_scheme_id")); this.set("colorSchemeId", this.get("model.color_scheme_id"));
}, },
changeScheme(){ changeScheme() {
let schemeId = this.get("colorSchemeId"); let schemeId = this.get("colorSchemeId");
this.set("model.color_scheme_id", schemeId === null ? null : parseInt(schemeId)); this.set(
"model.color_scheme_id",
schemeId === null ? null : parseInt(schemeId)
);
this.get("model").saveChanges("color_scheme_id"); this.get("model").saveChanges("color_scheme_id");
}, },
startEditingName() { startEditingName() {
@ -144,14 +157,23 @@ export default Ember.Controller.extend({
}, },
editTheme() { editTheme() {
let edit = ()=>this.transitionToRoute(this.get('editRouteName'), this.get('model.id'), 'common', 'scss'); let edit = () =>
this.transitionToRoute(
this.get("editRouteName"),
this.get("model.id"),
"common",
"scss"
);
if (this.get("model.remote_theme")) { if (this.get("model.remote_theme")) {
bootbox.confirm(I18n.t("admin.customize.theme.edit_confirm"), result => { bootbox.confirm(
if (result) { I18n.t("admin.customize.theme.edit_confirm"),
edit(); result => {
} if (result) {
}); edit();
}
}
);
} else { } else {
edit(); edit();
} }
@ -159,10 +181,10 @@ export default Ember.Controller.extend({
applyDefault() { applyDefault() {
const model = this.get("model"); const model = this.get("model");
model.saveChanges("default").then(()=>{ model.saveChanges("default").then(() => {
if (model.get("default")) { if (model.get("default")) {
this.get("allThemes").forEach(theme=>{ this.get("allThemes").forEach(theme => {
if (theme !== model && theme.get('default')) { if (theme !== model && theme.get("default")) {
theme.set("default", false); theme.set("default", false);
} }
}); });
@ -182,13 +204,15 @@ export default Ember.Controller.extend({
removeUpload(upload) { removeUpload(upload) {
return bootbox.confirm( return bootbox.confirm(
I18n.t("admin.customize.theme.delete_upload_confirm"), I18n.t("admin.customize.theme.delete_upload_confirm"),
I18n.t("no_value"), I18n.t("no_value"),
I18n.t("yes_value"), result => { I18n.t("yes_value"),
if (result) { result => {
this.get("model").removeField(upload); if (result) {
} this.get("model").removeField(upload);
}); }
}
);
}, },
removeChildTheme(theme) { removeChildTheme(theme) {
@ -196,17 +220,20 @@ export default Ember.Controller.extend({
}, },
destroy() { destroy() {
return bootbox.confirm(I18n.t("admin.customize.delete_confirm"), I18n.t("no_value"), I18n.t("yes_value"), result => { return bootbox.confirm(
if (result) { I18n.t("admin.customize.delete_confirm"),
const model = this.get('model'); I18n.t("no_value"),
model.destroyRecord().then(() => { I18n.t("yes_value"),
this.get('allThemes').removeObject(model); result => {
this.transitionToRoute('adminCustomizeThemes'); if (result) {
}); const model = this.get("model");
model.destroyRecord().then(() => {
this.get("allThemes").removeObject(model);
this.transitionToRoute("adminCustomizeThemes");
});
}
} }
}); );
}, }
} }
}); });

View file

@ -1,10 +1,14 @@
import { default as computed } from 'ember-addons/ember-computed-decorators'; import { default as computed } from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
@computed('model', 'model.@each') @computed("model", "model.@each")
sortedThemes(themes) { sortedThemes(themes) {
return _.sortBy(themes.content, t => { return _.sortBy(themes.content, t => {
return [!t.get("default"), !t.get("user_selectable"), t.get("name").toLowerCase()]; return [
!t.get("default"),
!t.get("user_selectable"),
t.get("name").toLowerCase()
];
}); });
} }
}); });

View file

@ -26,31 +26,46 @@ export default Ember.Controller.extend({
fetchDashboard() { fetchDashboard() {
if (this.get("isLoading")) return; if (this.get("isLoading")) return;
if (!this.get("dashboardFetchedAt") || moment().subtract(30, "minutes").toDate() > this.get("dashboardFetchedAt")) { if (
!this.get("dashboardFetchedAt") ||
moment()
.subtract(30, "minutes")
.toDate() > this.get("dashboardFetchedAt")
) {
this.set("isLoading", true); this.set("isLoading", true);
const versionChecks = this.siteSettings.version_checks; const versionChecks = this.siteSettings.version_checks;
AdminDashboardNext.find().then(adminDashboardNextModel => { AdminDashboardNext.find()
.then(adminDashboardNextModel => {
if (versionChecks) {
this.set(
"versionCheck",
VersionCheck.create(adminDashboardNextModel.version_check)
);
}
if (versionChecks) { this.setProperties({
this.set("versionCheck", VersionCheck.create(adminDashboardNextModel.version_check)); dashboardFetchedAt: new Date(),
} model: adminDashboardNextModel,
reports: adminDashboardNextModel.reports.map(x => Report.create(x))
this.setProperties({ });
dashboardFetchedAt: new Date(), })
model: adminDashboardNextModel, .catch(e => {
reports: adminDashboardNextModel.reports.map(x => Report.create(x)) this.get("exceptionController").set("thrown", e.jqXHR);
this.replaceRoute("exception");
})
.finally(() => {
this.set("isLoading", false);
}); });
}).catch(e => {
this.get("exceptionController").set("thrown", e.jqXHR);
this.replaceRoute("exception");
}).finally(() => {
this.set("isLoading", false);
});
} }
if (!this.get("problemsFetchedAt") || moment().subtract(PROBLEMS_CHECK_MINUTES, "minutes").toDate() > this.get("problemsFetchedAt")) { if (
!this.get("problemsFetchedAt") ||
moment()
.subtract(PROBLEMS_CHECK_MINUTES, "minutes")
.toDate() > this.get("problemsFetchedAt")
) {
this.loadProblems(); this.loadProblems();
} }
}, },
@ -58,21 +73,28 @@ export default Ember.Controller.extend({
loadProblems() { loadProblems() {
this.set("loadingProblems", true); this.set("loadingProblems", true);
this.set("problemsFetchedAt", new Date()); this.set("problemsFetchedAt", new Date());
AdminDashboardNext.fetchProblems().then(d => { AdminDashboardNext.fetchProblems()
this.set("problems", d.problems); .then(d => {
}).finally(() => { this.set("problems", d.problems);
this.set("loadingProblems", false); })
}); .finally(() => {
this.set("loadingProblems", false);
});
}, },
@computed("problemsFetchedAt") @computed("problemsFetchedAt")
problemsTimestamp(problemsFetchedAt) { problemsTimestamp(problemsFetchedAt) {
return moment(problemsFetchedAt).locale("en").format("LLL"); return moment(problemsFetchedAt)
.locale("en")
.format("LLL");
}, },
@computed("period") @computed("period")
startDate(period) { startDate(period) {
let fullDay = moment().locale("en").utc().subtract(1, "day"); let fullDay = moment()
.locale("en")
.utc()
.subtract(1, "day");
switch (period) { switch (period) {
case "yearly": case "yearly":
@ -94,12 +116,20 @@ export default Ember.Controller.extend({
@computed() @computed()
lastWeek() { lastWeek() {
return moment().locale("en").utc().endOf("day").subtract(1, "week"); return moment()
.locale("en")
.utc()
.endOf("day")
.subtract(1, "week");
}, },
@computed() @computed()
endDate() { endDate() {
return moment().locale("en").utc().subtract(1, "day").endOf("day"); return moment()
.locale("en")
.utc()
.subtract(1, "day")
.endOf("day");
}, },
@computed("model.attributes.updated_at") @computed("model.attributes.updated_at")
@ -118,7 +148,7 @@ export default Ember.Controller.extend({
}, },
refreshProblems() { refreshProblems() {
this.loadProblems(); this.loadProblems();
}, }
}, },
_reportsForPeriodURL(period) { _reportsForPeriodURL(period) {

View file

@ -1,50 +1,74 @@
import AdminDashboard from 'admin/models/admin-dashboard'; import AdminDashboard from "admin/models/admin-dashboard";
import Report from 'admin/models/report'; import Report from "admin/models/report";
import AdminUser from 'admin/models/admin-user'; import AdminUser from "admin/models/admin-user";
import computed from 'ember-addons/ember-computed-decorators'; import computed from "ember-addons/ember-computed-decorators";
const ATTRIBUTES = [
"disk_space",
"admins",
"moderators",
"silenced",
"suspended",
"top_traffic_sources",
"top_referred_topics",
"updated_at"
];
const ATTRIBUTES = [ 'disk_space','admins', 'moderators', 'silenced', 'suspended', 'top_traffic_sources', const REPORTS = [
'top_referred_topics', 'updated_at']; "global_reports",
"page_view_reports",
const REPORTS = [ 'global_reports', 'page_view_reports', 'private_message_reports', 'http_reports', "private_message_reports",
'user_reports', 'mobile_reports']; "http_reports",
"user_reports",
"mobile_reports"
];
// This controller supports the default interface when you enter the admin section. // This controller supports the default interface when you enter the admin section.
export default Ember.Controller.extend({ export default Ember.Controller.extend({
loading: null, loading: null,
versionCheck: null, versionCheck: null,
dashboardFetchedAt: null, dashboardFetchedAt: null,
exceptionController: Ember.inject.controller('exception'), exceptionController: Ember.inject.controller("exception"),
fetchDashboard() { fetchDashboard() {
if (!this.get('dashboardFetchedAt') || moment().subtract(30, 'minutes').toDate() > this.get('dashboardFetchedAt')) { if (
this.set('loading', true); !this.get("dashboardFetchedAt") ||
AdminDashboard.find().then(d => { moment()
this.set('dashboardFetchedAt', new Date()); .subtract(30, "minutes")
.toDate() > this.get("dashboardFetchedAt")
) {
this.set("loading", true);
AdminDashboard.find()
.then(d => {
this.set("dashboardFetchedAt", new Date());
REPORTS.forEach(name => this.set(name, d[name].map(r => Report.create(r)))); REPORTS.forEach(name =>
this.set(name, d[name].map(r => Report.create(r)))
);
const topReferrers = d.top_referrers; const topReferrers = d.top_referrers;
if (topReferrers && topReferrers.data) { if (topReferrers && topReferrers.data) {
d.top_referrers.data = topReferrers.data.map(user => AdminUser.create(user)); d.top_referrers.data = topReferrers.data.map(user =>
this.set('top_referrers', topReferrers); AdminUser.create(user)
} );
this.set("top_referrers", topReferrers);
}
ATTRIBUTES.forEach(a => this.set(a, d[a])); ATTRIBUTES.forEach(a => this.set(a, d[a]));
}).catch(e => { })
this.get('exceptionController').set('thrown', e.jqXHR); .catch(e => {
this.replaceRoute('exception'); this.get("exceptionController").set("thrown", e.jqXHR);
}).finally(() => { this.replaceRoute("exception");
this.set('loading', false); })
}); .finally(() => {
this.set("loading", false);
});
} }
}, },
@computed("updated_at")
@computed('updated_at')
updatedTimestamp(updatedAt) { updatedTimestamp(updatedAt) {
return moment(updatedAt).format('LLL'); return moment(updatedAt).format("LLL");
}, },
actions: { actions: {
@ -52,5 +76,4 @@ export default Ember.Controller.extend({
this.set("showTrafficReport", true); this.set("showTrafficReport", true);
} }
} }
}); });

View file

@ -1,6 +1,6 @@
import AdminEmailLogsController from 'admin/controllers/admin-email-logs'; import AdminEmailLogsController from "admin/controllers/admin-email-logs";
import debounce from 'discourse/lib/debounce'; import debounce from "discourse/lib/debounce";
import EmailLog from 'admin/models/email-log'; import EmailLog from "admin/models/email-log";
export default AdminEmailLogsController.extend({ export default AdminEmailLogsController.extend({
filterEmailLogs: debounce(function() { filterEmailLogs: debounce(function() {

View file

@ -1,21 +1,25 @@
import IncomingEmail from 'admin/models/incoming-email'; import IncomingEmail from "admin/models/incoming-email";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
loading: false, loading: false,
actions: { actions: {
loadMore() { loadMore() {
if (this.get("loading") || this.get("model.allLoaded")) { return; } if (this.get("loading") || this.get("model.allLoaded")) {
this.set('loading', true); return;
}
this.set("loading", true);
IncomingEmail.findAll(this.get("filter"), this.get("model.length")) IncomingEmail.findAll(this.get("filter"), this.get("model.length"))
.then(incoming => { .then(incoming => {
if (incoming.length < 50) { this.get("model").set("allLoaded", true); } if (incoming.length < 50) {
this.get("model").addObjects(incoming); this.get("model").set("allLoaded", true);
}).finally(() => { }
this.set('loading', false); this.get("model").addObjects(incoming);
}); })
.finally(() => {
this.set("loading", false);
});
} }
} }
}); });

View file

@ -1,12 +1,11 @@
import { ajax } from 'discourse/lib/ajax'; import { ajax } from "discourse/lib/ajax";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
/** /**
Is the "send test email" button disabled? Is the "send test email" button disabled?
@property sendTestEmailDisabled @property sendTestEmailDisabled
**/ **/
sendTestEmailDisabled: Em.computed.empty('testEmailAddress'), sendTestEmailDisabled: Em.computed.empty("testEmailAddress"),
/** /**
Clears the 'sentTestEmail' property on successful send. Clears the 'sentTestEmail' property on successful send.
@ -14,8 +13,8 @@ export default Ember.Controller.extend({
@method testEmailAddressChanged @method testEmailAddressChanged
**/ **/
testEmailAddressChanged: function() { testEmailAddressChanged: function() {
this.set('sentTestEmail', false); this.set("sentTestEmail", false);
}.observes('testEmailAddress'), }.observes("testEmailAddress"),
actions: { actions: {
/** /**
@ -31,21 +30,28 @@ export default Ember.Controller.extend({
var self = this; var self = this;
ajax("/admin/email/test", { ajax("/admin/email/test", {
type: 'POST', type: "POST",
data: { email_address: this.get('testEmailAddress') } data: { email_address: this.get("testEmailAddress") }
}).then(function () { })
self.set('sentTestEmail', true); .then(
}, function(e) { function() {
if (e.responseJSON && e.responseJSON.errors) { self.set("sentTestEmail", true);
bootbox.alert(I18n.t('admin.email.error', { server_error: e.responseJSON.errors[0] })); },
} else { function(e) {
bootbox.alert(I18n.t('admin.email.test_error')); if (e.responseJSON && e.responseJSON.errors) {
} bootbox.alert(
}).finally(function() { I18n.t("admin.email.error", {
self.set('sendingEmail', false); server_error: e.responseJSON.errors[0]
}); })
);
} else {
bootbox.alert(I18n.t("admin.email.test_error"));
}
}
)
.finally(function() {
self.set("sendingEmail", false);
});
} }
} }
}); });

View file

@ -1,20 +1,25 @@
import EmailLog from 'admin/models/email-log'; import EmailLog from "admin/models/email-log";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
loading: false, loading: false,
actions: { actions: {
loadMore() { loadMore() {
if (this.get("loading") || this.get("model.allLoaded")) { return; } if (this.get("loading") || this.get("model.allLoaded")) {
return;
}
this.set('loading', true); this.set("loading", true);
return EmailLog.findAll(this.get("filter"), this.get("model.length")) return EmailLog.findAll(this.get("filter"), this.get("model.length"))
.then(logs => { .then(logs => {
if (logs.length < 50) { this.get("model").set("allLoaded", true); } if (logs.length < 50) {
this.get("model").addObjects(logs); this.get("model").set("allLoaded", true);
}).finally(() => { }
this.set('loading', false); this.get("model").addObjects(logs);
}); })
.finally(() => {
this.set("loading", false);
});
} }
} }
}); });

View file

@ -1,52 +1,60 @@
import EmailPreview from 'admin/models/email-preview'; import EmailPreview from "admin/models/email-preview";
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
username: null, username: null,
lastSeen: null, lastSeen: null,
emailEmpty: Ember.computed.empty('email'), emailEmpty: Ember.computed.empty("email"),
sendEmailDisabled: Ember.computed.or('emailEmpty', 'sendingEmail'), sendEmailDisabled: Ember.computed.or("emailEmpty", "sendingEmail"),
showSendEmailForm: Ember.computed.notEmpty('model.html_content'), showSendEmailForm: Ember.computed.notEmpty("model.html_content"),
htmlEmpty: Ember.computed.empty('model.html_content'), htmlEmpty: Ember.computed.empty("model.html_content"),
actions: { actions: {
refresh() { refresh() {
const model = this.get('model'); const model = this.get("model");
this.set('loading', true); this.set("loading", true);
this.set('sentEmail', false); this.set("sentEmail", false);
let username = this.get('username'); let username = this.get("username");
if (!username) { if (!username) {
username = this.currentUser.get('username'); username = this.currentUser.get("username");
this.set('username', username); this.set("username", username);
} }
EmailPreview.findDigest(username, this.get('lastSeen')).then(email => { EmailPreview.findDigest(username, this.get("lastSeen")).then(email => {
model.setProperties(email.getProperties('html_content', 'text_content')); model.setProperties(
this.set('loading', false); email.getProperties("html_content", "text_content")
);
this.set("loading", false);
}); });
}, },
toggleShowHtml() { toggleShowHtml() {
this.toggleProperty('showHtml'); this.toggleProperty("showHtml");
}, },
sendEmail() { sendEmail() {
this.set('sendingEmail', true); this.set("sendingEmail", true);
this.set('sentEmail', false); this.set("sentEmail", false);
EmailPreview.sendDigest(this.get('username'), this.get('lastSeen'), this.get('email')).then(result => { EmailPreview.sendDigest(
if (result.errors) { this.get("username"),
bootbox.alert(result.errors); this.get("lastSeen"),
} else { this.get("email")
this.set('sentEmail', true); )
} .then(result => {
}).catch(popupAjaxError).finally(() => { if (result.errors) {
this.set('sendingEmail', false); bootbox.alert(result.errors);
}); } else {
this.set("sentEmail", true);
}
})
.catch(popupAjaxError)
.finally(() => {
this.set("sendingEmail", false);
});
} }
} }
}); });

View file

@ -1,9 +1,11 @@
import AdminEmailIncomingsController from 'admin/controllers/admin-email-incomings'; import AdminEmailIncomingsController from "admin/controllers/admin-email-incomings";
import debounce from 'discourse/lib/debounce'; import debounce from "discourse/lib/debounce";
import IncomingEmail from 'admin/models/incoming-email'; import IncomingEmail from "admin/models/incoming-email";
export default AdminEmailIncomingsController.extend({ export default AdminEmailIncomingsController.extend({
filterIncomingEmails: debounce(function() { filterIncomingEmails: debounce(function() {
IncomingEmail.findAll(this.get("filter")).then(incomings => this.set("model", incomings)); IncomingEmail.findAll(this.get("filter")).then(incomings =>
this.set("model", incomings)
);
}, 250).observes("filter.{from,to,subject}") }, 250).observes("filter.{from,to,subject}")
}); });

View file

@ -1,9 +1,11 @@
import AdminEmailIncomingsController from 'admin/controllers/admin-email-incomings'; import AdminEmailIncomingsController from "admin/controllers/admin-email-incomings";
import debounce from 'discourse/lib/debounce'; import debounce from "discourse/lib/debounce";
import IncomingEmail from 'admin/models/incoming-email'; import IncomingEmail from "admin/models/incoming-email";
export default AdminEmailIncomingsController.extend({ export default AdminEmailIncomingsController.extend({
filterIncomingEmails: debounce(function() { filterIncomingEmails: debounce(function() {
IncomingEmail.findAll(this.get("filter")).then(incomings => this.set("model", incomings)); IncomingEmail.findAll(this.get("filter")).then(incomings =>
this.set("model", incomings)
);
}, 250).observes("filter.{from,to,subject,error}") }, 250).observes("filter.{from,to,subject,error}")
}); });

View file

@ -1,6 +1,6 @@
import AdminEmailLogsController from 'admin/controllers/admin-email-logs'; import AdminEmailLogsController from "admin/controllers/admin-email-logs";
import debounce from 'discourse/lib/debounce'; import debounce from "discourse/lib/debounce";
import EmailLog from 'admin/models/email-log'; import EmailLog from "admin/models/email-log";
export default AdminEmailLogsController.extend({ export default AdminEmailLogsController.extend({
filterEmailLogs: debounce(function() { filterEmailLogs: debounce(function() {

View file

@ -1,6 +1,6 @@
import AdminEmailLogsController from 'admin/controllers/admin-email-logs'; import AdminEmailLogsController from "admin/controllers/admin-email-logs";
import debounce from 'discourse/lib/debounce'; import debounce from "discourse/lib/debounce";
import EmailLog from 'admin/models/email-log'; import EmailLog from "admin/models/email-log";
export default AdminEmailLogsController.extend({ export default AdminEmailLogsController.extend({
filterEmailLogs: debounce(function() { filterEmailLogs: debounce(function() {

View file

@ -1,22 +1,20 @@
import computed from 'ember-addons/ember-computed-decorators'; import computed from "ember-addons/ember-computed-decorators";
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
saved: false, saved: false,
embedding: null, embedding: null,
// show settings if we have at least one created host // show settings if we have at least one created host
@computed('embedding.embeddable_hosts.@each.isCreated') @computed("embedding.embeddable_hosts.@each.isCreated")
showSecondary() { showSecondary() {
const hosts = this.get('embedding.embeddable_hosts'); const hosts = this.get("embedding.embeddable_hosts");
return hosts.length && hosts.findBy('isCreated'); return hosts.length && hosts.findBy("isCreated");
}, },
@computed('embedding.base_url') @computed("embedding.base_url")
embeddingCode(baseUrl) { embeddingCode(baseUrl) {
const html = `<div id='discourse-comments'></div>
const html =
`<div id='discourse-comments'></div>
<script type="text/javascript"> <script type="text/javascript">
DiscourseEmbed = { discourseUrl: '${baseUrl}/', DiscourseEmbed = { discourseUrl: '${baseUrl}/',
@ -34,20 +32,23 @@ export default Ember.Controller.extend({
actions: { actions: {
saveChanges() { saveChanges() {
const embedding = this.get('embedding'); const embedding = this.get("embedding");
const updates = embedding.getProperties(embedding.get('fields')); const updates = embedding.getProperties(embedding.get("fields"));
this.set('saved', false); this.set("saved", false);
this.get('embedding').update(updates).then(() => this.set('saved', true)).catch(popupAjaxError); this.get("embedding")
.update(updates)
.then(() => this.set("saved", true))
.catch(popupAjaxError);
}, },
addHost() { addHost() {
const host = this.store.createRecord('embeddable-host'); const host = this.store.createRecord("embeddable-host");
this.get('embedding.embeddable_hosts').pushObject(host); this.get("embedding.embeddable_hosts").pushObject(host);
}, },
deleteHost(host) { deleteHost(host) {
this.get('embedding.embeddable_hosts').removeObject(host); this.get("embedding.embeddable_hosts").removeObject(host);
} }
} }
}); });

View file

@ -1,12 +1,12 @@
import { ajax } from 'discourse/lib/ajax'; import { ajax } from "discourse/lib/ajax";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
sortedEmojis: Ember.computed.sort('model', 'emojiSorting'), sortedEmojis: Ember.computed.sort("model", "emojiSorting"),
emojiSorting: ['name'], emojiSorting: ["name"],
actions: { actions: {
emojiUploaded(emoji) { emojiUploaded(emoji) {
emoji.url += "?t=" + new Date().getTime(); emoji.url += "?t=" + new Date().getTime();
this.get('model').pushObject(Ember.Object.create(emoji)); this.get("model").pushObject(Ember.Object.create(emoji));
}, },
destroy(emoji) { destroy(emoji) {
@ -16,8 +16,10 @@ export default Ember.Controller.extend({
I18n.t("yes_value"), I18n.t("yes_value"),
destroy => { destroy => {
if (destroy) { if (destroy) {
return ajax("/admin/customize/emojis/" + emoji.get("name"), { type: "DELETE" }).then(() => { return ajax("/admin/customize/emojis/" + emoji.get("name"), {
this.get('model').removeObject(emoji); type: "DELETE"
}).then(() => {
this.get("model").removeObject(emoji);
}); });
} }
} }

View file

@ -1,12 +1,12 @@
import { exportEntity } from 'discourse/lib/export-csv'; import { exportEntity } from "discourse/lib/export-csv";
import { outputExportResult } from 'discourse/lib/export-result'; import { outputExportResult } from "discourse/lib/export-result";
import ScreenedEmail from 'admin/models/screened-email'; import ScreenedEmail from "admin/models/screened-email";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
loading: false, loading: false,
actions: { actions: {
clearBlock(row){ clearBlock(row) {
row.clearBlock().then(function() { row.clearBlock().then(function() {
// feeling lazy // feeling lazy
window.location.reload(); window.location.reload();
@ -14,15 +14,15 @@ export default Ember.Controller.extend({
}, },
exportScreenedEmailList() { exportScreenedEmailList() {
exportEntity('screened_email').then(outputExportResult); exportEntity("screened_email").then(outputExportResult);
} }
}, },
show() { show() {
this.set('loading', true); this.set("loading", true);
ScreenedEmail.findAll().then(result => { ScreenedEmail.findAll().then(result => {
this.set('model', result); this.set("model", result);
this.set('loading', false); this.set("loading", false);
}); });
} }
}); });

View file

@ -1,7 +1,7 @@
import debounce from 'discourse/lib/debounce'; import debounce from "discourse/lib/debounce";
import { outputExportResult } from 'discourse/lib/export-result'; import { outputExportResult } from "discourse/lib/export-result";
import { exportEntity } from 'discourse/lib/export-csv'; import { exportEntity } from "discourse/lib/export-csv";
import ScreenedIpAddress from 'admin/models/screened-ip-address'; import ScreenedIpAddress from "admin/models/screened-ip-address";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
loading: false, loading: false,
@ -9,75 +9,90 @@ export default Ember.Controller.extend({
savedIpAddress: null, savedIpAddress: null,
show: debounce(function() { show: debounce(function() {
this.set('loading', true); this.set("loading", true);
ScreenedIpAddress.findAll(this.get("filter")) ScreenedIpAddress.findAll(this.get("filter")).then(result => {
.then(result => { this.set("model", result);
this.set('model', result); this.set("loading", false);
this.set('loading', false); });
});
}, 250).observes("filter"), }, 250).observes("filter"),
actions: { actions: {
allow(record) { allow(record) {
record.set('action_name', 'do_nothing'); record.set("action_name", "do_nothing");
record.save(); record.save();
}, },
block(record) { block(record) {
record.set('action_name', 'block'); record.set("action_name", "block");
record.save(); record.save();
}, },
edit(record) { edit(record) {
if (!record.get('editing')) { if (!record.get("editing")) {
this.set("savedIpAddress", record.get('ip_address')); this.set("savedIpAddress", record.get("ip_address"));
} }
record.set('editing', true); record.set("editing", true);
}, },
cancel(record) { cancel(record) {
if (this.get('savedIpAddress') && record.get('editing')) { if (this.get("savedIpAddress") && record.get("editing")) {
record.set('ip_address', this.get('savedIpAddress')); record.set("ip_address", this.get("savedIpAddress"));
} }
record.set('editing', false); record.set("editing", false);
}, },
save(record) { save(record) {
const wasEditing = record.get('editing'); const wasEditing = record.get("editing");
record.set('editing', false); record.set("editing", false);
record.save().then(saved => { record
if (saved.success) { .save()
this.set('savedIpAddress', null); .then(saved => {
} else { if (saved.success) {
bootbox.alert(saved.errors); this.set("savedIpAddress", null);
if (wasEditing) record.set('editing', true); } else {
} bootbox.alert(saved.errors);
}).catch(e => { if (wasEditing) record.set("editing", true);
if (e.responseJSON && e.responseJSON.errors) { }
bootbox.alert(I18n.t("generic_error_with_reason", {error: e.responseJSON.errors.join('. ')})); })
} else { .catch(e => {
bootbox.alert(I18n.t("generic_error")); if (e.responseJSON && e.responseJSON.errors) {
} bootbox.alert(
if (wasEditing) record.set('editing', true); I18n.t("generic_error_with_reason", {
}); error: e.responseJSON.errors.join(". ")
})
);
} else {
bootbox.alert(I18n.t("generic_error"));
}
if (wasEditing) record.set("editing", true);
});
}, },
destroy(record) { destroy(record) {
return bootbox.confirm( return bootbox.confirm(
I18n.t("admin.logs.screened_ips.delete_confirm", { ip_address: record.get('ip_address') }), I18n.t("admin.logs.screened_ips.delete_confirm", {
ip_address: record.get("ip_address")
}),
I18n.t("no_value"), I18n.t("no_value"),
I18n.t("yes_value"), I18n.t("yes_value"),
result => { result => {
if (result) { if (result) {
record.destroy().then(deleted => { record
if (deleted) { .destroy()
this.get("model").removeObject(record); .then(deleted => {
} else { if (deleted) {
bootbox.alert(I18n.t("generic_error")); this.get("model").removeObject(record);
} } else {
}).catch(e => { bootbox.alert(I18n.t("generic_error"));
bootbox.alert(I18n.t("generic_error_with_reason", {error: "http: " + e.status + " - " + e.body})); }
}); })
.catch(e => {
bootbox.alert(
I18n.t("generic_error_with_reason", {
error: "http: " + e.status + " - " + e.body
})
);
});
} }
} }
); );
@ -89,26 +104,37 @@ export default Ember.Controller.extend({
rollUp() { rollUp() {
const self = this; const self = this;
return bootbox.confirm(I18n.t("admin.logs.screened_ips.roll_up_confirm"), I18n.t("no_value"), I18n.t("yes_value"), function (confirmed) { return bootbox.confirm(
if (confirmed) { I18n.t("admin.logs.screened_ips.roll_up_confirm"),
self.set("loading", true); I18n.t("no_value"),
return ScreenedIpAddress.rollUp().then(function(results) { I18n.t("yes_value"),
if (results && results.subnets) { function(confirmed) {
if (results.subnets.length > 0) { if (confirmed) {
self.send("show"); self.set("loading", true);
bootbox.alert(I18n.t("admin.logs.screened_ips.rolled_up_some_subnets", { subnets: results.subnets.join(", ") })); return ScreenedIpAddress.rollUp().then(function(results) {
} else { if (results && results.subnets) {
self.set("loading", false); if (results.subnets.length > 0) {
bootbox.alert(I18n.t("admin.logs.screened_ips.rolled_up_no_subnet")); self.send("show");
bootbox.alert(
I18n.t("admin.logs.screened_ips.rolled_up_some_subnets", {
subnets: results.subnets.join(", ")
})
);
} else {
self.set("loading", false);
bootbox.alert(
I18n.t("admin.logs.screened_ips.rolled_up_no_subnet")
);
}
} }
} });
}); }
} }
}); );
}, },
exportScreenedIpList() { exportScreenedIpList() {
exportEntity('screened_ip').then(outputExportResult); exportEntity("screened_ip").then(outputExportResult);
} }
} }
}); });

View file

@ -1,21 +1,21 @@
import { exportEntity } from 'discourse/lib/export-csv'; import { exportEntity } from "discourse/lib/export-csv";
import { outputExportResult } from 'discourse/lib/export-result'; import { outputExportResult } from "discourse/lib/export-result";
import ScreenedUrl from 'admin/models/screened-url'; import ScreenedUrl from "admin/models/screened-url";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
loading: false, loading: false,
show() { show() {
this.set('loading', true); this.set("loading", true);
ScreenedUrl.findAll().then(result => { ScreenedUrl.findAll().then(result => {
this.set('model', result); this.set("model", result);
this.set('loading', false); this.set("loading", false);
}); });
}, },
actions: { actions: {
exportScreenedUrlList() { exportScreenedUrlList() {
exportEntity('screened_url').then(outputExportResult); exportEntity("screened_url").then(outputExportResult);
} }
} }
}); });

View file

@ -1,41 +1,44 @@
import { exportEntity } from 'discourse/lib/export-csv'; import { exportEntity } from "discourse/lib/export-csv";
import { outputExportResult } from 'discourse/lib/export-result'; import { outputExportResult } from "discourse/lib/export-result";
import StaffActionLog from 'admin/models/staff-action-log'; import StaffActionLog from "admin/models/staff-action-log";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
loading: false, loading: false,
filters: null, filters: null,
userHistoryActions: [], userHistoryActions: [],
filtersExists: Ember.computed.gt('filterCount', 0), filtersExists: Ember.computed.gt("filterCount", 0),
filterActionIdChanged: function(){ filterActionIdChanged: function() {
const filterActionId = this.get('filterActionId'); const filterActionId = this.get("filterActionId");
if (filterActionId) { if (filterActionId) {
this._changeFilters({ this._changeFilters({
action_name: this.get('userHistoryActions').findBy("id", parseInt(filterActionId,10)).name_raw, action_name: this.get("userHistoryActions").findBy(
"id",
parseInt(filterActionId, 10)
).name_raw,
action_id: filterActionId action_id: filterActionId
}); });
} }
}.observes('filterActionId'), }.observes("filterActionId"),
actionFilter: function() { actionFilter: function() {
var name = this.get('filters.action_name'); var name = this.get("filters.action_name");
if (name) { if (name) {
return I18n.t("admin.logs.staff_actions.actions." + name); return I18n.t("admin.logs.staff_actions.actions." + name);
} else { } else {
return null; return null;
} }
}.property('filters.action_name'), }.property("filters.action_name"),
showInstructions: Ember.computed.gt('model.length', 0), showInstructions: Ember.computed.gt("model.length", 0),
_refresh() { _refresh() {
this.set('loading', true); this.set("loading", true);
var filters = this.get('filters'), var filters = this.get("filters"),
params = {}, params = {},
count = 0; count = 0;
// Don't send null values // Don't send null values
Object.keys(filters).forEach(function(k) { Object.keys(filters).forEach(function(k) {
@ -45,37 +48,39 @@ export default Ember.Controller.extend({
count += 1; count += 1;
} }
}); });
this.set('filterCount', count); this.set("filterCount", count);
StaffActionLog.findAll(params).then((result) => { StaffActionLog.findAll(params)
this.set('model', result.staff_action_logs); .then(result => {
if (this.get('userHistoryActions').length === 0) { this.set("model", result.staff_action_logs);
let actionTypes = result.user_history_actions.map(pair => { if (this.get("userHistoryActions").length === 0) {
return { let actionTypes = result.user_history_actions.map(pair => {
id: pair.id, return {
name: I18n.t("admin.logs.staff_actions.actions." + pair.name), id: pair.id,
name_raw: pair.name name: I18n.t("admin.logs.staff_actions.actions." + pair.name),
}; name_raw: pair.name
}); };
actionTypes = _.sortBy(actionTypes, row => row.name); });
this.set('userHistoryActions', actionTypes); actionTypes = _.sortBy(actionTypes, row => row.name);
} this.set("userHistoryActions", actionTypes);
}).finally(()=>{ }
this.set('loading', false); })
}); .finally(() => {
this.set("loading", false);
});
}, },
scheduleRefresh() { scheduleRefresh() {
Ember.run.scheduleOnce('afterRender', this, this._refresh); Ember.run.scheduleOnce("afterRender", this, this._refresh);
}, },
resetFilters: function() { resetFilters: function() {
this.set('filters', Ember.Object.create()); this.set("filters", Ember.Object.create());
this.scheduleRefresh(); this.scheduleRefresh();
}.on('init'), }.on("init"),
_changeFilters: function(props) { _changeFilters: function(props) {
this.get('filters').setProperties(props); this.get("filters").setProperties(props);
this.scheduleRefresh(); this.scheduleRefresh();
}, },
@ -84,7 +89,7 @@ export default Ember.Controller.extend({
var changed = {}; var changed = {};
// Special case, clear all action related stuff // Special case, clear all action related stuff
if (key === 'actionFilter') { if (key === "actionFilter") {
changed.action_name = null; changed.action_name = null;
changed.action_id = null; changed.action_id = null;
changed.custom_type = null; changed.custom_type = null;
@ -102,9 +107,9 @@ export default Ember.Controller.extend({
filterByAction: function(logItem) { filterByAction: function(logItem) {
this._changeFilters({ this._changeFilters({
action_name: logItem.get('action_name'), action_name: logItem.get("action_name"),
action_id: logItem.get('action'), action_id: logItem.get("action"),
custom_type: logItem.get('custom_type') custom_type: logItem.get("custom_type")
}); });
}, },
@ -121,7 +126,7 @@ export default Ember.Controller.extend({
}, },
exportStaffActionLogs: function() { exportStaffActionLogs: function() {
exportEntity('staff_action').then(outputExportResult); exportEntity("staff_action").then(outputExportResult);
} }
} }
}); });

View file

@ -1,5 +1,5 @@
import debounce from 'discourse/lib/debounce'; import debounce from "discourse/lib/debounce";
import Permalink from 'admin/models/permalink'; import Permalink from "admin/models/permalink";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
loading: false, loading: false,
@ -7,8 +7,8 @@ export default Ember.Controller.extend({
show: debounce(function() { show: debounce(function() {
Permalink.findAll(this.get("filter")).then(result => { Permalink.findAll(this.get("filter")).then(result => {
this.set('model', result); this.set("model", result);
this.set('loading', false); this.set("loading", false);
}); });
}, 250).observes("filter"), }, 250).observes("filter"),
@ -18,19 +18,27 @@ export default Ember.Controller.extend({
}, },
destroy: function(record) { destroy: function(record) {
return bootbox.confirm(I18n.t("admin.permalink.delete_confirm"), I18n.t("no_value"), I18n.t("yes_value"), result => { return bootbox.confirm(
if (result) { I18n.t("admin.permalink.delete_confirm"),
record.destroy().then(deleted => { I18n.t("no_value"),
if (deleted) { I18n.t("yes_value"),
this.get('model').removeObject(record); result => {
} else { if (result) {
bootbox.alert(I18n.t("generic_error")); record.destroy().then(
} deleted => {
}, function(){ if (deleted) {
bootbox.alert(I18n.t("generic_error")); this.get("model").removeObject(record);
}); } else {
bootbox.alert(I18n.t("generic_error"));
}
},
function() {
bootbox.alert(I18n.t("generic_error"));
}
);
}
} }
}); );
} }
} }
}); });

View file

@ -1,9 +1,11 @@
export default Ember.Controller.extend({ export default Ember.Controller.extend({
adminRoutes: function() { adminRoutes: function() {
return this.get('model').map(p => { return this.get("model")
if (p.get('enabled')) { .map(p => {
return p.admin_route; if (p.get("enabled")) {
} return p.admin_route;
}).compact(); }
})
.compact();
}.property() }.property()
}); });

View file

@ -1,14 +1,14 @@
import { exportEntity } from 'discourse/lib/export-csv'; import { exportEntity } from "discourse/lib/export-csv";
import { outputExportResult } from 'discourse/lib/export-result'; import { outputExportResult } from "discourse/lib/export-result";
import Report from 'admin/models/report'; import Report from "admin/models/report";
import computed from 'ember-addons/ember-computed-decorators'; import computed from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
classNames: ["admin-reports"], classNames: ["admin-reports"],
queryParams: ["mode", "start_date", "end_date", "category_id", "group_id"], queryParams: ["mode", "start_date", "end_date", "category_id", "group_id"],
viewMode: 'graph', viewMode: "graph",
viewingTable: Em.computed.equal('viewMode', 'table'), viewingTable: Em.computed.equal("viewMode", "table"),
viewingGraph: Em.computed.equal('viewMode', 'graph'), viewingGraph: Em.computed.equal("viewMode", "graph"),
startDate: null, startDate: null,
endDate: null, endDate: null,
categoryId: null, categoryId: null,
@ -17,32 +17,46 @@ export default Ember.Controller.extend({
@computed() @computed()
categoryOptions() { categoryOptions() {
const arr = [{name: I18n.t('category.all'), value: 'all'}]; const arr = [{ name: I18n.t("category.all"), value: "all" }];
return arr.concat(Discourse.Site.currentProp('sortedCategories').map((i) => {return {name: i.get('name'), value: i.get('id')};})); return arr.concat(
Discourse.Site.currentProp("sortedCategories").map(i => {
return { name: i.get("name"), value: i.get("id") };
})
);
}, },
@computed() @computed()
groupOptions() { groupOptions() {
const arr = [{name: I18n.t('admin.dashboard.reports.groups'), value: 'all'}]; const arr = [
return arr.concat(this.site.groups.map((i) => {return {name: i['name'], value: i['id']};})); { name: I18n.t("admin.dashboard.reports.groups"), value: "all" }
];
return arr.concat(
this.site.groups.map(i => {
return { name: i["name"], value: i["id"] };
})
);
}, },
@computed('model.type') @computed("model.type")
showCategoryOptions(modelType) { showCategoryOptions(modelType) {
return [ return [
'topics', "topics",
'posts', "posts",
'time_to_first_response_total', "time_to_first_response_total",
'topics_with_no_response', "topics_with_no_response",
'flags', "flags",
'likes', "likes",
'bookmarks' "bookmarks"
].includes(modelType); ].includes(modelType);
}, },
@computed('model.type') @computed("model.type")
showGroupOptions(modelType) { showGroupOptions(modelType) {
return modelType === "visits" || modelType === "signups" || modelType === "profile_views"; return (
modelType === "visits" ||
modelType === "signups" ||
modelType === "profile_views"
);
}, },
actions: { actions: {
@ -51,34 +65,44 @@ export default Ember.Controller.extend({
this.set("refreshing", true); this.set("refreshing", true);
this.setProperties({ this.setProperties({
'start_date': this.get('startDate'), start_date: this.get("startDate"),
'end_date': this.get('endDate'), end_date: this.get("endDate"),
'category_id': this.get('categoryId'), category_id: this.get("categoryId")
}); });
if (this.get('groupId')){ if (this.get("groupId")) {
this.set('group_id', this.get('groupId')); this.set("group_id", this.get("groupId"));
} }
q = Report.find(this.get("model.type"), this.get("startDate"), this.get("endDate"), this.get("categoryId"), this.get("groupId")); q = Report.find(
q.then(m => this.set("model", m)).finally(() => this.set("refreshing", false)); this.get("model.type"),
this.get("startDate"),
this.get("endDate"),
this.get("categoryId"),
this.get("groupId")
);
q.then(m => this.set("model", m)).finally(() =>
this.set("refreshing", false)
);
}, },
viewAsTable() { viewAsTable() {
this.set('viewMode', 'table'); this.set("viewMode", "table");
}, },
viewAsGraph() { viewAsGraph() {
this.set('viewMode', 'graph'); this.set("viewMode", "graph");
}, },
exportCsv() { exportCsv() {
exportEntity('report', { exportEntity("report", {
name: this.get("model.type"), name: this.get("model.type"),
start_date: this.get('startDate'), start_date: this.get("startDate"),
end_date: this.get('endDate'), end_date: this.get("endDate"),
category_id: this.get('categoryId') === 'all' ? undefined : this.get('categoryId'), category_id:
group_id: this.get('groupId') === 'all' ? undefined : this.get('groupId') this.get("categoryId") === "all" ? undefined : this.get("categoryId"),
group_id:
this.get("groupId") === "all" ? undefined : this.get("groupId")
}).then(outputExportResult); }).then(outputExportResult);
} }
} }

View file

@ -4,8 +4,11 @@ export default Ember.Controller.extend({
searchType: "all", searchType: "all",
searchTypeOptions: [ 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: "all",
{id: 'full_page', name: I18n.t('admin.logs.search_logs.types.full_page')} 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

@ -5,9 +5,15 @@ export default Ember.Controller.extend({
searchType: "all", searchType: "all",
searchTypeOptions: [ 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: "all",
{id: 'full_page', name: I18n.t('admin.logs.search_logs.types.full_page')}, name: I18n.t("admin.logs.search_logs.types.all_search_types")
{id: 'click_through_only', name: I18n.t('admin.logs.search_logs.types.click_through_only')} },
] { 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

@ -1,4 +1,4 @@
import debounce from 'discourse/lib/debounce'; import debounce from "discourse/lib/debounce";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
filter: null, filter: null,
@ -6,32 +6,41 @@ export default Ember.Controller.extend({
filterContentNow(category) { filterContentNow(category) {
// If we have no content, don't bother filtering anything // If we have no content, don't bother filtering anything
if (!!Ember.isEmpty(this.get('allSiteSettings'))) return; if (!!Ember.isEmpty(this.get("allSiteSettings"))) return;
let filter; let filter;
if (this.get('filter')) { if (this.get("filter")) {
filter = this.get('filter').toLowerCase(); filter = this.get("filter").toLowerCase();
} }
if ((!filter || 0 === filter.length) && !this.get('onlyOverridden')) { if ((!filter || 0 === filter.length) && !this.get("onlyOverridden")) {
this.set('model', this.get('allSiteSettings')); this.set("model", this.get("allSiteSettings"));
this.transitionToRoute('adminSiteSettings'); this.transitionToRoute("adminSiteSettings");
return; return;
} }
const all = {nameKey: 'all_results', name: I18n.t('admin.site_settings.categories.all_results'), siteSettings: []}; const all = {
nameKey: "all_results",
name: I18n.t("admin.site_settings.categories.all_results"),
siteSettings: []
};
const matchesGroupedByCategory = [all]; const matchesGroupedByCategory = [all];
const matches = []; const matches = [];
this.get('allSiteSettings').forEach(settingsCategory => { this.get("allSiteSettings").forEach(settingsCategory => {
const siteSettings = settingsCategory.siteSettings.filter(item => { const siteSettings = settingsCategory.siteSettings.filter(item => {
if (this.get('onlyOverridden') && !item.get('overridden')) return false; if (this.get("onlyOverridden") && !item.get("overridden")) return false;
if (filter) { if (filter) {
const setting = item.get('setting').toLowerCase(); const setting = item.get("setting").toLowerCase();
return setting.includes(filter) || return (
setting.replace(/_/g, ' ').includes(filter) || setting.includes(filter) ||
item.get('description').toLowerCase().includes(filter) || setting.replace(/_/g, " ").includes(filter) ||
(item.get('value') || '').toLowerCase().includes(filter); item
.get("description")
.toLowerCase()
.includes(filter) ||
(item.get("value") || "").toLowerCase().includes(filter)
);
} else { } else {
return true; return true;
} }
@ -40,7 +49,9 @@ export default Ember.Controller.extend({
matches.pushObjects(siteSettings); matches.pushObjects(siteSettings);
matchesGroupedByCategory.pushObject({ matchesGroupedByCategory.pushObject({
nameKey: settingsCategory.nameKey, nameKey: settingsCategory.nameKey,
name: I18n.t('admin.site_settings.categories.' + settingsCategory.nameKey), name: I18n.t(
"admin.site_settings.categories." + settingsCategory.nameKey
),
siteSettings, siteSettings,
count: siteSettings.length count: siteSettings.length
}); });
@ -49,28 +60,30 @@ export default Ember.Controller.extend({
all.siteSettings.pushObjects(matches.slice(0, 30)); all.siteSettings.pushObjects(matches.slice(0, 30));
all.hasMore = matches.length > 30; all.hasMore = matches.length > 30;
all.count = all.hasMore ? '30+' : matches.length; all.count = all.hasMore ? "30+" : matches.length;
this.set('model', matchesGroupedByCategory); this.set("model", matchesGroupedByCategory);
this.transitionToRoute('adminSiteSettingsCategory', category || 'all_results'); this.transitionToRoute(
"adminSiteSettingsCategory",
category || "all_results"
);
}, },
filterContent: debounce(function() { filterContent: debounce(function() {
if (this.get('_skipBounce')) { if (this.get("_skipBounce")) {
this.set('_skipBounce', false); this.set("_skipBounce", false);
} else { } else {
this.filterContentNow(); this.filterContentNow();
} }
}, 250).observes('filter', 'onlyOverridden'), }, 250).observes("filter", "onlyOverridden"),
actions: { actions: {
clearFilter() { clearFilter() {
this.setProperties({ filter: '', onlyOverridden: false }); this.setProperties({ filter: "", onlyOverridden: false });
}, },
toggleMenu() { toggleMenu() {
$('.admin-detail').toggleClass('mobile-closed mobile-open'); $(".admin-detail").toggleClass("mobile-closed mobile-open");
} }
} }
}); });

View file

@ -1,27 +1,33 @@
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
import { bufferedProperty } from 'discourse/mixins/buffered-content'; import { bufferedProperty } from "discourse/mixins/buffered-content";
export default Ember.Controller.extend(bufferedProperty('siteText'), { export default Ember.Controller.extend(bufferedProperty("siteText"), {
saved: false, saved: false,
actions: { actions: {
saveChanges() { saveChanges() {
const buffered = this.get('buffered'); const buffered = this.get("buffered");
this.get('siteText').save(buffered.getProperties('value')).then(() => { this.get("siteText")
this.commitBuffer(); .save(buffered.getProperties("value"))
this.set('saved', true); .then(() => {
}).catch(popupAjaxError); this.commitBuffer();
this.set("saved", true);
})
.catch(popupAjaxError);
}, },
revertChanges() { revertChanges() {
this.set('saved', false); this.set("saved", false);
bootbox.confirm(I18n.t('admin.site_text.revert_confirm'), result => { bootbox.confirm(I18n.t("admin.site_text.revert_confirm"), result => {
if (result) { if (result) {
this.get('siteText').revert().then(props => { this.get("siteText")
const buffered = this.get('buffered'); .revert()
buffered.setProperties(props); .then(props => {
this.commitBuffer(); const buffered = this.get("buffered");
}).catch(popupAjaxError); buffered.setProperties(props);
this.commitBuffer();
})
.catch(popupAjaxError);
} }
}); });
} }

View file

@ -5,28 +5,31 @@ export default Ember.Controller.extend({
searching: false, searching: false,
siteTexts: null, siteTexts: null,
preferred: false, preferred: false,
queryParams: ['q', 'overridden'], queryParams: ["q", "overridden"],
q: null, q: null,
overridden: null, overridden: null,
_performSearch() { _performSearch() {
this.store.find('site-text', this.getProperties('q', 'overridden')).then(results => { this.store
this.set('siteTexts', results); .find("site-text", this.getProperties("q", "overridden"))
}).finally(() => this.set('searching', false)); .then(results => {
this.set("siteTexts", results);
})
.finally(() => this.set("searching", false));
}, },
actions: { actions: {
edit(siteText) { edit(siteText) {
this.transitionToRoute('adminSiteText.edit', siteText.get('id')); this.transitionToRoute("adminSiteText.edit", siteText.get("id"));
}, },
search(overridden) { search(overridden) {
this.set('overridden', overridden); this.set("overridden", overridden);
const q = this.get('q'); const q = this.get("q");
if (q !== lastSearch || overridden !== lastOverridden) { if (q !== lastSearch || overridden !== lastOverridden) {
this.set('searching', true); this.set("searching", true);
Ember.run.debounce(this, this._performSearch, 400); Ember.run.debounce(this, this._performSearch, 400);
lastSearch = q; lastSearch = q;
lastOverridden = overridden; lastOverridden = overridden;

View file

@ -2,29 +2,33 @@ import GrantBadgeController from "discourse/mixins/grant-badge-controller";
export default Ember.Controller.extend(GrantBadgeController, { export default Ember.Controller.extend(GrantBadgeController, {
adminUser: Ember.inject.controller(), adminUser: Ember.inject.controller(),
user: Ember.computed.alias('adminUser.model'), user: Ember.computed.alias("adminUser.model"),
userBadges: Ember.computed.alias('model'), userBadges: Ember.computed.alias("model"),
allBadges: Ember.computed.alias('badges'), allBadges: Ember.computed.alias("badges"),
sortedBadges: Ember.computed.sort('model', 'badgeSortOrder'), sortedBadges: Ember.computed.sort("model", "badgeSortOrder"),
badgeSortOrder: ['granted_at:desc'], badgeSortOrder: ["granted_at:desc"],
groupedBadges: function(){ groupedBadges: function() {
const allBadges = this.get('model'); const allBadges = this.get("model");
var grouped = _.groupBy(allBadges, badge => badge.badge_id); var grouped = _.groupBy(allBadges, badge => badge.badge_id);
var expanded = []; var expanded = [];
const expandedBadges = allBadges.get('expandedBadges'); const expandedBadges = allBadges.get("expandedBadges");
_(grouped).each(function(badges){ _(grouped).each(function(badges) {
var lastGranted = badges[0].granted_at; var lastGranted = badges[0].granted_at;
_.each(badges, function(badge) { _.each(badges, function(badge) {
lastGranted = lastGranted < badge.granted_at ? badge.granted_at : lastGranted; lastGranted =
lastGranted < badge.granted_at ? badge.granted_at : lastGranted;
}); });
if(badges.length===1 || _.include(expandedBadges, badges[0].badge.id)){ if (
badges.length === 1 ||
_.include(expandedBadges, badges[0].badge.id)
) {
_.each(badges, badge => expanded.push(badge)); _.each(badges, badge => expanded.push(badge));
return; return;
} }
@ -40,43 +44,55 @@ export default Ember.Controller.extend(GrantBadgeController, {
expanded.push(result); expanded.push(result);
}); });
return _(expanded).sortBy(group => group.granted_at).reverse().value(); return _(expanded)
}.property('model', 'model.[]', 'model.expandedBadges.[]'), .sortBy(group => group.granted_at)
.reverse()
.value();
}.property("model", "model.[]", "model.expandedBadges.[]"),
actions: { actions: {
expandGroup: function(userBadge) {
expandGroup: function(userBadge){ const model = this.get("model");
const model = this.get('model'); model.set("expandedBadges", model.get("expandedBadges") || []);
model.set('expandedBadges', model.get('expandedBadges') || []); model.get("expandedBadges").pushObject(userBadge.badge.id);
model.get('expandedBadges').pushObject(userBadge.badge.id);
}, },
grantBadge() { grantBadge() {
this.grantBadge(this.get('selectedBadgeId'), this.get('user.username'), this.get('badgeReason')) this.grantBadge(
.then(() => { this.get("selectedBadgeId"),
this.set('badgeReason', ''); this.get("user.username"),
this.get("badgeReason")
).then(
() => {
this.set("badgeReason", "");
Ember.run.next(() => { Ember.run.next(() => {
// Update the selected badge ID after the combobox has re-rendered. // Update the selected badge ID after the combobox has re-rendered.
const newSelectedBadge = this.get('grantableBadges')[0]; const newSelectedBadge = this.get("grantableBadges")[0];
if (newSelectedBadge) { if (newSelectedBadge) {
this.set('selectedBadgeId', newSelectedBadge.get('id')); this.set("selectedBadgeId", newSelectedBadge.get("id"));
} }
}); });
}, function() { },
function() {
// Failure // Failure
bootbox.alert(I18n.t('generic_error')); bootbox.alert(I18n.t("generic_error"));
}); }
);
}, },
revokeBadge(userBadge) { revokeBadge(userBadge) {
return bootbox.confirm(I18n.t("admin.badges.revoke_confirm"), I18n.t("no_value"), I18n.t("yes_value"), result => { return bootbox.confirm(
if (result) { I18n.t("admin.badges.revoke_confirm"),
userBadge.revoke().then(() => { I18n.t("no_value"),
this.get('model').removeObject(userBadge); I18n.t("yes_value"),
}); result => {
if (result) {
userBadge.revoke().then(() => {
this.get("model").removeObject(userBadge);
});
}
} }
}); );
} }
} }
}); });

View file

@ -1,52 +1,59 @@
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
const MAX_FIELDS = 20; const MAX_FIELDS = 20;
export default Ember.Controller.extend({ export default Ember.Controller.extend({
fieldTypes: null, fieldTypes: null,
createDisabled: Em.computed.gte('model.length', MAX_FIELDS), createDisabled: Em.computed.gte("model.length", MAX_FIELDS),
fieldSortOrder: ['position'], fieldSortOrder: ["position"],
sortedFields: Ember.computed.sort('model', 'fieldSortOrder'), sortedFields: Ember.computed.sort("model", "fieldSortOrder"),
actions: { actions: {
createField() { createField() {
const f = this.store.createRecord('user-field', { field_type: 'text', position: MAX_FIELDS }); const f = this.store.createRecord("user-field", {
this.get('model').pushObject(f); field_type: "text",
position: MAX_FIELDS
});
this.get("model").pushObject(f);
}, },
moveUp(f) { moveUp(f) {
const idx = this.get('sortedFields').indexOf(f); const idx = this.get("sortedFields").indexOf(f);
if (idx) { if (idx) {
const prev = this.get('sortedFields').objectAt(idx-1); const prev = this.get("sortedFields").objectAt(idx - 1);
const prevPos = prev.get('position'); const prevPos = prev.get("position");
prev.update({ position: f.get('position') }); prev.update({ position: f.get("position") });
f.update({ position: prevPos }); f.update({ position: prevPos });
} }
}, },
moveDown(f) { moveDown(f) {
const idx = this.get('sortedFields').indexOf(f); const idx = this.get("sortedFields").indexOf(f);
if (idx > -1) { if (idx > -1) {
const next = this.get('sortedFields').objectAt(idx+1); const next = this.get("sortedFields").objectAt(idx + 1);
const nextPos = next.get('position'); const nextPos = next.get("position");
next.update({ position: f.get('position') }); next.update({ position: f.get("position") });
f.update({ position: nextPos }); f.update({ position: nextPos });
} }
}, },
destroy(f) { destroy(f) {
const model = this.get('model'); const model = this.get("model");
// Only confirm if we already been saved // Only confirm if we already been saved
if (f.get('id')) { if (f.get("id")) {
bootbox.confirm(I18n.t("admin.user_fields.delete_confirm"), function(result) { bootbox.confirm(I18n.t("admin.user_fields.delete_confirm"), function(
result
) {
if (result) { if (result) {
f.destroyRecord().then(function() { f.destroyRecord()
model.removeObject(f); .then(function() {
}).catch(popupAjaxError); model.removeObject(f);
})
.catch(popupAjaxError);
} }
}); });
} else { } else {

View file

@ -1,9 +1,9 @@
import { ajax } from 'discourse/lib/ajax'; import { ajax } from "discourse/lib/ajax";
import CanCheckEmails from 'discourse/mixins/can-check-emails'; import CanCheckEmails from "discourse/mixins/can-check-emails";
import { propertyNotEqual, setting } from 'discourse/lib/computed'; import { propertyNotEqual, setting } from "discourse/lib/computed";
import { userPath } from 'discourse/lib/url'; import { userPath } from "discourse/lib/url";
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
import computed from 'ember-addons/ember-computed-decorators'; import computed from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend(CanCheckEmails, { export default Ember.Controller.extend(CanCheckEmails, {
adminTools: Ember.inject.service(), adminTools: Ember.inject.service(),
@ -14,218 +14,291 @@ export default Ember.Controller.extend(CanCheckEmails, {
availableGroups: null, availableGroups: null,
userTitleValue: null, userTitleValue: null,
showApproval: setting('must_approve_users'), showApproval: setting("must_approve_users"),
showBadges: setting('enable_badges'), showBadges: setting("enable_badges"),
primaryGroupDirty: propertyNotEqual('originalPrimaryGroupId', 'model.primary_group_id'), primaryGroupDirty: propertyNotEqual(
"originalPrimaryGroupId",
"model.primary_group_id"
),
canDisableSecondFactor: Ember.computed.and( canDisableSecondFactor: Ember.computed.and(
'model.second_factor_enabled', "model.second_factor_enabled",
'model.can_disable_second_factor' "model.can_disable_second_factor"
), ),
@computed("model.automaticGroups") @computed("model.automaticGroups")
automaticGroups(automaticGroups) { automaticGroups(automaticGroups) {
return automaticGroups.map(group => { return automaticGroups
const name = Ember.String.htmlSafe(group.name); .map(group => {
return `<a href="/groups/${name}">${name}</a>`; const name = Ember.String.htmlSafe(group.name);
}).join(", "); return `<a href="/groups/${name}">${name}</a>`;
})
.join(", ");
}, },
userFields: function() { userFields: function() {
const siteUserFields = this.site.get('user_fields'), const siteUserFields = this.site.get("user_fields"),
userFields = this.get('model.user_fields'); userFields = this.get("model.user_fields");
if (!Ember.isEmpty(siteUserFields)) { if (!Ember.isEmpty(siteUserFields)) {
return siteUserFields.map(function(uf) { return siteUserFields.map(function(uf) {
let value = userFields ? userFields[uf.get('id').toString()] : null; let value = userFields ? userFields[uf.get("id").toString()] : null;
return { name: uf.get('name'), value: value }; return { name: uf.get("name"), value: value };
}); });
} }
return []; return [];
}.property('model.user_fields.[]'), }.property("model.user_fields.[]"),
@computed('model.username_lower') @computed("model.username_lower")
preferencesPath(username) { preferencesPath(username) {
return userPath(`${username}/preferences`); return userPath(`${username}/preferences`);
}, },
@computed('model.can_delete_all_posts', 'model.staff', 'model.post_count') @computed("model.can_delete_all_posts", "model.staff", "model.post_count")
deleteAllPostsExplanation(canDeleteAllPosts, staff, postCount) { deleteAllPostsExplanation(canDeleteAllPosts, staff, postCount) {
if (canDeleteAllPosts) { if (canDeleteAllPosts) {
return null; return null;
} }
if (staff) { if (staff) {
return I18n.t('admin.user.delete_posts_forbidden_because_staff'); return I18n.t("admin.user.delete_posts_forbidden_because_staff");
} }
if (postCount > this.siteSettings.delete_all_posts_max) { if (postCount > this.siteSettings.delete_all_posts_max) {
return I18n.t('admin.user.cant_delete_all_too_many_posts', {count: this.siteSettings.delete_all_posts_max}); return I18n.t("admin.user.cant_delete_all_too_many_posts", {
count: this.siteSettings.delete_all_posts_max
});
} else { } else {
return I18n.t('admin.user.cant_delete_all_posts', {count: this.siteSettings.delete_user_max_post_age}); return I18n.t("admin.user.cant_delete_all_posts", {
count: this.siteSettings.delete_user_max_post_age
});
} }
}, },
@computed('model.canBeDeleted', 'model.staff') @computed("model.canBeDeleted", "model.staff")
deleteExplanation(canBeDeleted, staff) { deleteExplanation(canBeDeleted, staff) {
if (canBeDeleted) { if (canBeDeleted) {
return null; return null;
} }
if (staff) { if (staff) {
return I18n.t('admin.user.delete_forbidden_because_staff'); return I18n.t("admin.user.delete_forbidden_because_staff");
} else { } else {
return I18n.t('admin.user.delete_forbidden', {count: this.siteSettings.delete_user_max_post_age}); return I18n.t("admin.user.delete_forbidden", {
count: this.siteSettings.delete_user_max_post_age
});
} }
}, },
actions: { actions: {
impersonate() {
impersonate() { return this.get("model").impersonate(); }, return this.get("model").impersonate();
logOut() { return this.get("model").logOut(); }, },
resetBounceScore() { return this.get("model").resetBounceScore(); }, logOut() {
refreshBrowsers() { return this.get("model").refreshBrowsers(); }, return this.get("model").logOut();
approve() { return this.get("model").approve(); }, },
deactivate() { return this.get("model").deactivate(); }, resetBounceScore() {
sendActivationEmail() { return this.get("model").sendActivationEmail(); }, return this.get("model").resetBounceScore();
activate() { return this.get("model").activate(); }, },
revokeAdmin() { return this.get("model").revokeAdmin(); }, refreshBrowsers() {
grantAdmin() { return this.get("model").grantAdmin(); }, return this.get("model").refreshBrowsers();
revokeModeration() { return this.get("model").revokeModeration(); }, },
grantModeration() { return this.get("model").grantModeration(); }, approve() {
saveTrustLevel() { return this.get("model").saveTrustLevel(); }, return this.get("model").approve();
restoreTrustLevel() { return this.get("model").restoreTrustLevel(); }, },
lockTrustLevel(locked) { return this.get("model").lockTrustLevel(locked); }, deactivate() {
unsilence() { return this.get("model").unsilence(); }, return this.get("model").deactivate();
silence() { return this.get("model").silence(); }, },
deleteAllPosts() { return this.get("model").deleteAllPosts(); }, sendActivationEmail() {
anonymize() { return this.get('model').anonymize(); }, return this.get("model").sendActivationEmail();
disableSecondFactor() { return this.get('model').disableSecondFactor(); }, },
activate() {
return this.get("model").activate();
},
revokeAdmin() {
return this.get("model").revokeAdmin();
},
grantAdmin() {
return this.get("model").grantAdmin();
},
revokeModeration() {
return this.get("model").revokeModeration();
},
grantModeration() {
return this.get("model").grantModeration();
},
saveTrustLevel() {
return this.get("model").saveTrustLevel();
},
restoreTrustLevel() {
return this.get("model").restoreTrustLevel();
},
lockTrustLevel(locked) {
return this.get("model").lockTrustLevel(locked);
},
unsilence() {
return this.get("model").unsilence();
},
silence() {
return this.get("model").silence();
},
deleteAllPosts() {
return this.get("model").deleteAllPosts();
},
anonymize() {
return this.get("model").anonymize();
},
disableSecondFactor() {
return this.get("model").disableSecondFactor();
},
clearPenaltyHistory() { clearPenaltyHistory() {
let user = this.get('model'); let user = this.get("model");
return ajax(`/admin/users/${user.get('id')}/penalty_history`, { return ajax(`/admin/users/${user.get("id")}/penalty_history`, {
type: 'DELETE' type: "DELETE"
}).then(() => { })
user.set('tl3_requirements.penalty_counts.total', 0); .then(() => {
}).catch(popupAjaxError); user.set("tl3_requirements.penalty_counts.total", 0);
})
.catch(popupAjaxError);
}, },
destroy() { destroy() {
const postCount = this.get('model.post_count'); const postCount = this.get("model.post_count");
if (postCount <= 5) { if (postCount <= 5) {
return this.get('model').destroy({ deletePosts: true }); return this.get("model").destroy({ deletePosts: true });
} else { } else {
return this.get('model').destroy(); return this.get("model").destroy();
} }
}, },
viewActionLogs() { viewActionLogs() {
this.get('adminTools').showActionLogs(this, { this.get("adminTools").showActionLogs(this, {
target_user: this.get('model.username'), target_user: this.get("model.username")
}); });
}, },
showFlagsReceived() { showFlagsReceived() {
this.get('adminTools').showFlagsReceived(this.get('model')); this.get("adminTools").showFlagsReceived(this.get("model"));
}, },
showSuspendModal() { showSuspendModal() {
this.get('adminTools').showSuspendModal(this.get('model')); this.get("adminTools").showSuspendModal(this.get("model"));
}, },
unsuspend() { unsuspend() {
this.get("model").unsuspend().catch(popupAjaxError); this.get("model")
.unsuspend()
.catch(popupAjaxError);
}, },
showSilenceModal() { showSilenceModal() {
this.get('adminTools').showSilenceModal(this.get('model')); this.get("adminTools").showSilenceModal(this.get("model"));
}, },
toggleUsernameEdit() { toggleUsernameEdit() {
this.set('userUsernameValue', this.get('model.username')); this.set("userUsernameValue", this.get("model.username"));
this.toggleProperty('editingUsername'); this.toggleProperty("editingUsername");
}, },
saveUsername() { saveUsername() {
const oldUsername = this.get('model.username'); const oldUsername = this.get("model.username");
this.set('model.username', this.get('userUsernameValue')); this.set("model.username", this.get("userUsernameValue"));
return ajax(`/users/${oldUsername.toLowerCase()}/preferences/username`, { return ajax(`/users/${oldUsername.toLowerCase()}/preferences/username`, {
data: { new_username: this.get('userUsernameValue') }, data: { new_username: this.get("userUsernameValue") },
type: 'PUT' type: "PUT"
}).catch(e => { })
this.set('model.username', oldUsername); .catch(e => {
popupAjaxError(e); this.set("model.username", oldUsername);
}).finally(() => this.toggleProperty('editingUsername')); popupAjaxError(e);
})
.finally(() => this.toggleProperty("editingUsername"));
}, },
toggleNameEdit() { toggleNameEdit() {
this.set('userNameValue', this.get('model.name')); this.set("userNameValue", this.get("model.name"));
this.toggleProperty('editingName'); this.toggleProperty("editingName");
}, },
saveName() { saveName() {
const oldName = this.get('model.name'); const oldName = this.get("model.name");
this.set('model.name', this.get('userNameValue')); this.set("model.name", this.get("userNameValue"));
return ajax(userPath(`${this.get('model.username').toLowerCase()}.json`), { return ajax(
data: { name: this.get('userNameValue') }, userPath(`${this.get("model.username").toLowerCase()}.json`),
type: 'PUT' {
}).catch(e => { data: { name: this.get("userNameValue") },
this.set('model.name', oldName); type: "PUT"
popupAjaxError(e); }
}).finally(() => this.toggleProperty('editingName')); )
.catch(e => {
this.set("model.name", oldName);
popupAjaxError(e);
})
.finally(() => this.toggleProperty("editingName"));
}, },
toggleTitleEdit() { toggleTitleEdit() {
this.set('userTitleValue', this.get('model.title')); this.set("userTitleValue", this.get("model.title"));
this.toggleProperty('editingTitle'); this.toggleProperty("editingTitle");
}, },
saveTitle() { saveTitle() {
const prevTitle = this.get('userTitleValue'); const prevTitle = this.get("userTitleValue");
this.set('model.title', this.get('userTitleValue')); this.set("model.title", this.get("userTitleValue"));
return ajax(userPath(`${this.get('model.username').toLowerCase()}.json`), { return ajax(
data: {title: this.get('userTitleValue')}, userPath(`${this.get("model.username").toLowerCase()}.json`),
type: 'PUT' {
}).catch(e => { data: { title: this.get("userTitleValue") },
this.set('model.title', prevTitle); type: "PUT"
popupAjaxError(e); }
}).finally(() => this.toggleProperty('editingTitle')); )
.catch(e => {
this.set("model.title", prevTitle);
popupAjaxError(e);
})
.finally(() => this.toggleProperty("editingTitle"));
}, },
generateApiKey() { generateApiKey() {
this.get('model').generateApiKey(); this.get("model").generateApiKey();
}, },
groupAdded(added) { groupAdded(added) {
this.get('model').groupAdded(added).catch(function() { this.get("model")
bootbox.alert(I18n.t('generic_error')); .groupAdded(added)
}); .catch(function() {
bootbox.alert(I18n.t("generic_error"));
});
}, },
groupRemoved(groupId) { groupRemoved(groupId) {
this.get('model').groupRemoved(groupId).catch(function() { this.get("model")
bootbox.alert(I18n.t('generic_error')); .groupRemoved(groupId)
}); .catch(function() {
bootbox.alert(I18n.t("generic_error"));
});
}, },
savePrimaryGroup() { savePrimaryGroup() {
const self = this; const self = this;
return ajax("/admin/users/" + this.get('model.id') + "/primary_group", { return ajax("/admin/users/" + this.get("model.id") + "/primary_group", {
type: 'PUT', type: "PUT",
data: {primary_group_id: this.get('model.primary_group_id')} data: { primary_group_id: this.get("model.primary_group_id") }
}).then(function () { })
self.set('originalPrimaryGroupId', self.get('model.primary_group_id')); .then(function() {
}).catch(function() { self.set(
bootbox.alert(I18n.t('generic_error')); "originalPrimaryGroupId",
}); self.get("model.primary_group_id")
);
})
.catch(function() {
bootbox.alert(I18n.t("generic_error"));
});
}, },
resetPrimaryGroup() { resetPrimaryGroup() {
this.set('model.primary_group_id', this.get('originalPrimaryGroupId')); this.set("model.primary_group_id", this.get("originalPrimaryGroupId"));
}, },
regenerateApiKey() { regenerateApiKey() {
@ -236,7 +309,9 @@ export default Ember.Controller.extend(CanCheckEmails, {
I18n.t("no_value"), I18n.t("no_value"),
I18n.t("yes_value"), I18n.t("yes_value"),
function(result) { function(result) {
if (result) { self.get('model').generateApiKey(); } if (result) {
self.get("model").generateApiKey();
}
} }
); );
}, },
@ -249,10 +324,11 @@ export default Ember.Controller.extend(CanCheckEmails, {
I18n.t("no_value"), I18n.t("no_value"),
I18n.t("yes_value"), I18n.t("yes_value"),
function(result) { function(result) {
if (result) { self.get('model').revokeApiKey(); } if (result) {
self.get("model").revokeApiKey();
}
} }
); );
} }
} }
}); });

View file

@ -1,12 +1,11 @@
import debounce from 'discourse/lib/debounce'; import debounce from "discourse/lib/debounce";
import { i18n } from 'discourse/lib/computed'; import { i18n } from "discourse/lib/computed";
import AdminUser from 'admin/models/admin-user'; import AdminUser from "admin/models/admin-user";
import { observes } from 'ember-addons/ember-computed-decorators'; import { observes } from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
query: null, query: null,
queryParams: ['order', 'ascending'], queryParams: ["order", "ascending"],
order: null, order: null,
ascending: null, ascending: null,
showEmails: false, showEmails: false,
@ -14,72 +13,88 @@ export default Ember.Controller.extend({
listFilter: null, listFilter: null,
selectAll: false, selectAll: false,
queryNew: Em.computed.equal('query', 'new'), queryNew: Em.computed.equal("query", "new"),
queryPending: Em.computed.equal('query', 'pending'), queryPending: Em.computed.equal("query", "pending"),
queryHasApproval: Em.computed.or('queryNew', 'queryPending'), queryHasApproval: Em.computed.or("queryNew", "queryPending"),
showApproval: Em.computed.and('siteSettings.must_approve_users', 'queryHasApproval'), showApproval: Em.computed.and(
searchHint: i18n('search_hint'), "siteSettings.must_approve_users",
hasSelection: Em.computed.gt('selectedCount', 0), "queryHasApproval"
),
searchHint: i18n("search_hint"),
hasSelection: Em.computed.gt("selectedCount", 0),
selectedCount: function() { selectedCount: function() {
var model = this.get('model'); var model = this.get("model");
if (!model || !model.length) return 0; if (!model || !model.length) return 0;
return model.filterBy('selected').length; return model.filterBy("selected").length;
}.property('model.@each.selected'), }.property("model.@each.selected"),
selectAllChanged: function() { selectAllChanged: function() {
var val = this.get('selectAll'); var val = this.get("selectAll");
this.get('model').forEach(function(user) { this.get("model").forEach(function(user) {
if (user.get('can_approve')) { if (user.get("can_approve")) {
user.set('selected', val); user.set("selected", val);
} }
}); });
}.observes('selectAll'), }.observes("selectAll"),
title: function() { title: function() {
return I18n.t('admin.users.titles.' + this.get('query')); return I18n.t("admin.users.titles." + this.get("query"));
}.property('query'), }.property("query"),
_filterUsers: debounce(function() { _filterUsers: debounce(function() {
this._refreshUsers(); this._refreshUsers();
}, 250).observes('listFilter'), }, 250).observes("listFilter"),
@observes("order", "ascending")
@observes('order', 'ascending')
_refreshUsers: function() { _refreshUsers: function() {
this.set('refreshing', true); this.set("refreshing", true);
AdminUser.findAll(this.get('query'), { filter: this.get('listFilter'), show_emails: this.get('showEmails'), order: this.get('order'), ascending: this.get('ascending') }).then( (result) => { AdminUser.findAll(this.get("query"), {
this.set('model', result); filter: this.get("listFilter"),
}).finally( () => { show_emails: this.get("showEmails"),
this.set('refreshing', false); order: this.get("order"),
}); ascending: this.get("ascending")
})
.then(result => {
this.set("model", result);
})
.finally(() => {
this.set("refreshing", false);
});
}, },
actions: { actions: {
approveUsers: function() { approveUsers: function() {
AdminUser.bulkApprove(this.get('model').filterBy('selected')); AdminUser.bulkApprove(this.get("model").filterBy("selected"));
this._refreshUsers(); this._refreshUsers();
}, },
rejectUsers: function() { rejectUsers: function() {
var maxPostAge = this.siteSettings.delete_user_max_post_age; var maxPostAge = this.siteSettings.delete_user_max_post_age;
var controller = this; var controller = this;
AdminUser.bulkReject(this.get('model').filterBy('selected')).then(function(result){ AdminUser.bulkReject(this.get("model").filterBy("selected")).then(
var message = I18n.t("admin.users.reject_successful", {count: result.success}); function(result) {
if (result.failed > 0) { var message = I18n.t("admin.users.reject_successful", {
message += ' ' + I18n.t("admin.users.reject_failures", {count: result.failed}); count: result.success
message += ' ' + I18n.t("admin.user.delete_forbidden", {count: maxPostAge}); });
if (result.failed > 0) {
message +=
" " +
I18n.t("admin.users.reject_failures", { count: result.failed });
message +=
" " +
I18n.t("admin.user.delete_forbidden", { count: maxPostAge });
}
bootbox.alert(message);
controller._refreshUsers();
} }
bootbox.alert(message); );
controller._refreshUsers();
});
}, },
showEmails: function() { showEmails: function() {
this.set('showEmails', true); this.set("showEmails", true);
this._refreshUsers(true); this._refreshUsers(true);
} }
} }
}); });

View file

@ -1,29 +1,37 @@
import computed from 'ember-addons/ember-computed-decorators'; import computed from "ember-addons/ember-computed-decorators";
import WatchedWord from 'admin/models/watched-word'; import WatchedWord from "admin/models/watched-word";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
actionNameKey: null, actionNameKey: null,
adminWatchedWords: Ember.inject.controller(), adminWatchedWords: Ember.inject.controller(),
showWordsList: Ember.computed.or('adminWatchedWords.filtered', 'adminWatchedWords.showWords'), showWordsList: Ember.computed.or(
"adminWatchedWords.filtered",
"adminWatchedWords.showWords"
),
findAction(actionName) { findAction(actionName) {
return (this.get('adminWatchedWords.model') || []).findBy('nameKey', actionName); return (this.get("adminWatchedWords.model") || []).findBy(
"nameKey",
actionName
);
}, },
@computed('actionNameKey', 'adminWatchedWords.model') @computed("actionNameKey", "adminWatchedWords.model")
filteredContent(actionNameKey) { filteredContent(actionNameKey) {
if (!actionNameKey) { return []; } if (!actionNameKey) {
return [];
}
const a = this.findAction(actionNameKey); const a = this.findAction(actionNameKey);
return a ? a.words : []; return a ? a.words : [];
}, },
@computed('actionNameKey') @computed("actionNameKey")
actionDescription(actionNameKey) { actionDescription(actionNameKey) {
return I18n.t('admin.watched_words.action_descriptions.' + actionNameKey); return I18n.t("admin.watched_words.action_descriptions." + actionNameKey);
}, },
@computed('actionNameKey', 'adminWatchedWords.model') @computed("actionNameKey", "adminWatchedWords.model")
wordCount(actionNameKey) { wordCount(actionNameKey) {
const a = this.findAction(actionNameKey); const a = this.findAction(actionNameKey);
return a ? a.words.length : 0; return a ? a.words.length : 0;
@ -31,21 +39,21 @@ export default Ember.Controller.extend({
actions: { actions: {
recordAdded(arg) { recordAdded(arg) {
const a = this.findAction(this.get('actionNameKey')); const a = this.findAction(this.get("actionNameKey"));
if (a) { if (a) {
a.words.unshiftObject(arg); a.words.unshiftObject(arg);
a.incrementProperty('count'); a.incrementProperty("count");
Em.run.schedule('afterRender', () => { Em.run.schedule("afterRender", () => {
// remove from other actions lists // remove from other actions lists
let match = null; let match = null;
this.get('adminWatchedWords.model').forEach(action => { this.get("adminWatchedWords.model").forEach(action => {
if (match) return; if (match) return;
if (action.nameKey !== this.get('actionNameKey')) { if (action.nameKey !== this.get("actionNameKey")) {
match = action.words.findBy('id', arg.id); match = action.words.findBy("id", arg.id);
if (match) { if (match) {
action.words.removeObject(match); action.words.removeObject(match);
action.decrementProperty('count'); action.decrementProperty("count");
} }
} }
}); });
@ -54,18 +62,17 @@ export default Ember.Controller.extend({
}, },
recordRemoved(arg) { recordRemoved(arg) {
const a = this.findAction(this.get('actionNameKey')); const a = this.findAction(this.get("actionNameKey"));
if (a) { if (a) {
a.words.removeObject(arg); a.words.removeObject(arg);
a.decrementProperty('count'); a.decrementProperty("count");
} }
}, },
uploadComplete() { uploadComplete() {
WatchedWord.findAll().then(data => { WatchedWord.findAll().then(data => {
this.set('adminWatchedWords.model', data); this.set("adminWatchedWords.model", data);
}); });
} }
} }
}); });

View file

@ -1,56 +1,56 @@
import debounce from 'discourse/lib/debounce'; import debounce from "discourse/lib/debounce";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
filter: null, filter: null,
filtered: false, filtered: false,
showWords: false, showWords: false,
disableShowWords: Ember.computed.alias('filtered'), disableShowWords: Ember.computed.alias("filtered"),
regularExpressions: null, regularExpressions: null,
filterContentNow() { filterContentNow() {
if (!!Ember.isEmpty(this.get("allWatchedWords"))) return;
if (!!Ember.isEmpty(this.get('allWatchedWords'))) return;
let filter; let filter;
if (this.get('filter')) { if (this.get("filter")) {
filter = this.get('filter').toLowerCase(); filter = this.get("filter").toLowerCase();
} }
if (filter === undefined || filter.length < 1) { if (filter === undefined || filter.length < 1) {
this.set('model', this.get('allWatchedWords')); this.set("model", this.get("allWatchedWords"));
return; return;
} }
const matchesByAction = []; const matchesByAction = [];
this.get('allWatchedWords').forEach(wordsForAction => { this.get("allWatchedWords").forEach(wordsForAction => {
const wordRecords = wordsForAction.words.filter(wordRecord => { const wordRecords = wordsForAction.words.filter(wordRecord => {
return (wordRecord.word.indexOf(filter) > -1); return wordRecord.word.indexOf(filter) > -1;
}); });
matchesByAction.pushObject( Ember.Object.create({ matchesByAction.pushObject(
nameKey: wordsForAction.nameKey, Ember.Object.create({
name: wordsForAction.name, nameKey: wordsForAction.nameKey,
words: wordRecords, name: wordsForAction.name,
count: wordRecords.length words: wordRecords,
}) ); count: wordRecords.length
})
);
}); });
this.set('model', matchesByAction); this.set("model", matchesByAction);
}, },
filterContent: debounce(function() { filterContent: debounce(function() {
this.filterContentNow(); this.filterContentNow();
this.set('filtered', !Ember.isEmpty(this.get('filter'))); this.set("filtered", !Ember.isEmpty(this.get("filter")));
}, 250).observes('filter'), }, 250).observes("filter"),
actions: { actions: {
clearFilter() { clearFilter() {
this.setProperties({ filter: '' }); this.setProperties({ filter: "" });
}, },
toggleMenu() { toggleMenu() {
$('.admin-detail').toggleClass('mobile-closed mobile-open'); $(".admin-detail").toggleClass("mobile-closed mobile-open");
} }
} }
}); });

View file

@ -1,28 +1,31 @@
import { ajax } from 'discourse/lib/ajax'; import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
import computed from 'ember-addons/ember-computed-decorators'; import computed from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
pingDisabled: false, pingDisabled: false,
incomingEventIds: [], incomingEventIds: [],
incomingCount: Ember.computed.alias("incomingEventIds.length"), incomingCount: Ember.computed.alias("incomingEventIds.length"),
@computed('incomingCount') @computed("incomingCount")
hasIncoming(incomingCount) { hasIncoming(incomingCount) {
return incomingCount > 0; return incomingCount > 0;
}, },
subscribe() { subscribe() {
this.messageBus.subscribe(`/web_hook_events/${this.get('model.extras.web_hook_id')}`, data => { this.messageBus.subscribe(
if (data.event_type === 'ping') { `/web_hook_events/${this.get("model.extras.web_hook_id")}`,
this.set('pingDisabled', false); data => {
if (data.event_type === "ping") {
this.set("pingDisabled", false);
}
this._addIncoming(data.web_hook_event_id);
} }
this._addIncoming(data.web_hook_event_id); );
});
}, },
unsubscribe() { unsubscribe() {
this.messageBus.unsubscribe('/web_hook_events/*'); this.messageBus.unsubscribe("/web_hook_events/*");
}, },
_addIncoming(eventId) { _addIncoming(eventId) {
@ -35,28 +38,33 @@ export default Ember.Controller.extend({
actions: { actions: {
loadMore() { loadMore() {
this.get('model').loadMore(); this.get("model").loadMore();
}, },
ping() { ping() {
this.set('pingDisabled', true); this.set("pingDisabled", true);
ajax(`/admin/api/web_hooks/${this.get('model.extras.web_hook_id')}/ping`, { ajax(
type: 'POST' `/admin/api/web_hooks/${this.get("model.extras.web_hook_id")}/ping`,
}).catch(error => { {
this.set('pingDisabled', false); type: "POST"
}
).catch(error => {
this.set("pingDisabled", false);
popupAjaxError(error); popupAjaxError(error);
}); });
}, },
showInserted() { showInserted() {
const webHookId = this.get('model.extras.web_hook_id'); const webHookId = this.get("model.extras.web_hook_id");
ajax(`/admin/api/web_hooks/${webHookId}/events/bulk`, { ajax(`/admin/api/web_hooks/${webHookId}/events/bulk`, {
type: 'GET', type: "GET",
data: { ids: this.get('incomingEventIds') } data: { ids: this.get("incomingEventIds") }
}).then(data => { }).then(data => {
const objects = data.map(event => this.store.createRecord('web-hook-event', event)); const objects = data.map(event =>
this.store.createRecord("web-hook-event", event)
);
this.get("model").unshiftObjects(objects); this.get("model").unshiftObjects(objects);
this.set("incomingEventIds", []); this.set("incomingEventIds", []);
}); });

View file

@ -1,104 +1,131 @@
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
import { extractDomainFromUrl } from 'discourse/lib/utilities'; import { extractDomainFromUrl } from "discourse/lib/utilities";
import computed from 'ember-addons/ember-computed-decorators'; import computed from "ember-addons/ember-computed-decorators";
import InputValidation from 'discourse/models/input-validation'; import InputValidation from "discourse/models/input-validation";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
adminWebHooks: Ember.inject.controller(), adminWebHooks: Ember.inject.controller(),
eventTypes: Ember.computed.alias('adminWebHooks.eventTypes'), eventTypes: Ember.computed.alias("adminWebHooks.eventTypes"),
defaultEventTypes: Ember.computed.alias('adminWebHooks.defaultEventTypes'), defaultEventTypes: Ember.computed.alias("adminWebHooks.defaultEventTypes"),
contentTypes: Ember.computed.alias('adminWebHooks.contentTypes'), contentTypes: Ember.computed.alias("adminWebHooks.contentTypes"),
@computed('model.isSaving', 'saved', 'saveButtonDisabled') @computed("model.isSaving", "saved", "saveButtonDisabled")
savingStatus(isSaving, saved, saveButtonDisabled) { savingStatus(isSaving, saved, saveButtonDisabled) {
if (isSaving) { if (isSaving) {
return I18n.t('saving'); return I18n.t("saving");
} else if (!saveButtonDisabled && saved) { } else if (!saveButtonDisabled && saved) {
return I18n.t('saved'); return I18n.t("saved");
} }
// Use side effect of validation to clear saved text // Use side effect of validation to clear saved text
this.set('saved', false); this.set("saved", false);
return ''; return "";
}, },
@computed('model.isNew') @computed("model.isNew")
saveButtonText(isNew) { saveButtonText(isNew) {
return isNew ? I18n.t('admin.web_hooks.create') : I18n.t('admin.web_hooks.save'); return isNew
? I18n.t("admin.web_hooks.create")
: I18n.t("admin.web_hooks.save");
}, },
@computed('model.secret') @computed("model.secret")
secretValidation(secret) { secretValidation(secret) {
if (!Ember.isEmpty(secret)) { if (!Ember.isEmpty(secret)) {
if (secret.indexOf(' ') !== -1) { if (secret.indexOf(" ") !== -1) {
return InputValidation.create({ return InputValidation.create({
failed: true, failed: true,
reason: I18n.t('admin.web_hooks.secret_invalid') reason: I18n.t("admin.web_hooks.secret_invalid")
}); });
} }
if (secret.length < 12) { if (secret.length < 12) {
return InputValidation.create({ return InputValidation.create({
failed: true, failed: true,
reason: I18n.t('admin.web_hooks.secret_too_short') reason: I18n.t("admin.web_hooks.secret_too_short")
}); });
} }
} }
}, },
@computed('model.wildcard_web_hook', 'model.web_hook_event_types.[]') @computed("model.wildcard_web_hook", "model.web_hook_event_types.[]")
eventTypeValidation(isWildcard, eventTypes) { eventTypeValidation(isWildcard, eventTypes) {
if (!isWildcard && Ember.isEmpty(eventTypes)) { if (!isWildcard && Ember.isEmpty(eventTypes)) {
return InputValidation.create({ return InputValidation.create({
failed: true, failed: true,
reason: I18n.t('admin.web_hooks.event_type_missing') reason: I18n.t("admin.web_hooks.event_type_missing")
}); });
} }
}, },
@computed('model.isSaving', 'secretValidation', 'eventTypeValidation') @computed("model.isSaving", "secretValidation", "eventTypeValidation")
saveButtonDisabled(isSaving, secretValidation, eventTypeValidation) { saveButtonDisabled(isSaving, secretValidation, eventTypeValidation) {
return isSaving ? false : secretValidation || eventTypeValidation; return isSaving ? false : secretValidation || eventTypeValidation;
}, },
actions: { actions: {
save() { save() {
this.set('saved', false); this.set("saved", false);
const url = extractDomainFromUrl(this.get('model.payload_url')); const url = extractDomainFromUrl(this.get("model.payload_url"));
const model = this.get('model'); const model = this.get("model");
const isNew = model.get('isNew'); const isNew = model.get("isNew");
const saveWebHook = () => { const saveWebHook = () => {
return model.save().then(() => { return model
this.set('saved', true); .save()
this.get('adminWebHooks').get('model').addObject(model); .then(() => {
this.set("saved", true);
this.get("adminWebHooks")
.get("model")
.addObject(model);
if (isNew) { if (isNew) {
this.transitionToRoute('adminWebHooks.show', model.get('id')); this.transitionToRoute("adminWebHooks.show", model.get("id"));
} }
}).catch(popupAjaxError); })
.catch(popupAjaxError);
}; };
if (url === 'localhost' || url.match(/192\.168\.\d+\.\d+/) || url.match(/127\.\d+\.\d+\.\d+/) || url === Discourse.BaseUrl) { if (
return bootbox.confirm(I18n.t('admin.web_hooks.warn_local_payload_url'), I18n.t('no_value'), I18n.t('yes_value'), result => { url === "localhost" ||
if (result) { url.match(/192\.168\.\d+\.\d+/) ||
return saveWebHook(); url.match(/127\.\d+\.\d+\.\d+/) ||
url === Discourse.BaseUrl
) {
return bootbox.confirm(
I18n.t("admin.web_hooks.warn_local_payload_url"),
I18n.t("no_value"),
I18n.t("yes_value"),
result => {
if (result) {
return saveWebHook();
}
} }
}); );
} }
return saveWebHook(); return saveWebHook();
}, },
destroy() { destroy() {
return bootbox.confirm(I18n.t('admin.web_hooks.delete_confirm'), I18n.t('no_value'), I18n.t('yes_value'), result => { return bootbox.confirm(
if (result) { I18n.t("admin.web_hooks.delete_confirm"),
const model = this.get('model'); I18n.t("no_value"),
model.destroyRecord().then(() => { I18n.t("yes_value"),
this.get('adminWebHooks').get('model').removeObject(model); result => {
this.transitionToRoute('adminWebHooks'); if (result) {
}).catch(popupAjaxError); const model = this.get("model");
model
.destroyRecord()
.then(() => {
this.get("adminWebHooks")
.get("model")
.removeObject(model);
this.transitionToRoute("adminWebHooks");
})
.catch(popupAjaxError);
}
} }
}); );
} }
} }
}); });

View file

@ -1,19 +1,27 @@
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from "discourse/lib/ajax-error";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
actions: { actions: {
destroy(webhook) { destroy(webhook) {
return bootbox.confirm(I18n.t('admin.web_hooks.delete_confirm'), I18n.t('no_value'), I18n.t('yes_value'), result => { return bootbox.confirm(
if (result) { I18n.t("admin.web_hooks.delete_confirm"),
webhook.destroyRecord().then(() => { I18n.t("no_value"),
this.get('model').removeObject(webhook); I18n.t("yes_value"),
}).catch(popupAjaxError); result => {
if (result) {
webhook
.destroyRecord()
.then(() => {
this.get("model").removeObject(webhook);
})
.catch(popupAjaxError);
}
} }
}); );
}, },
loadMore() { loadMore() {
this.get('model').loadMore(); this.get("model").loadMore();
} }
} }
}); });

Some files were not shown because too many files have changed in this diff Show more