mirror of
https://github.com/discourse/discourse.git
synced 2026-08-07 11:45:21 -05:00
REFACTOR: Support bundling our admin section as an ember addon
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
import I18n from "I18n";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
import { and, not } from "@ember/object/computed";
|
||||
import Controller, { inject as controller } from "@ember/controller";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import discourseComputed, { observes } from "discourse-common/utils/decorators";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
|
||||
const THEME_FIELD_VARIABLE_TYPE_IDS = [2, 3, 4];
|
||||
|
||||
const SCSS_VARIABLE_NAMES = [
|
||||
// common/foundation/colors.scss
|
||||
"primary",
|
||||
"secondary",
|
||||
"tertiary",
|
||||
"quaternary",
|
||||
"header_background",
|
||||
"header_primary",
|
||||
"highlight",
|
||||
"danger",
|
||||
"success",
|
||||
"love",
|
||||
// common/foundation/math.scss
|
||||
"E",
|
||||
"PI",
|
||||
"LN2",
|
||||
"SQRT2",
|
||||
// common/foundation/variables.scss
|
||||
"small-width",
|
||||
"medium-width",
|
||||
"large-width",
|
||||
"google",
|
||||
"instagram",
|
||||
"facebook",
|
||||
"cas",
|
||||
"twitter",
|
||||
"github",
|
||||
"base-font-size",
|
||||
"base-line-height",
|
||||
"base-font-family",
|
||||
"primary-low",
|
||||
"primary-medium",
|
||||
"secondary-low",
|
||||
"secondary-medium",
|
||||
"tertiary-low",
|
||||
"quaternary-low",
|
||||
"highlight-low",
|
||||
"highlight-medium",
|
||||
"danger-low",
|
||||
"danger-medium",
|
||||
"success-low",
|
||||
"love-low",
|
||||
];
|
||||
|
||||
export default Controller.extend(ModalFunctionality, {
|
||||
adminCustomizeThemesShow: controller(),
|
||||
|
||||
uploadUrl: "/admin/themes/upload_asset",
|
||||
|
||||
onShow() {
|
||||
this.set("name", null);
|
||||
this.set("fileSelected", false);
|
||||
},
|
||||
|
||||
enabled: and("nameValid", "fileSelected"),
|
||||
disabled: not("enabled"),
|
||||
|
||||
@discourseComputed("name", "adminCustomizeThemesShow.model.theme_fields")
|
||||
errorMessage(name, themeFields) {
|
||||
if (name) {
|
||||
if (!name.match(/^[a-z_][a-z0-9_-]*$/i)) {
|
||||
return I18n.t(
|
||||
"admin.customize.theme.variable_name_error.invalid_syntax"
|
||||
);
|
||||
} else if (SCSS_VARIABLE_NAMES.includes(name.toLowerCase())) {
|
||||
return I18n.t("admin.customize.theme.variable_name_error.no_overwrite");
|
||||
} else if (
|
||||
themeFields.some(
|
||||
(tf) =>
|
||||
THEME_FIELD_VARIABLE_TYPE_IDS.includes(tf.type_id) &&
|
||||
name === tf.name
|
||||
)
|
||||
) {
|
||||
return I18n.t(
|
||||
"admin.customize.theme.variable_name_error.must_be_unique"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
@discourseComputed("errorMessage")
|
||||
nameValid(errorMessage) {
|
||||
return null === errorMessage;
|
||||
},
|
||||
|
||||
@observes("name")
|
||||
uploadChanged() {
|
||||
const file = $("#file-input")[0];
|
||||
this.set("fileSelected", file && file.files[0]);
|
||||
},
|
||||
|
||||
actions: {
|
||||
updateName() {
|
||||
let name = this.name;
|
||||
if (isEmpty(name)) {
|
||||
name = $("#file-input")[0].files[0].name;
|
||||
this.set("name", name.split(".")[0]);
|
||||
}
|
||||
this.uploadChanged();
|
||||
},
|
||||
|
||||
upload() {
|
||||
const file = $("#file-input")[0].files[0];
|
||||
|
||||
const options = {
|
||||
type: "POST",
|
||||
processData: false,
|
||||
contentType: false,
|
||||
data: new FormData(),
|
||||
};
|
||||
|
||||
options.data.append("file", file);
|
||||
|
||||
ajax(this.uploadUrl, options)
|
||||
.then((result) => {
|
||||
const upload = {
|
||||
upload_id: result.upload_id,
|
||||
name: this.name,
|
||||
original_filename: file.name,
|
||||
};
|
||||
this.adminCustomizeThemesShow.send("addUpload", upload);
|
||||
this.send("closeModal");
|
||||
})
|
||||
.catch((e) => {
|
||||
popupAjaxError(e);
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,59 @@
|
||||
import I18n from "I18n";
|
||||
import { alias, map } from "@ember/object/computed";
|
||||
import Controller from "@ember/controller";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { escapeExpression } from "discourse/lib/utilities";
|
||||
|
||||
export default Controller.extend({
|
||||
sample: alias("model.sample"),
|
||||
errors: alias("model.errors"),
|
||||
count: alias("model.grant_count"),
|
||||
|
||||
@discourseComputed("count", "sample.length")
|
||||
countWarning(count, sampleLength) {
|
||||
if (count <= 10) {
|
||||
return sampleLength !== count;
|
||||
} else {
|
||||
return sampleLength !== 10;
|
||||
}
|
||||
},
|
||||
|
||||
@discourseComputed("model.query_plan")
|
||||
hasQueryPlan(queryPlan) {
|
||||
return !!queryPlan;
|
||||
},
|
||||
|
||||
@discourseComputed("model.query_plan")
|
||||
queryPlanHtml(queryPlan) {
|
||||
let output = `<pre class="badge-query-plan">`;
|
||||
|
||||
queryPlan.forEach((linehash) => {
|
||||
output += escapeExpression(linehash["QUERY PLAN"]);
|
||||
output += "<br>";
|
||||
});
|
||||
|
||||
output += "</pre>";
|
||||
return output;
|
||||
},
|
||||
|
||||
processedSample: map("model.sample", (grant) => {
|
||||
let i18nKey = "admin.badges.preview.grant.with";
|
||||
const i18nParams = { username: escapeExpression(grant.username) };
|
||||
|
||||
if (grant.post_id) {
|
||||
i18nKey += "_post";
|
||||
i18nParams.link = `<a href="/p/${grant.post_id}" data-auto-route="true">
|
||||
${escapeExpression(grant.title)}
|
||||
</a>`;
|
||||
}
|
||||
|
||||
if (grant.granted_at) {
|
||||
i18nKey += "_time";
|
||||
i18nParams.time = escapeExpression(
|
||||
moment(grant.granted_at).format(I18n.t("dates.long_with_year"))
|
||||
);
|
||||
}
|
||||
|
||||
return I18n.t(i18nKey, i18nParams);
|
||||
}),
|
||||
});
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
import Controller, { inject as controller } from "@ember/controller";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
|
||||
export default Controller.extend(ModalFunctionality, {
|
||||
adminCustomizeColors: controller(),
|
||||
|
||||
selectedBaseThemeId: null,
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
|
||||
const defaultScheme = this.get(
|
||||
"adminCustomizeColors.baseColorSchemes.0.base_scheme_id"
|
||||
);
|
||||
this.set("selectedBaseThemeId", defaultScheme);
|
||||
},
|
||||
|
||||
actions: {
|
||||
selectBase() {
|
||||
this.adminCustomizeColors.send(
|
||||
"newColorSchemeWithBase",
|
||||
this.selectedBaseThemeId
|
||||
);
|
||||
this.send("closeModal");
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,85 @@
|
||||
import I18n from "I18n";
|
||||
import Controller from "@ember/controller";
|
||||
import { A } from "@ember/array";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import { observes } from "discourse-common/utils/decorators";
|
||||
import bootbox from "bootbox";
|
||||
|
||||
export default Controller.extend(ModalFunctionality, {
|
||||
@observes("model")
|
||||
modelChanged() {
|
||||
const model = this.model;
|
||||
const copy = A();
|
||||
const store = this.store;
|
||||
|
||||
if (model) {
|
||||
model.forEach((o) =>
|
||||
copy.pushObject(store.createRecord("badge-grouping", o))
|
||||
);
|
||||
}
|
||||
|
||||
this.set("workingCopy", copy);
|
||||
},
|
||||
|
||||
moveItem(item, delta) {
|
||||
const copy = this.workingCopy;
|
||||
const index = copy.indexOf(item);
|
||||
if (index + delta < 0 || index + delta >= copy.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
copy.removeAt(index);
|
||||
copy.insertAt(index + delta, item);
|
||||
},
|
||||
|
||||
actions: {
|
||||
up(item) {
|
||||
this.moveItem(item, -1);
|
||||
},
|
||||
down(item) {
|
||||
this.moveItem(item, 1);
|
||||
},
|
||||
delete(item) {
|
||||
this.workingCopy.removeObject(item);
|
||||
},
|
||||
cancel() {
|
||||
this.setProperties({ model: null, workingCopy: null });
|
||||
this.send("closeModal");
|
||||
},
|
||||
edit(item) {
|
||||
item.set("editing", true);
|
||||
},
|
||||
save(item) {
|
||||
item.set("editing", false);
|
||||
},
|
||||
add() {
|
||||
const obj = this.store.createRecord("badge-grouping", {
|
||||
editing: true,
|
||||
name: I18n.t("admin.badges.badge_grouping"),
|
||||
});
|
||||
this.workingCopy.pushObject(obj);
|
||||
},
|
||||
saveAll() {
|
||||
let items = this.workingCopy;
|
||||
const groupIds = items.map((i) => i.get("id") || -1);
|
||||
const names = items.map((i) => i.get("name"));
|
||||
|
||||
ajax("/admin/badges/badge_groupings", {
|
||||
data: { ids: groupIds, names },
|
||||
type: "POST",
|
||||
}).then(
|
||||
(data) => {
|
||||
items = this.model;
|
||||
items.clear();
|
||||
data.badge_groupings.forEach((g) => {
|
||||
items.pushObject(this.store.createRecord("badge-grouping", g));
|
||||
});
|
||||
this.setProperties({ model: null, workingCopy: null });
|
||||
this.send("closeModal");
|
||||
},
|
||||
() => bootbox.alert(I18n.t("generic_error"))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import Controller from "@ember/controller";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import IncomingEmail from "admin/models/incoming-email";
|
||||
import { longDate } from "discourse/lib/formatter";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
|
||||
export default Controller.extend(ModalFunctionality, {
|
||||
@discourseComputed("model.date")
|
||||
date(d) {
|
||||
return longDate(d);
|
||||
},
|
||||
|
||||
load(id) {
|
||||
return IncomingEmail.find(id).then((result) => this.set("model", result));
|
||||
},
|
||||
|
||||
loadFromBounced(id) {
|
||||
return IncomingEmail.findByBounced(id)
|
||||
.then((result) => this.set("model", result))
|
||||
.catch((error) => {
|
||||
this.send("closeModal");
|
||||
popupAjaxError(error);
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,199 @@
|
||||
import I18n from "I18n";
|
||||
import { equal, match, alias } from "@ember/object/computed";
|
||||
import Controller, { inject as controller } from "@ember/controller";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import discourseComputed, { observes } from "discourse-common/utils/decorators";
|
||||
import { THEMES, COMPONENTS } from "admin/models/theme";
|
||||
import { POPULAR_THEMES } from "discourse-common/helpers/popular-themes";
|
||||
import { set } from "@ember/object";
|
||||
|
||||
const MIN_NAME_LENGTH = 4;
|
||||
|
||||
export default Controller.extend(ModalFunctionality, {
|
||||
adminCustomizeThemes: controller(),
|
||||
themesController: controller("adminCustomizeThemes"),
|
||||
popular: equal("selection", "popular"),
|
||||
local: equal("selection", "local"),
|
||||
remote: equal("selection", "remote"),
|
||||
create: equal("selection", "create"),
|
||||
selection: "popular",
|
||||
loading: false,
|
||||
keyGenUrl: "/admin/themes/generate_key_pair",
|
||||
importUrl: "/admin/themes/import",
|
||||
recordType: "theme",
|
||||
checkPrivate: match("uploadUrl", /^git/),
|
||||
localFile: null,
|
||||
uploadUrl: null,
|
||||
urlPlaceholder: "https://github.com/discourse/sample_theme",
|
||||
advancedVisible: false,
|
||||
selectedType: alias("themesController.currentTab"),
|
||||
component: equal("selectedType", COMPONENTS),
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
|
||||
this.createTypes = [
|
||||
{ name: I18n.t("admin.customize.theme.theme"), value: THEMES },
|
||||
{ name: I18n.t("admin.customize.theme.component"), value: COMPONENTS },
|
||||
];
|
||||
},
|
||||
|
||||
@discourseComputed("themesController.installedThemes")
|
||||
themes(installedThemes) {
|
||||
return POPULAR_THEMES.map((t) => {
|
||||
if (installedThemes.includes(t.name)) {
|
||||
set(t, "installed", true);
|
||||
}
|
||||
return t;
|
||||
});
|
||||
},
|
||||
|
||||
@discourseComputed(
|
||||
"loading",
|
||||
"remote",
|
||||
"uploadUrl",
|
||||
"local",
|
||||
"localFile",
|
||||
"create",
|
||||
"nameTooShort"
|
||||
)
|
||||
installDisabled(
|
||||
isLoading,
|
||||
isRemote,
|
||||
uploadUrl,
|
||||
isLocal,
|
||||
localFile,
|
||||
isCreate,
|
||||
nameTooShort
|
||||
) {
|
||||
return (
|
||||
isLoading ||
|
||||
(isRemote && !uploadUrl) ||
|
||||
(isLocal && !localFile) ||
|
||||
(isCreate && nameTooShort)
|
||||
);
|
||||
},
|
||||
|
||||
@observes("privateChecked")
|
||||
privateWasChecked() {
|
||||
this.privateChecked
|
||||
? this.set("urlPlaceholder", "git@github.com:discourse/sample_theme.git")
|
||||
: this.set("urlPlaceholder", "https://github.com/discourse/sample_theme");
|
||||
|
||||
const checked = this.privateChecked;
|
||||
if (checked && !this._keyLoading) {
|
||||
this._keyLoading = true;
|
||||
ajax(this.keyGenUrl, { type: "POST" })
|
||||
.then((pair) => {
|
||||
this.setProperties({
|
||||
privateKey: pair.private_key,
|
||||
publicKey: pair.public_key,
|
||||
});
|
||||
})
|
||||
.catch(popupAjaxError)
|
||||
.finally(() => {
|
||||
this._keyLoading = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@discourseComputed("name")
|
||||
nameTooShort(name) {
|
||||
return !name || name.length < MIN_NAME_LENGTH;
|
||||
},
|
||||
|
||||
@discourseComputed("component")
|
||||
placeholder(component) {
|
||||
if (component) {
|
||||
return I18n.t("admin.customize.theme.component_name");
|
||||
} else {
|
||||
return I18n.t("admin.customize.theme.theme_name");
|
||||
}
|
||||
},
|
||||
|
||||
@discourseComputed("selection")
|
||||
submitLabel(selection) {
|
||||
return `admin.customize.theme.${
|
||||
selection === "create" ? "create" : "install"
|
||||
}`;
|
||||
},
|
||||
|
||||
@discourseComputed("privateChecked", "checkPrivate", "publicKey")
|
||||
showPublicKey(privateChecked, checkPrivate, publicKey) {
|
||||
return privateChecked && checkPrivate && publicKey;
|
||||
},
|
||||
|
||||
actions: {
|
||||
uploadLocaleFile() {
|
||||
this.set("localFile", $("#file-input")[0].files[0]);
|
||||
},
|
||||
|
||||
toggleAdvanced() {
|
||||
this.toggleProperty("advancedVisible");
|
||||
},
|
||||
|
||||
installThemeFromList(url) {
|
||||
this.set("uploadUrl", url);
|
||||
this.send("installTheme");
|
||||
},
|
||||
|
||||
installTheme() {
|
||||
if (this.create) {
|
||||
this.set("loading", true);
|
||||
const theme = this.store.createRecord(this.recordType);
|
||||
theme
|
||||
.save({ name: this.name, component: this.component })
|
||||
.then(() => {
|
||||
this.themesController.send("addTheme", theme);
|
||||
this.send("closeModal");
|
||||
})
|
||||
.catch(popupAjaxError)
|
||||
.finally(() => this.set("loading", false));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let options = {
|
||||
type: "POST",
|
||||
};
|
||||
|
||||
if (this.local) {
|
||||
options.processData = false;
|
||||
options.contentType = false;
|
||||
options.data = new FormData();
|
||||
options.data.append("theme", this.localFile);
|
||||
}
|
||||
|
||||
if (this.remote || this.popular) {
|
||||
options.data = {
|
||||
remote: this.uploadUrl,
|
||||
branch: this.branch,
|
||||
};
|
||||
|
||||
if (this.privateChecked) {
|
||||
options.data.private_key = this.privateKey;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.get("model.user_id")) {
|
||||
// Used by theme-creator
|
||||
options.data["user_id"] = this.get("model.user_id");
|
||||
}
|
||||
|
||||
this.set("loading", true);
|
||||
ajax(this.importUrl, options)
|
||||
.then((result) => {
|
||||
const theme = this.store.createRecord(this.recordType, result.theme);
|
||||
this.adminCustomizeThemes.send("addTheme", theme);
|
||||
this.send("closeModal");
|
||||
})
|
||||
.then(() => {
|
||||
this.setProperties({ privateKey: null, publicKey: null });
|
||||
})
|
||||
.catch(popupAjaxError)
|
||||
.finally(() => this.set("loading", false));
|
||||
},
|
||||
},
|
||||
});
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
import I18n from "I18n";
|
||||
import Controller, { inject as controller } from "@ember/controller";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { alias } from "@ember/object/computed";
|
||||
import { action } from "@ember/object";
|
||||
|
||||
export default Controller.extend(ModalFunctionality, {
|
||||
adminUserIndex: controller(),
|
||||
username: alias("model.username"),
|
||||
targetUsername: alias("model.targetUsername"),
|
||||
|
||||
onShow() {
|
||||
this.set("value", null);
|
||||
},
|
||||
|
||||
@discourseComputed("username", "targetUsername")
|
||||
text(username, targetUsername) {
|
||||
return I18n.t(`admin.user.merge.confirmation.text`, {
|
||||
username,
|
||||
targetUsername,
|
||||
});
|
||||
},
|
||||
|
||||
@discourseComputed("value", "text")
|
||||
mergeDisabled(value, text) {
|
||||
return !value || text !== value;
|
||||
},
|
||||
|
||||
@action
|
||||
confirm() {
|
||||
this.adminUserIndex.send("merge", this.targetUsername);
|
||||
this.send("closeModal");
|
||||
},
|
||||
|
||||
@action
|
||||
close() {
|
||||
this.send("closeModal");
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
import Controller, { inject as controller } from "@ember/controller";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { alias } from "@ember/object/computed";
|
||||
import { action } from "@ember/object";
|
||||
|
||||
export default Controller.extend(ModalFunctionality, {
|
||||
adminUserIndex: controller(),
|
||||
username: alias("model.username"),
|
||||
|
||||
onShow() {
|
||||
this.set("targetUsername", null);
|
||||
},
|
||||
|
||||
@discourseComputed("username", "targetUsername")
|
||||
mergeDisabled(username, targetUsername) {
|
||||
return !targetUsername || username === targetUsername;
|
||||
},
|
||||
|
||||
@action
|
||||
showConfirmation() {
|
||||
this.send("closeModal");
|
||||
this.adminUserIndex.send("showMergeConfirmation", this.targetUsername);
|
||||
},
|
||||
|
||||
@action
|
||||
close() {
|
||||
this.send("closeModal");
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,45 @@
|
||||
import I18n from "I18n";
|
||||
import Controller from "@ember/controller";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import bootbox from "bootbox";
|
||||
|
||||
export default Controller.extend(ModalFunctionality, {
|
||||
loading: true,
|
||||
reseeding: false,
|
||||
categories: null,
|
||||
topics: null,
|
||||
|
||||
onShow() {
|
||||
ajax("/admin/customize/reseed")
|
||||
.then((result) => {
|
||||
this.setProperties({
|
||||
categories: result.categories,
|
||||
topics: result.topics,
|
||||
});
|
||||
})
|
||||
.finally(() => this.set("loading", false));
|
||||
},
|
||||
|
||||
_extractSelectedIds(items) {
|
||||
return items.filter((item) => item.selected).map((item) => item.id);
|
||||
},
|
||||
|
||||
actions: {
|
||||
reseed() {
|
||||
this.set("reseeding", true);
|
||||
ajax("/admin/customize/reseed", {
|
||||
data: {
|
||||
category_ids: this._extractSelectedIds(this.categories),
|
||||
topic_ids: this._extractSelectedIds(this.topics),
|
||||
},
|
||||
type: "POST",
|
||||
})
|
||||
.then(
|
||||
() => this.send("closeModal"),
|
||||
() => bootbox.alert(I18n.t("generic_error"))
|
||||
)
|
||||
.finally(() => this.set("reseeding", false));
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
import Controller from "@ember/controller";
|
||||
import PenaltyController from "admin/mixins/penalty-controller";
|
||||
|
||||
export default Controller.extend(PenaltyController, {
|
||||
silenceUntil: null,
|
||||
silencing: false,
|
||||
|
||||
onShow() {
|
||||
this.resetModal();
|
||||
this.setProperties({ silenceUntil: null, silencing: false });
|
||||
},
|
||||
|
||||
@discourseComputed("silenceUntil", "reason", "silencing")
|
||||
submitDisabled(silenceUntil, reason, silencing) {
|
||||
return silencing || isEmpty(silenceUntil) || !reason || reason.length < 1;
|
||||
},
|
||||
|
||||
actions: {
|
||||
silence() {
|
||||
if (this.submitDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.set("silencing", true);
|
||||
this.penalize(() => {
|
||||
return this.user.silence({
|
||||
silenced_till: this.silenceUntil,
|
||||
reason: this.reason,
|
||||
message: this.message,
|
||||
post_id: this.postId,
|
||||
post_action: this.postAction,
|
||||
post_edit: this.postEdit,
|
||||
});
|
||||
}).finally(() => this.set("silencing", false));
|
||||
},
|
||||
},
|
||||
});
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import Controller from "@ember/controller";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
|
||||
export default Controller.extend(ModalFunctionality);
|
||||
@@ -0,0 +1,22 @@
|
||||
import Controller, { inject as controller } from "@ember/controller";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
|
||||
export default Controller.extend(ModalFunctionality, {
|
||||
adminBackupsLogs: controller(),
|
||||
|
||||
actions: {
|
||||
startBackupWithUploads() {
|
||||
this.send("closeModal");
|
||||
this.send("startBackup", true);
|
||||
},
|
||||
|
||||
startBackupWithoutUploads() {
|
||||
this.send("closeModal");
|
||||
this.send("startBackup", false);
|
||||
},
|
||||
|
||||
cancel() {
|
||||
this.send("closeModal");
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
import Controller from "@ember/controller";
|
||||
import PenaltyController from "admin/mixins/penalty-controller";
|
||||
|
||||
export default Controller.extend(PenaltyController, {
|
||||
suspendUntil: null,
|
||||
suspending: false,
|
||||
|
||||
onShow() {
|
||||
this.resetModal();
|
||||
this.setProperties({ suspendUntil: null, suspending: false });
|
||||
},
|
||||
|
||||
@discourseComputed("suspendUntil", "reason", "suspending")
|
||||
submitDisabled(suspendUntil, reason, suspending) {
|
||||
return suspending || isEmpty(suspendUntil) || !reason || reason.length < 1;
|
||||
},
|
||||
|
||||
actions: {
|
||||
suspend() {
|
||||
if (this.submitDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.set("suspending", true);
|
||||
|
||||
this.penalize(() => {
|
||||
return this.user.suspend({
|
||||
suspend_until: this.suspendUntil,
|
||||
reason: this.reason,
|
||||
message: this.message,
|
||||
post_id: this.postId,
|
||||
post_action: this.postAction,
|
||||
post_edit: this.postEdit,
|
||||
});
|
||||
}).finally(() => this.set("suspending", false));
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
import Controller from "@ember/controller";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
|
||||
export default Controller.extend(ModalFunctionality, {
|
||||
loadDiff() {
|
||||
this.set("loading", true);
|
||||
ajax(
|
||||
"/admin/logs/staff_action_logs/" + this.get("model.id") + "/diff"
|
||||
).then((diff) => {
|
||||
this.set("loading", false);
|
||||
this.set("diff", diff.side_by_side);
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,27 @@
|
||||
import Controller from "@ember/controller";
|
||||
import { on, observes } from "discourse-common/utils/decorators";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
|
||||
export default Controller.extend(ModalFunctionality, {
|
||||
@on("init")
|
||||
@observes("model.value")
|
||||
_setup() {
|
||||
const value = this.get("model.value");
|
||||
this.set("images", value && value.length ? value.split("\n") : []);
|
||||
},
|
||||
|
||||
actions: {
|
||||
uploadDone({ url }) {
|
||||
this.images.addObject(url);
|
||||
},
|
||||
|
||||
remove(url) {
|
||||
this.images.removeObject(url);
|
||||
},
|
||||
|
||||
close() {
|
||||
this.save(this.images.join("\n"));
|
||||
this.send("closeModal");
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
import Controller from "@ember/controller";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
|
||||
export default Controller.extend(ModalFunctionality, {
|
||||
@discourseComputed("value", "model.compiledRegularExpression")
|
||||
matches(value, regexpString) {
|
||||
if (!value || !regexpString) {
|
||||
return;
|
||||
}
|
||||
let censorRegexp = new RegExp(regexpString, "ig");
|
||||
return value.match(censorRegexp);
|
||||
},
|
||||
});
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
import Controller from "@ember/controller";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
|
||||
export default Controller.extend(ModalFunctionality, {
|
||||
onShow() {
|
||||
this.set("updateExistingUsers", null);
|
||||
},
|
||||
|
||||
actions: {
|
||||
updateExistingUsers() {
|
||||
this.set("updateExistingUsers", true);
|
||||
this.send("closeModal");
|
||||
},
|
||||
|
||||
cancel() {
|
||||
this.set("updateExistingUsers", false);
|
||||
this.send("closeModal");
|
||||
},
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user