Version bump
This commit is contained in:
commit
0a32b86f23
@ -1,5 +1,8 @@
|
||||
language: ruby
|
||||
|
||||
git:
|
||||
depth: false
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
@ -303,7 +303,7 @@ GEM
|
||||
nokogiri (>= 1.6)
|
||||
rails-html-sanitizer (1.0.4)
|
||||
loofah (~> 2.2, >= 2.2.2)
|
||||
rails_multisite (2.0.4)
|
||||
rails_multisite (2.0.6)
|
||||
activerecord (> 4.2, < 6)
|
||||
railties (> 4.2, < 6)
|
||||
railties (5.2.2)
|
||||
|
||||
@ -14,6 +14,10 @@ export default RestAdapter.extend({
|
||||
let mapped = theme.get("child_themes") || [];
|
||||
mapped = mapped.map(t => map[t.id]);
|
||||
theme.set("childThemes", mapped);
|
||||
|
||||
let mappedParents = theme.get("parent_themes") || [];
|
||||
mappedParents = mappedParents.map(t => map[t.id]);
|
||||
theme.set("parentThemes", mappedParents);
|
||||
});
|
||||
return results;
|
||||
},
|
||||
|
||||
@ -60,7 +60,11 @@ export default Ember.Component.extend({
|
||||
backgroundColor: prevChartData.length
|
||||
? "transparent"
|
||||
: model.secondary_color,
|
||||
borderColor: model.primary_color
|
||||
borderColor: model.primary_color,
|
||||
pointRadius: 3,
|
||||
borderWidth: 1,
|
||||
pointBackgroundColor: model.primary_color,
|
||||
pointBorderColor: model.primary_color
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
@ -68,14 +68,21 @@ export default Ember.Component.extend({
|
||||
return {
|
||||
type: "bar",
|
||||
data,
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
hover: { mode: "index" },
|
||||
tooltips: {
|
||||
mode: "index",
|
||||
intersect: false,
|
||||
callbacks: {
|
||||
beforeFooter: tooltipItem => {
|
||||
let total = 0;
|
||||
tooltipItem.forEach(
|
||||
item => (total += parseInt(item.yLabel || 0, 10))
|
||||
);
|
||||
return `= ${total}`;
|
||||
},
|
||||
title: tooltipItem =>
|
||||
moment(tooltipItem[0].xLabel, "YYYY-MM-DD").format("LL")
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { default as computed } from "ember-addons/ember-computed-decorators";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import AdminUser from "admin/models/admin-user";
|
||||
import copyText from "discourse/lib/copy-text";
|
||||
@ -5,43 +6,39 @@ import copyText from "discourse/lib/copy-text";
|
||||
export default Ember.Component.extend({
|
||||
classNames: ["ip-lookup"],
|
||||
|
||||
otherAccountsToDelete: function() {
|
||||
@computed("other_accounts.length", "totalOthersWithSameIP")
|
||||
otherAccountsToDelete(otherAccountsLength, totalOthersWithSameIP) {
|
||||
// can only delete up to 50 accounts at a time
|
||||
var total = Math.min(50, this.get("totalOthersWithSameIP") || 0);
|
||||
var visible = Math.min(50, this.get("other_accounts.length") || 0);
|
||||
const total = Math.min(50, totalOthersWithSameIP || 0);
|
||||
const visible = Math.min(50, otherAccountsLength || 0);
|
||||
return Math.max(visible, total);
|
||||
}.property("other_accounts", "totalOthersWithSameIP"),
|
||||
},
|
||||
|
||||
actions: {
|
||||
lookup: function() {
|
||||
var self = this;
|
||||
lookup() {
|
||||
this.set("show", true);
|
||||
|
||||
if (!this.get("location")) {
|
||||
ajax("/admin/users/ip-info", {
|
||||
data: { ip: this.get("ip") }
|
||||
}).then(function(location) {
|
||||
self.set("location", Ember.Object.create(location));
|
||||
});
|
||||
ajax("/admin/users/ip-info", { data: { ip: this.get("ip") } }).then(
|
||||
location => this.set("location", Ember.Object.create(location))
|
||||
);
|
||||
}
|
||||
|
||||
if (!this.get("other_accounts")) {
|
||||
this.set("otherAccountsLoading", true);
|
||||
|
||||
var data = {
|
||||
const data = {
|
||||
ip: this.get("ip"),
|
||||
exclude: this.get("userId"),
|
||||
order: "trust_level DESC"
|
||||
};
|
||||
|
||||
ajax("/admin/users/total-others-with-same-ip", { data }).then(function(
|
||||
result
|
||||
) {
|
||||
self.set("totalOthersWithSameIP", result.total);
|
||||
});
|
||||
ajax("/admin/users/total-others-with-same-ip", { data }).then(result =>
|
||||
this.set("totalOthersWithSameIP", result.total)
|
||||
);
|
||||
|
||||
AdminUser.findAll("active", data).then(function(users) {
|
||||
self.setProperties({
|
||||
AdminUser.findAll("active", data).then(users => {
|
||||
this.setProperties({
|
||||
other_accounts: users,
|
||||
otherAccountsLoading: false
|
||||
});
|
||||
@ -49,11 +46,11 @@ export default Ember.Component.extend({
|
||||
}
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
hide() {
|
||||
this.set("show", false);
|
||||
},
|
||||
|
||||
copy: function() {
|
||||
copy() {
|
||||
let text = `IP: ${this.get("ip")}\n`;
|
||||
const location = this.get("location");
|
||||
if (location) {
|
||||
@ -73,25 +70,25 @@ export default Ember.Component.extend({
|
||||
text += `: ${location.organization}\n`;
|
||||
}
|
||||
}
|
||||
const copyRange = $('<p id="copy-range"></p>');
|
||||
copyRange.html(text.trim().replace(/\n/g, "<br>"));
|
||||
$(document.body).append(copyRange);
|
||||
if (copyText(text, copyRange[0])) {
|
||||
|
||||
const $copyRange = $('<p id="copy-range"></p>');
|
||||
$copyRange.html(text.trim().replace(/\n/g, "<br>"));
|
||||
$(document.body).append($copyRange);
|
||||
if (copyText(text, $copyRange[0])) {
|
||||
this.set("copied", true);
|
||||
Ember.run.later(() => this.set("copied", false), 2000);
|
||||
}
|
||||
copyRange.remove();
|
||||
$copyRange.remove();
|
||||
},
|
||||
|
||||
deleteOtherAccounts: function() {
|
||||
var self = this;
|
||||
deleteOtherAccounts() {
|
||||
bootbox.confirm(
|
||||
I18n.t("ip_lookup.confirm_delete_other_accounts"),
|
||||
I18n.t("no_value"),
|
||||
I18n.t("yes_value"),
|
||||
function(confirmed) {
|
||||
confirmed => {
|
||||
if (confirmed) {
|
||||
self.setProperties({
|
||||
this.setProperties({
|
||||
other_accounts: null,
|
||||
otherAccountsLoading: true,
|
||||
totalOthersWithSameIP: null
|
||||
@ -100,13 +97,11 @@ export default Ember.Component.extend({
|
||||
ajax("/admin/users/delete-others-with-same-ip.json", {
|
||||
type: "DELETE",
|
||||
data: {
|
||||
ip: self.get("ip"),
|
||||
exclude: self.get("userId"),
|
||||
ip: this.get("ip"),
|
||||
exclude: this.get("userId"),
|
||||
order: "trust_level DESC"
|
||||
}
|
||||
}).then(function() {
|
||||
self.send("lookup");
|
||||
});
|
||||
}).then(() => this.send("lookup"));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@ -1,70 +1,76 @@
|
||||
import { default as computed } from "ember-addons/ember-computed-decorators";
|
||||
import { fmt } from "discourse/lib/computed";
|
||||
import Permalink from "admin/models/permalink";
|
||||
|
||||
export default Ember.Component.extend({
|
||||
classNames: ["permalink-form"],
|
||||
formSubmitted: false,
|
||||
permalinkType: "topic_id",
|
||||
permalinkTypePlaceholder: fmt("permalinkType", "admin.permalink.%@"),
|
||||
|
||||
permalinkTypes: function() {
|
||||
@computed
|
||||
permalinkTypes() {
|
||||
return [
|
||||
{ id: "topic_id", name: I18n.t("admin.permalink.topic_id") },
|
||||
{ id: "post_id", name: I18n.t("admin.permalink.post_id") },
|
||||
{ id: "category_id", name: I18n.t("admin.permalink.category_id") },
|
||||
{ id: "external_url", name: I18n.t("admin.permalink.external_url") }
|
||||
];
|
||||
}.property(),
|
||||
},
|
||||
|
||||
permalinkTypePlaceholder: function() {
|
||||
return "admin.permalink." + this.get("permalinkType");
|
||||
}.property("permalinkType"),
|
||||
focusPermalink() {
|
||||
Ember.run.schedule("afterRender", () => this.$(".permalink-url").focus());
|
||||
},
|
||||
|
||||
actions: {
|
||||
submit: function() {
|
||||
submit() {
|
||||
if (!this.get("formSubmitted")) {
|
||||
const self = this;
|
||||
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")
|
||||
});
|
||||
permalink.save().then(
|
||||
function(result) {
|
||||
self.set("url", "");
|
||||
self.set("permalink_type_value", "");
|
||||
self.set("formSubmitted", false);
|
||||
self.action(Permalink.create(result.permalink));
|
||||
Ember.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(". ")
|
||||
this.set("formSubmitted", true);
|
||||
|
||||
Permalink.create({
|
||||
url: this.get("url"),
|
||||
permalink_type: this.get("permalinkType"),
|
||||
permalink_type_value: this.get("permalink_type_value")
|
||||
})
|
||||
.save()
|
||||
.then(
|
||||
result => {
|
||||
this.setProperties({
|
||||
url: "",
|
||||
permalink_type_value: "",
|
||||
formSubmitted: false
|
||||
});
|
||||
} else {
|
||||
error = I18n.t("generic_error");
|
||||
|
||||
this.action(Permalink.create(result.permalink));
|
||||
|
||||
this.focusPermalink();
|
||||
},
|
||||
e => {
|
||||
this.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, () => this.focusPermalink());
|
||||
}
|
||||
bootbox.alert(error, function() {
|
||||
self.$(".permalink-url").focus();
|
||||
});
|
||||
}
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
didInsertElement: function() {
|
||||
var self = this;
|
||||
self._super();
|
||||
Ember.run.schedule("afterRender", function() {
|
||||
self.$(".external-url").keydown(function(e) {
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
|
||||
Ember.run.schedule("afterRender", () => {
|
||||
this.$(".external-url").keydown(e => {
|
||||
// enter key
|
||||
if (e.keyCode === 13) {
|
||||
// enter key
|
||||
self.send("submit");
|
||||
this.send("submit");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -8,7 +8,7 @@ export default Ember.Component.extend({
|
||||
classNames: ["themes-list"],
|
||||
|
||||
hasThemes: Ember.computed.gt("themesList.length", 0),
|
||||
hasUserThemes: Ember.computed.gt("userThemes.length", 0),
|
||||
hasActiveThemes: Ember.computed.gt("activeThemes.length", 0),
|
||||
hasInactiveThemes: Ember.computed.gt("inactiveThemes.length", 0),
|
||||
|
||||
themesTabActive: Ember.computed.equal("currentTab", THEMES),
|
||||
@ -31,7 +31,7 @@ export default Ember.Component.extend({
|
||||
)
|
||||
inactiveThemes(themes) {
|
||||
if (this.get("componentsTabActive")) {
|
||||
return [];
|
||||
return themes.filter(theme => theme.get("parent_themes.length") <= 0);
|
||||
}
|
||||
return themes.filter(
|
||||
theme => !theme.get("user_selectable") && !theme.get("default")
|
||||
@ -44,20 +44,21 @@ export default Ember.Component.extend({
|
||||
"themesList.@each.user_selectable",
|
||||
"themesList.@each.default"
|
||||
)
|
||||
userThemes(themes) {
|
||||
activeThemes(themes) {
|
||||
if (this.get("componentsTabActive")) {
|
||||
return [];
|
||||
return themes.filter(theme => theme.get("parent_themes.length") > 0);
|
||||
} else {
|
||||
themes = themes.filter(
|
||||
theme => theme.get("user_selectable") || theme.get("default")
|
||||
);
|
||||
return _.sortBy(themes, t => {
|
||||
return [
|
||||
!t.get("default"),
|
||||
!t.get("user_selectable"),
|
||||
t.get("name").toLowerCase()
|
||||
];
|
||||
});
|
||||
}
|
||||
themes = themes.filter(
|
||||
theme => theme.get("user_selectable") || theme.get("default")
|
||||
);
|
||||
return _.sortBy(themes, t => {
|
||||
return [
|
||||
!t.get("default"),
|
||||
!t.get("user_selectable"),
|
||||
t.get("name").toLowerCase()
|
||||
];
|
||||
});
|
||||
},
|
||||
|
||||
didRender() {
|
||||
|
||||
@ -30,7 +30,7 @@ export default Ember.Component.extend({
|
||||
result.className = "disagreed";
|
||||
result.label = `${result.disagreed}%`;
|
||||
} else {
|
||||
result.icon = "external-link";
|
||||
result.icon = "external-link-alt";
|
||||
result.className = "ignored";
|
||||
result.label = `${result.ignored}%`;
|
||||
}
|
||||
|
||||
@ -1,6 +1,12 @@
|
||||
import ApiKey from "admin/models/api-key";
|
||||
import { default as computed } from "ember-addons/ember-computed-decorators";
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
@computed("model.[]")
|
||||
hasMasterKey(model) {
|
||||
return !!model.findBy("user", null);
|
||||
},
|
||||
|
||||
actions: {
|
||||
generateMasterKey() {
|
||||
ApiKey.generateMasterKey().then(key => this.get("model").pushObject(key));
|
||||
@ -31,10 +37,5 @@ export default Ember.Controller.extend({
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
// Has a master key already been generated?
|
||||
hasMasterKey: function() {
|
||||
return !!this.get("model").findBy("user", null);
|
||||
}.property("model.[]")
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,41 +1,36 @@
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
import { default as computed } from "ember-addons/ember-computed-decorators";
|
||||
import { setting, i18n } from "discourse/lib/computed";
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
adminBackups: Ember.inject.controller(),
|
||||
status: Ember.computed.alias("adminBackups.model"),
|
||||
uploadLabel: i18n("admin.backups.upload.label"),
|
||||
backupLocation: setting("backup_location"),
|
||||
localBackupStorage: Ember.computed.equal("backupLocation", "local"),
|
||||
|
||||
@computed
|
||||
localBackupStorage() {
|
||||
return this.siteSettings.backup_location === "local";
|
||||
},
|
||||
|
||||
uploadLabel: function() {
|
||||
return I18n.t("admin.backups.upload.label");
|
||||
}.property(),
|
||||
|
||||
restoreTitle: function() {
|
||||
if (!this.get("status.allowRestore")) {
|
||||
@computed("status.allowRestore", "status.isOperationRunning")
|
||||
restoreTitle(allowRestore, isOperationRunning) {
|
||||
if (!allowRestore) {
|
||||
return "admin.backups.operations.restore.is_disabled";
|
||||
} else if (this.get("status.isOperationRunning")) {
|
||||
} else if (isOperationRunning) {
|
||||
return "admin.backups.operations.is_running";
|
||||
} else {
|
||||
return "admin.backups.operations.restore.title";
|
||||
}
|
||||
}.property("status.{allowRestore,isOperationRunning}"),
|
||||
},
|
||||
|
||||
actions: {
|
||||
toggleReadOnlyMode() {
|
||||
var self = this;
|
||||
if (!this.site.get("isReadOnly")) {
|
||||
bootbox.confirm(
|
||||
I18n.t("admin.backups.read_only.enable.confirm"),
|
||||
I18n.t("no_value"),
|
||||
I18n.t("yes_value"),
|
||||
function(confirmed) {
|
||||
confirmed => {
|
||||
if (confirmed) {
|
||||
Discourse.User.currentProp("hideReadOnlyAlert", true);
|
||||
self._toggleReadOnlyMode(true);
|
||||
this._toggleReadOnlyMode(true);
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -45,20 +40,17 @@ export default Ember.Controller.extend({
|
||||
},
|
||||
|
||||
download(backup) {
|
||||
let link = backup.get("filename");
|
||||
ajax("/admin/backups/" + link, { type: "PUT" }).then(() => {
|
||||
bootbox.alert(I18n.t("admin.backups.operations.download.alert"));
|
||||
});
|
||||
const link = backup.get("filename");
|
||||
ajax(`/admin/backups/${link}`, { type: "PUT" }).then(() =>
|
||||
bootbox.alert(I18n.t("admin.backups.operations.download.alert"))
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
_toggleReadOnlyMode(enable) {
|
||||
var site = this.site;
|
||||
ajax("/admin/backups/readonly", {
|
||||
type: "PUT",
|
||||
data: { enable: enable }
|
||||
}).then(() => {
|
||||
site.set("isReadOnly", enable);
|
||||
});
|
||||
data: { enable }
|
||||
}).then(() => this.site.set("isReadOnly", enable));
|
||||
}
|
||||
});
|
||||
|
||||
@ -8,22 +8,11 @@ import { THEMES, COMPONENTS } from "admin/models/theme";
|
||||
const THEME_UPLOAD_VAR = 2;
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
downloadUrl: url("model.id", "/admin/themes/%@"),
|
||||
downloadUrl: url("model.id", "/admin/customize/themes/%@/export"),
|
||||
previewUrl: url("model.id", "/admin/themes/%@/preview"),
|
||||
addButtonDisabled: Ember.computed.empty("selectedChildThemeId"),
|
||||
editRouteName: "adminCustomizeThemes.edit",
|
||||
|
||||
@computed("model", "allThemes", "model.component")
|
||||
parentThemes(model, allThemes) {
|
||||
if (!model.get("component")) {
|
||||
return null;
|
||||
}
|
||||
const parents = allThemes.filter(theme =>
|
||||
_.contains(theme.get("childThemes"), model)
|
||||
);
|
||||
return parents.length === 0 ? null : parents;
|
||||
},
|
||||
|
||||
@computed("model.editedFields")
|
||||
editedFieldsFormatted() {
|
||||
const descriptions = [];
|
||||
@ -214,7 +203,7 @@ export default Ember.Controller.extend({
|
||||
},
|
||||
|
||||
editTheme() {
|
||||
if (this.get("model.remote_theme")) {
|
||||
if (this.get("model.remote_theme.is_git")) {
|
||||
bootbox.confirm(
|
||||
I18n.t("admin.customize.theme.edit_confirm"),
|
||||
result => {
|
||||
|
||||
@ -11,8 +11,7 @@ export default Ember.Controller.extend({
|
||||
show: debounce(function() {
|
||||
this.set("loading", true);
|
||||
ScreenedIpAddress.findAll(this.get("filter")).then(result => {
|
||||
this.set("model", result);
|
||||
this.set("loading", false);
|
||||
this.setProperties({ model: result, loading: false });
|
||||
});
|
||||
}, 250).observes("filter"),
|
||||
|
||||
@ -35,8 +34,9 @@ export default Ember.Controller.extend({
|
||||
},
|
||||
|
||||
cancel(record) {
|
||||
if (this.get("savedIpAddress") && record.get("editing")) {
|
||||
record.set("ip_address", this.get("savedIpAddress"));
|
||||
const savedIpAddress = this.get("savedIpAddress");
|
||||
if (savedIpAddress && record.get("editing")) {
|
||||
record.set("ip_address", savedIpAddress);
|
||||
}
|
||||
record.set("editing", false);
|
||||
},
|
||||
@ -46,9 +46,7 @@ export default Ember.Controller.extend({
|
||||
record.set("editing", false);
|
||||
record
|
||||
.save()
|
||||
.then(() => {
|
||||
this.set("savedIpAddress", null);
|
||||
})
|
||||
.then(() => this.set("savedIpAddress", null))
|
||||
.catch(e => {
|
||||
if (e.jqXHR.responseJSON && e.jqXHR.responseJSON.errors) {
|
||||
bootbox.alert(
|
||||
@ -84,7 +82,7 @@ export default Ember.Controller.extend({
|
||||
.catch(e => {
|
||||
bootbox.alert(
|
||||
I18n.t("generic_error_with_reason", {
|
||||
error: "http: " + e.status + " - " + e.body
|
||||
error: `http: ${e.status} - ${e.body}`
|
||||
})
|
||||
);
|
||||
});
|
||||
@ -98,25 +96,24 @@ export default Ember.Controller.extend({
|
||||
},
|
||||
|
||||
rollUp() {
|
||||
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) {
|
||||
confirmed => {
|
||||
if (confirmed) {
|
||||
self.set("loading", true);
|
||||
return ScreenedIpAddress.rollUp().then(function(results) {
|
||||
this.set("loading", true);
|
||||
return ScreenedIpAddress.rollUp().then(results => {
|
||||
if (results && results.subnets) {
|
||||
if (results.subnets.length > 0) {
|
||||
self.send("show");
|
||||
this.send("show");
|
||||
bootbox.alert(
|
||||
I18n.t("admin.logs.screened_ips.rolled_up_some_subnets", {
|
||||
subnets: results.subnets.join(", ")
|
||||
})
|
||||
);
|
||||
} else {
|
||||
self.set("loading", false);
|
||||
this.set("loading", false);
|
||||
bootbox.alert(
|
||||
I18n.t("admin.logs.screened_ips.rolled_up_no_subnet")
|
||||
);
|
||||
|
||||
@ -3,7 +3,8 @@ import CanCheckEmails from "discourse/mixins/can-check-emails";
|
||||
import { propertyNotEqual, setting } from "discourse/lib/computed";
|
||||
import { userPath } from "discourse/lib/url";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
import { default as computed } from "ember-addons/ember-computed-decorators";
|
||||
import { fmt } from "discourse/lib/computed";
|
||||
|
||||
export default Ember.Controller.extend(CanCheckEmails, {
|
||||
adminTools: Ember.inject.service(),
|
||||
@ -64,24 +65,22 @@ export default Ember.Controller.extend(CanCheckEmails, {
|
||||
.join(", ");
|
||||
},
|
||||
|
||||
userFields: function() {
|
||||
const siteUserFields = this.site.get("user_fields"),
|
||||
userFields = this.get("model.user_fields");
|
||||
@computed("model.user_fields.[]")
|
||||
userFields(userFields) {
|
||||
const siteUserFields = this.site.get("user_fields");
|
||||
|
||||
if (!Ember.isEmpty(siteUserFields)) {
|
||||
return siteUserFields.map(function(uf) {
|
||||
let value = userFields ? userFields[uf.get("id").toString()] : null;
|
||||
return { name: uf.get("name"), value: value };
|
||||
return siteUserFields.map(uf => {
|
||||
const value = userFields ? userFields[uf.get("id").toString()] : null;
|
||||
return { name: uf.get("name"), value };
|
||||
});
|
||||
}
|
||||
return [];
|
||||
}.property("model.user_fields.[]"),
|
||||
|
||||
@computed("model.username_lower")
|
||||
preferencesPath(username) {
|
||||
return userPath(`${username}/preferences`);
|
||||
return [];
|
||||
},
|
||||
|
||||
preferencesPath: fmt("model.username_lower", userPath("%@/preferences")),
|
||||
|
||||
@computed("model.can_delete_all_posts", "model.staff", "model.post_count")
|
||||
deleteAllPostsExplanation(canDeleteAllPosts, staff, postCount) {
|
||||
if (canDeleteAllPosts) {
|
||||
@ -120,9 +119,7 @@ export default Ember.Controller.extend(CanCheckEmails, {
|
||||
groupAdded(added) {
|
||||
this.get("model")
|
||||
.groupAdded(added)
|
||||
.catch(function() {
|
||||
bootbox.alert(I18n.t("generic_error"));
|
||||
});
|
||||
.catch(() => bootbox.alert(I18n.t("generic_error")));
|
||||
},
|
||||
|
||||
groupRemoved(groupId) {
|
||||
@ -133,9 +130,7 @@ export default Ember.Controller.extend(CanCheckEmails, {
|
||||
this.set("originalPrimaryGroupId", null);
|
||||
}
|
||||
})
|
||||
.catch(function() {
|
||||
bootbox.alert(I18n.t("generic_error"));
|
||||
});
|
||||
.catch(() => bootbox.alert(I18n.t("generic_error")));
|
||||
},
|
||||
|
||||
actions: {
|
||||
@ -201,13 +196,11 @@ export default Ember.Controller.extend(CanCheckEmails, {
|
||||
},
|
||||
|
||||
clearPenaltyHistory() {
|
||||
let user = this.get("model");
|
||||
return ajax(`/admin/users/${user.get("id")}/penalty_history`, {
|
||||
type: "DELETE"
|
||||
})
|
||||
.then(() => {
|
||||
user.set("tl3_requirements.penalty_counts.total", 0);
|
||||
})
|
||||
const user = this.get("model");
|
||||
const path = `/admin/users/${user.get("id")}/penalty_history`;
|
||||
|
||||
return ajax(path, { type: "DELETE" })
|
||||
.then(() => user.set("tl3_requirements.penalty_counts.total", 0))
|
||||
.catch(popupAjaxError);
|
||||
},
|
||||
|
||||
@ -225,7 +218,6 @@ export default Ember.Controller.extend(CanCheckEmails, {
|
||||
target_user: this.get("model.username")
|
||||
});
|
||||
},
|
||||
|
||||
showFlagsReceived() {
|
||||
this.get("adminTools").showFlagsReceived(this.get("model"));
|
||||
},
|
||||
@ -245,10 +237,9 @@ export default Ember.Controller.extend(CanCheckEmails, {
|
||||
const oldUsername = this.get("model.username");
|
||||
this.set("model.username", newUsername);
|
||||
|
||||
return ajax(`/users/${oldUsername.toLowerCase()}/preferences/username`, {
|
||||
data: { new_username: newUsername },
|
||||
type: "PUT"
|
||||
})
|
||||
const path = `/users/${oldUsername.toLowerCase()}/preferences/username`;
|
||||
|
||||
return ajax(path, { data: { new_username: newUsername }, type: "PUT" })
|
||||
.catch(e => {
|
||||
this.set("model.username", oldUsername);
|
||||
popupAjaxError(e);
|
||||
@ -260,13 +251,9 @@ export default Ember.Controller.extend(CanCheckEmails, {
|
||||
const oldName = this.get("model.name");
|
||||
this.set("model.name", newName);
|
||||
|
||||
return ajax(
|
||||
userPath(`${this.get("model.username").toLowerCase()}.json`),
|
||||
{
|
||||
data: { name: newName },
|
||||
type: "PUT"
|
||||
}
|
||||
)
|
||||
const path = userPath(`${this.get("model.username").toLowerCase()}.json`);
|
||||
|
||||
return ajax(path, { data: { name: newName }, type: "PUT" })
|
||||
.catch(e => {
|
||||
this.set("model.name", oldName);
|
||||
popupAjaxError(e);
|
||||
@ -276,15 +263,11 @@ export default Ember.Controller.extend(CanCheckEmails, {
|
||||
|
||||
saveTitle(newTitle) {
|
||||
const oldTitle = this.get("model.title");
|
||||
|
||||
this.set("model.title", newTitle);
|
||||
return ajax(
|
||||
userPath(`${this.get("model.username").toLowerCase()}.json`),
|
||||
{
|
||||
data: { title: newTitle },
|
||||
type: "PUT"
|
||||
}
|
||||
)
|
||||
|
||||
const path = userPath(`${this.get("model.username").toLowerCase()}.json`);
|
||||
|
||||
return ajax(path, { data: { title: newTitle }, type: "PUT" })
|
||||
.catch(e => {
|
||||
this.set("model.title", oldTitle);
|
||||
popupAjaxError(e);
|
||||
@ -303,9 +286,7 @@ export default Ember.Controller.extend(CanCheckEmails, {
|
||||
|
||||
bufferedIds
|
||||
.filter(id => !currentIds.includes(id))
|
||||
.forEach(id => {
|
||||
this.groupAdded(availableGroups.findBy("id", id));
|
||||
});
|
||||
.forEach(id => this.groupAdded(availableGroups.findBy("id", id)));
|
||||
|
||||
currentIds
|
||||
.filter(id => !bufferedIds.includes(id))
|
||||
@ -317,21 +298,15 @@ export default Ember.Controller.extend(CanCheckEmails, {
|
||||
},
|
||||
|
||||
savePrimaryGroup() {
|
||||
const self = this;
|
||||
const primaryGroupId = this.get("model.primary_group_id");
|
||||
const path = `/admin/users/${this.get("model.id")}/primary_group`;
|
||||
|
||||
return ajax("/admin/users/" + this.get("model.id") + "/primary_group", {
|
||||
return ajax(path, {
|
||||
type: "PUT",
|
||||
data: { primary_group_id: this.get("model.primary_group_id") }
|
||||
data: { primary_group_id: primaryGroupId }
|
||||
})
|
||||
.then(function() {
|
||||
self.set(
|
||||
"originalPrimaryGroupId",
|
||||
self.get("model.primary_group_id")
|
||||
);
|
||||
})
|
||||
.catch(function() {
|
||||
bootbox.alert(I18n.t("generic_error"));
|
||||
});
|
||||
.then(() => this.set("originalPrimaryGroupId", primaryGroupId))
|
||||
.catch(() => bootbox.alert(I18n.t("generic_error")));
|
||||
},
|
||||
|
||||
resetPrimaryGroup() {
|
||||
@ -339,30 +314,26 @@ export default Ember.Controller.extend(CanCheckEmails, {
|
||||
},
|
||||
|
||||
regenerateApiKey() {
|
||||
const self = this;
|
||||
|
||||
bootbox.confirm(
|
||||
I18n.t("admin.api.confirm_regen"),
|
||||
I18n.t("no_value"),
|
||||
I18n.t("yes_value"),
|
||||
function(result) {
|
||||
result => {
|
||||
if (result) {
|
||||
self.get("model").generateApiKey();
|
||||
this.get("model").generateApiKey();
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
revokeApiKey() {
|
||||
const self = this;
|
||||
|
||||
bootbox.confirm(
|
||||
I18n.t("admin.api.confirm_revoke"),
|
||||
I18n.t("no_value"),
|
||||
I18n.t("yes_value"),
|
||||
function(result) {
|
||||
result => {
|
||||
if (result) {
|
||||
self.get("model").revokeApiKey();
|
||||
this.get("model").revokeApiKey();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@ -9,7 +9,7 @@ export default Ember.Helper.extend({
|
||||
let title = "admin.flags.dispositions." + disposition;
|
||||
switch (disposition) {
|
||||
case "deferred": {
|
||||
icon = "external-link";
|
||||
icon = "external-link-alt";
|
||||
break;
|
||||
}
|
||||
case "agreed": {
|
||||
|
||||
@ -1,32 +1,22 @@
|
||||
import AdminUser from "admin/models/admin-user";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
|
||||
const ApiKey = Discourse.Model.extend({
|
||||
/**
|
||||
Regenerates the api key
|
||||
const KEY_ENDPOINT = "/admin/api/key";
|
||||
const KEYS_ENDPOINT = "/admin/api/keys";
|
||||
|
||||
@method regenerate
|
||||
@returns {Promise} a promise that resolves to the key
|
||||
**/
|
||||
regenerate: function() {
|
||||
var self = this;
|
||||
return ajax("/admin/api/key", {
|
||||
const ApiKey = Discourse.Model.extend({
|
||||
regenerate() {
|
||||
return ajax(KEY_ENDPOINT, {
|
||||
type: "PUT",
|
||||
data: { id: this.get("id") }
|
||||
}).then(function(result) {
|
||||
self.set("key", result.api_key.key);
|
||||
return self;
|
||||
}).then(result => {
|
||||
this.set("key", result.api_key.key);
|
||||
return this;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
Revokes the current key
|
||||
|
||||
@method revoke
|
||||
@returns {Promise} a promise that resolves when the key has been revoked
|
||||
**/
|
||||
revoke: function() {
|
||||
return ajax("/admin/api/key", {
|
||||
revoke() {
|
||||
return ajax(KEY_ENDPOINT, {
|
||||
type: "DELETE",
|
||||
data: { id: this.get("id") }
|
||||
});
|
||||
@ -34,45 +24,24 @@ const ApiKey = Discourse.Model.extend({
|
||||
});
|
||||
|
||||
ApiKey.reopenClass({
|
||||
/**
|
||||
Creates an API key instance with internal user object
|
||||
|
||||
@method create
|
||||
@param {...} var_args the properties to initialize this with
|
||||
@returns {ApiKey} the ApiKey instance
|
||||
**/
|
||||
create() {
|
||||
var result = this._super.apply(this, arguments);
|
||||
const result = this._super.apply(this, arguments);
|
||||
if (result.user) {
|
||||
result.user = AdminUser.create(result.user);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
Finds a list of API keys
|
||||
|
||||
@method find
|
||||
@returns {Promise} a promise that resolves to the array of `ApiKey` instances
|
||||
**/
|
||||
find: function() {
|
||||
return ajax("/admin/api/keys").then(function(keys) {
|
||||
return keys.map(function(key) {
|
||||
return ApiKey.create(key);
|
||||
});
|
||||
});
|
||||
find() {
|
||||
return ajax(KEYS_ENDPOINT).then(keys =>
|
||||
keys.map(key => ApiKey.create(key))
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
Generates a master api key and returns it.
|
||||
|
||||
@method generateMasterKey
|
||||
@returns {Promise} a promise that resolves to a master `ApiKey`
|
||||
**/
|
||||
generateMasterKey: function() {
|
||||
return ajax("/admin/api/key", { type: "POST" }).then(function(result) {
|
||||
return ApiKey.create(result.api_key);
|
||||
});
|
||||
generateMasterKey() {
|
||||
return ajax(KEY_ENDPOINT, { type: "POST" }).then(result =>
|
||||
ApiKey.create(result.api_key)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -47,15 +47,15 @@ export default Discourse.Route.extend({
|
||||
},
|
||||
|
||||
model() {
|
||||
return PreloadStore.getAndRemove("operations_status", function() {
|
||||
return ajax("/admin/backups/status.json");
|
||||
}).then(status => {
|
||||
return BackupStatus.create({
|
||||
return PreloadStore.getAndRemove("operations_status", () =>
|
||||
ajax("/admin/backups/status.json")
|
||||
).then(status =>
|
||||
BackupStatus.create({
|
||||
isOperationRunning: status.is_operation_running,
|
||||
canRollback: status.can_rollback,
|
||||
allowRestore: status.allow_restore
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
deactivate() {
|
||||
@ -74,33 +74,30 @@ export default Discourse.Route.extend({
|
||||
},
|
||||
|
||||
destroyBackup(backup) {
|
||||
const self = this;
|
||||
bootbox.confirm(
|
||||
I18n.t("admin.backups.operations.destroy.confirm"),
|
||||
I18n.t("no_value"),
|
||||
I18n.t("yes_value"),
|
||||
function(confirmed) {
|
||||
confirmed => {
|
||||
if (confirmed) {
|
||||
backup.destroy().then(function() {
|
||||
self
|
||||
.controllerFor("adminBackupsIndex")
|
||||
backup.destroy().then(() =>
|
||||
this.controllerFor("adminBackupsIndex")
|
||||
.get("model")
|
||||
.removeObject(backup);
|
||||
});
|
||||
.removeObject(backup)
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
startRestore(backup) {
|
||||
const self = this;
|
||||
bootbox.confirm(
|
||||
I18n.t("admin.backups.operations.restore.confirm"),
|
||||
I18n.t("no_value"),
|
||||
I18n.t("yes_value"),
|
||||
function(confirmed) {
|
||||
confirmed => {
|
||||
if (confirmed) {
|
||||
self.transitionTo("admin.backups.logs");
|
||||
this.transitionTo("admin.backups.logs");
|
||||
backup.restore();
|
||||
}
|
||||
}
|
||||
@ -108,17 +105,17 @@ export default Discourse.Route.extend({
|
||||
},
|
||||
|
||||
cancelOperation() {
|
||||
const self = this;
|
||||
bootbox.confirm(
|
||||
I18n.t("admin.backups.operations.cancel.confirm"),
|
||||
I18n.t("no_value"),
|
||||
I18n.t("yes_value"),
|
||||
function(confirmed) {
|
||||
confirmed => {
|
||||
if (confirmed) {
|
||||
Backup.cancel().then(function() {
|
||||
self
|
||||
.controllerFor("adminBackups")
|
||||
.set("model.isOperationRunning", false);
|
||||
Backup.cancel().then(() => {
|
||||
this.controllerFor("adminBackups").set(
|
||||
"model.isOperationRunning",
|
||||
false
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -130,7 +127,7 @@ export default Discourse.Route.extend({
|
||||
I18n.t("admin.backups.operations.rollback.confirm"),
|
||||
I18n.t("no_value"),
|
||||
I18n.t("yes_value"),
|
||||
function(confirmed) {
|
||||
confirmed => {
|
||||
if (confirmed) {
|
||||
Backup.rollback();
|
||||
}
|
||||
@ -139,17 +136,12 @@ export default Discourse.Route.extend({
|
||||
},
|
||||
|
||||
uploadSuccess(filename) {
|
||||
bootbox.alert(
|
||||
I18n.t("admin.backups.upload.success", { filename: filename })
|
||||
);
|
||||
bootbox.alert(I18n.t("admin.backups.upload.success", { filename }));
|
||||
},
|
||||
|
||||
uploadError(filename, message) {
|
||||
bootbox.alert(
|
||||
I18n.t("admin.backups.upload.error", {
|
||||
filename: filename,
|
||||
message: message
|
||||
})
|
||||
I18n.t("admin.backups.upload.error", { filename, message })
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
import { emojiUrlFor } from "discourse/lib/text";
|
||||
|
||||
const badgeIntroLinks = [
|
||||
{
|
||||
text: "admin.badges.badge_intro.what_are_badges_title",
|
||||
href: "https://meta.discourse.org/t/32540",
|
||||
icon: "book"
|
||||
},
|
||||
{
|
||||
text: "admin.badges.badge_intro.badge_query_examples_title",
|
||||
href: "https://meta.discourse.org/t/18978",
|
||||
icon: "book"
|
||||
}
|
||||
];
|
||||
|
||||
export default Ember.Route.extend({
|
||||
setupController(controller) {
|
||||
controller.setProperties({
|
||||
badgeIntroLinks,
|
||||
badgeIntroEmoji: emojiUrlFor("woman_student:t4")
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -1,35 +1,47 @@
|
||||
{{#if model}}
|
||||
<table class='api-keys grid'>
|
||||
<table class="api-keys grid">
|
||||
<thead>
|
||||
<th>{{i18n 'admin.api.key'}}</th>
|
||||
<th>{{i18n 'admin.api.user'}}</th>
|
||||
<th>{{i18n "admin.api.key"}}</th>
|
||||
<th>{{i18n "admin.api.user"}}</th>
|
||||
<th> </th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each model as |k|}}
|
||||
<tr>
|
||||
<td class='key'>{{k.key}}</td>
|
||||
<td class="key">{{k.key}}</td>
|
||||
<td class="key-user">
|
||||
{{#if k.user}}
|
||||
{{#link-to 'adminUser' k.user}}
|
||||
{{#link-to "adminUser" k.user}}
|
||||
{{avatar k.user imageSize="small"}}
|
||||
{{/link-to}}
|
||||
{{else}}
|
||||
{{i18n 'admin.api.all_users'}}
|
||||
{{i18n "admin.api.all_users"}}
|
||||
{{/if}}
|
||||
</td>
|
||||
<td class="key-controls">
|
||||
{{d-button class="btn-default" action=(action "regenerateKey") actionParam=k icon="undo" label='admin.api.regenerate'}}
|
||||
{{d-button class="btn-default" action=(action "revokeKey") actionParam=k icon="times" label='admin.api.revoke'}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "regenerateKey")
|
||||
actionParam=k icon="undo"
|
||||
label="admin.api.regenerate"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "revokeKey")
|
||||
actionParam=k
|
||||
icon="times"
|
||||
label="admin.api.revoke"}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{else}}
|
||||
<p>{{i18n 'admin.api.none'}}</p>
|
||||
<p>{{i18n "admin.api.none"}}</p>
|
||||
{{/if}}
|
||||
|
||||
{{#unless hasMasterKey}}
|
||||
<button class='btn btn-icon no-text btn-primary' {{action "generateMasterKey"}}>{{d-icon "key"}}</button>
|
||||
{{d-button
|
||||
class="btn-primary"
|
||||
action=(action "generateMasterKey")
|
||||
icon="key"}}
|
||||
{{/unless}}
|
||||
|
||||
@ -1,20 +1,38 @@
|
||||
<div class="backup-options">
|
||||
{{#if localBackupStorage}}
|
||||
{{resumable-upload target="/admin/backups/upload" success=(route-action "uploadSuccess") error=(route-action "uploadError") uploadText=uploadLabel title="admin.backups.upload.title" class="btn-default"}}
|
||||
{{else}}
|
||||
{{backup-uploader done=(route-action "remoteUploadSuccess")}}
|
||||
{{/if}}
|
||||
<div class="backup-options">
|
||||
{{#if localBackupStorage}}
|
||||
{{resumable-upload
|
||||
target="/admin/backups/upload"
|
||||
success=(route-action "uploadSuccess")
|
||||
error=(route-action "uploadError")
|
||||
uploadText=uploadLabel
|
||||
title="admin.backups.upload.title"
|
||||
class="btn-default"}}
|
||||
{{else}}
|
||||
{{backup-uploader done=(route-action "remoteUploadSuccess")}}
|
||||
{{/if}}
|
||||
|
||||
{{#if site.isReadOnly}}
|
||||
{{d-button class="btn-default" icon="far-eye" action=(action "toggleReadOnlyMode") disabled=status.isOperationRunning title="admin.backups.read_only.disable.title" label="admin.backups.read_only.disable.label"}}
|
||||
{{else}}
|
||||
{{d-button class="btn-default" icon="far-eye" action=(action "toggleReadOnlyMode") disabled=status.isOperationRunning title="admin.backups.read_only.enable.title" label="admin.backups.read_only.enable.label"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{#if site.isReadOnly}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
icon="far-eye"
|
||||
action=(action "toggleReadOnlyMode")
|
||||
disabled=status.isOperationRunning
|
||||
title="admin.backups.read_only.disable.title"
|
||||
label="admin.backups.read_only.disable.label"}}
|
||||
{{else}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
icon="far-eye"
|
||||
action=(action "toggleReadOnlyMode")
|
||||
disabled=status.isOperationRunning
|
||||
title="admin.backups.read_only.enable.title"
|
||||
label="admin.backups.read_only.enable.label"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<table class="grid">
|
||||
<thead>
|
||||
<th width="55%">{{i18n 'admin.backups.columns.filename'}}</th>
|
||||
<th width="10%">{{i18n 'admin.backups.columns.size'}}</th>
|
||||
<th width="55%">{{i18n "admin.backups.columns.filename"}}</th>
|
||||
<th width="10%">{{i18n "admin.backups.columns.size"}}</th>
|
||||
<th></th>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -25,24 +43,47 @@
|
||||
<td class="backup-controls">
|
||||
<div>
|
||||
{{d-button class="btn-default download"
|
||||
action=(action "download")
|
||||
actionParam=backup
|
||||
icon="download"
|
||||
title="admin.backups.operations.download.title"
|
||||
label="admin.backups.operations.download.label"}}
|
||||
action=(action "download")
|
||||
actionParam=backup
|
||||
icon="download"
|
||||
title="admin.backups.operations.download.title"
|
||||
label="admin.backups.operations.download.label"}}
|
||||
{{#if status.isOperationRunning}}
|
||||
{{d-button icon="far-trash-alt" action=(route-action "destroyBackup") actionParam=backup class="btn-danger" disabled="true" title="admin.backups.operations.is_running"}}
|
||||
{{d-button icon="play" action=(route-action "startRestore") actionParam=backup disabled=status.restoreDisabled class="btn-default" title=restoreTitle label="admin.backups.operations.restore.label"}}
|
||||
{{d-button
|
||||
icon="far-trash-alt"
|
||||
action=(route-action "destroyBackup")
|
||||
actionParam=backup class="btn-danger"
|
||||
disabled="true"
|
||||
title="admin.backups.operations.is_running"}}
|
||||
{{d-button
|
||||
icon="play"
|
||||
action=(route-action "startRestore")
|
||||
actionParam=backup disabled=status.restoreDisabled
|
||||
class="btn-default"
|
||||
title=restoreTitle
|
||||
label="admin.backups.operations.restore.label"}}
|
||||
{{else}}
|
||||
{{d-button icon="far-trash-alt" action=(route-action "destroyBackup") actionParam=backup class="btn-danger" title="admin.backups.operations.destroy.title"}}
|
||||
{{d-button icon="play" action=(route-action "startRestore") actionParam=backup disabled=status.restoreDisabled class="btn-default" title=restoreTitle label="admin.backups.operations.restore.label"}}
|
||||
{{d-button
|
||||
icon="far-trash-alt"
|
||||
action=(route-action "destroyBackup")
|
||||
actionParam=backup
|
||||
class="btn-danger"
|
||||
title="admin.backups.operations.destroy.title"}}
|
||||
{{d-button
|
||||
icon="play"
|
||||
action=(route-action "startRestore")
|
||||
actionParam=backup
|
||||
disabled=status.restoreDisabled
|
||||
class="btn-default"
|
||||
title=restoreTitle
|
||||
label="admin.backups.operations.restore.label"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{else}}
|
||||
<tr>
|
||||
<td>{{i18n 'admin.backups.none'}}</td>
|
||||
<td>{{i18n "admin.backups.none"}}</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
@ -1,9 +1,16 @@
|
||||
{{#d-section class="current-badge content-body"}}
|
||||
<p>{{i18n 'admin.badges.none_selected'}}</p>
|
||||
|
||||
<div>
|
||||
{{#link-to 'adminBadges.show' 'new' class="btn btn-default"}}
|
||||
{{d-icon "plus"}} {{i18n 'admin.badges.new'}}
|
||||
{{/link-to}}
|
||||
{{#d-section class="current-badges"}}
|
||||
<div class="badge-intro">
|
||||
<img src={{badgeIntroEmoji}} class="badge-intro-emoji">
|
||||
<div class="content-wrapper">
|
||||
<h1>{{i18n 'admin.badges.badge_intro.title'}}</h1>
|
||||
<div class="external-resources">
|
||||
{{#each badgeIntroLinks as |link|}}
|
||||
<a href={{link.href}} class="external-link" target="_blank">
|
||||
{{d-icon link.icon}}
|
||||
<span>{{I18n link.text}}</span>
|
||||
</a>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/d-section}}
|
||||
{{/d-section}}
|
||||
@ -39,7 +39,7 @@
|
||||
content=badgeGroupings
|
||||
class="badge-selector"
|
||||
nameProperty="name"}}
|
||||
<button {{action "editGroupings"}} class='btn btn-icon no-text btn-default'>{{d-icon 'pencil'}}</button>
|
||||
<button {{action "editGroupings"}} class='btn btn-icon no-text btn-default'>{{d-icon "pencil-alt"}}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -1,25 +1,26 @@
|
||||
<div class="badges">
|
||||
|
||||
<div class="badges-header">
|
||||
<h3 class="badges-heading">{{i18n 'admin.badges.title'}}</h3>
|
||||
<div class="create-new-badge">
|
||||
{{#link-to 'adminBadges.show' 'new' class="btn btn-primary"}}
|
||||
{{d-icon "plus"}}
|
||||
<span>{{i18n 'admin.badges.new'}}</span>
|
||||
{{/link-to}}
|
||||
</div>
|
||||
</div>
|
||||
<div class='content-list'>
|
||||
<h3>{{i18n 'admin.badges.title'}}</h3>
|
||||
<ul>
|
||||
<ul class="admin-badge-list">
|
||||
{{#each model as |badge|}}
|
||||
<li>
|
||||
{{#link-to 'adminBadges.show' badge.id}}
|
||||
{{badge-button badge=badge}}
|
||||
{{#if badge.newBadge}}
|
||||
<span class="list-badge">{{i18n 'filters.new.lower_title'}}</span>
|
||||
{{/if}}
|
||||
{{/link-to}}
|
||||
</li>
|
||||
<li class="admin-badge-list-item">
|
||||
{{#link-to 'adminBadges.show' badge.id}}
|
||||
{{badge-button badge=badge}}
|
||||
{{#if badge.newBadge}}
|
||||
<span class="list-badge">{{i18n 'filters.new.lower_title'}}</span>
|
||||
{{/if}}
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{#link-to 'adminBadges.show' 'new' class="btn btn-default"}}
|
||||
{{d-icon "plus"}} {{i18n 'admin.badges.new'}}
|
||||
{{/link-to}}
|
||||
<br>
|
||||
<br>
|
||||
</div>
|
||||
|
||||
{{outlet}}
|
||||
</div>
|
||||
</div>
|
||||
@ -11,6 +11,6 @@
|
||||
{{d-button class="btn-default" action=(action "save") label="admin.user_fields.save"}}
|
||||
<a href {{action "edit"}}>{{i18n 'cancel'}}</a>
|
||||
{{else}}
|
||||
{{d-button class="btn-default" action=(action "edit") icon="pencil"}}
|
||||
{{d-button class="btn-default" action=(action "edit") icon="pencil-alt"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
<div class="chart-canvas-container">
|
||||
<canvas class="chart-canvas" height="250"></canvas>
|
||||
<canvas class="chart-canvas"></canvas>
|
||||
</div>
|
||||
|
||||
@ -46,9 +46,9 @@
|
||||
</div>
|
||||
<div class='form-display'>{{fieldName}}</div>
|
||||
<div class='form-element controls'>
|
||||
{{d-button action=(action "edit") class="btn-default" icon="pencil" label="admin.user_fields.edit"}}
|
||||
{{d-button action=(action "edit") class="btn-default" icon="pencil-alt" label="admin.user_fields.edit"}}
|
||||
|
||||
{{d-button action=destroyAction actionParam=userField class="btn-danger" icon="trash-o" label="admin.user_fields.delete"}}
|
||||
{{d-button action=destroyAction actionParam=userField class="btn-danger" icon="far-trash-alt" label="admin.user_fields.delete"}}
|
||||
{{d-button action=moveUpAction actionParam=userField class="btn-default" icon="arrow-up" disabled=cantMoveUp}}
|
||||
{{d-button action=moveDownAction actionParam=userField class="btn-default" icon="arrow-down" disabled=cantMoveDown}}
|
||||
</div>
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
<td><div class="label">{{i18n "admin.embedding.path_whitelist"}}</div>{{host.path_whitelist}}</td>
|
||||
<td><div class="label">{{i18n "admin.embedding.category"}}</div>{{category-badge host.category}}</td>
|
||||
<td class="controls">
|
||||
{{d-button icon="pencil" action=(action "edit")}}
|
||||
{{d-button icon="trash-o" action=(action "delete") class='btn-danger'}}
|
||||
{{d-button icon="pencil-alt" action=(action "edit")}}
|
||||
{{d-button icon="far-trash-alt" action=(action "delete") class='btn-danger'}}
|
||||
</td>
|
||||
{{/if}}
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
{{/link-to}}
|
||||
{{#if flaggedPost.wasEdited}}
|
||||
<div class='edited-after'>
|
||||
{{d-icon "pencil" title="admin.flags.was_edited"}}
|
||||
{{d-icon "pencil-alt" title="admin.flags.was_edited"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
@ -94,7 +94,7 @@
|
||||
class="btn-default defer-flag"
|
||||
title="admin.flags.ignore_flag_title"
|
||||
action=(action "defer")
|
||||
icon="external-link"
|
||||
icon="external-link-alt"
|
||||
label="admin.flags.ignore_flag"}}
|
||||
|
||||
{{admin-delete-flag-dropdown
|
||||
|
||||
@ -1,5 +1,25 @@
|
||||
<b>{{i18n 'admin.permalink.form.label'}}</b>
|
||||
{{text-field value=url disabled=formSubmitted class="permalink-url" placeholderKey="admin.permalink.url" autocorrect="off" autocapitalize="off"}}
|
||||
<b>{{i18n "admin.permalink.form.label"}}</b>
|
||||
|
||||
{{text-field
|
||||
value=url
|
||||
disabled=formSubmitted
|
||||
class="permalink-url"
|
||||
placeholderKey="admin.permalink.url"
|
||||
autocorrect="off"
|
||||
autocapitalize="off"}}
|
||||
|
||||
{{combo-box content=permalinkTypes value=permalinkType}}
|
||||
{{text-field value=permalink_type_value disabled=formSubmitted class="external-url" placeholderKey=permalinkTypePlaceholder autocorrect="off" autocapitalize="off"}}
|
||||
{{d-button class="btn-default" action=(action "submit") disabled=formSubmitted label="admin.permalink.form.add"}}
|
||||
|
||||
{{text-field
|
||||
value=permalink_type_value
|
||||
disabled=formSubmitted
|
||||
class="external-url"
|
||||
placeholderKey=permalinkTypePlaceholder
|
||||
autocorrect="off"
|
||||
autocapitalize="off"}}
|
||||
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "submit")
|
||||
disabled=formSubmitted
|
||||
label="admin.permalink.form.add"}}
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
</div>
|
||||
{{else if setting.overridden}}
|
||||
{{#if setting.secret}}
|
||||
{{d-button action=(action "toggleSecret") icon="eye-slash"}}
|
||||
{{d-button action=(action "toggleSecret") icon="far-eye-slash"}}
|
||||
{{/if}}
|
||||
{{d-button class="btn-default undo" action=(action "resetDefault") icon="undo" label="admin.settings.reset"}}
|
||||
{{/if}}
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
{{d-icon "check" class="default-indicator" title="admin.customize.theme.default_theme_tooltip"}}
|
||||
{{/if}}
|
||||
{{#if theme.isPendingUpdates}}
|
||||
{{d-icon "refresh" title="admin.customize.theme.updates_available_tooltip" class="light-grey-icon"}}
|
||||
{{d-icon "sync" title="admin.customize.theme.updates_available_tooltip" class="light-grey-icon"}}
|
||||
{{/if}}
|
||||
{{#if theme.isBroken}}
|
||||
{{d-icon "exclamation-circle" class="broken-indicator" title="admin.customize.theme.broken_theme_tooltip"}}
|
||||
|
||||
@ -9,32 +9,32 @@
|
||||
|
||||
<div class="themes-list-container">
|
||||
{{#if hasThemes}}
|
||||
{{#if componentsTabActive}}
|
||||
{{#each themesList as |theme|}}
|
||||
{{#if hasActiveThemes}}
|
||||
{{#each activeThemes as |theme|}}
|
||||
{{themes-list-item theme=theme navigateToTheme=(action "navigateToTheme" theme)}}
|
||||
{{/each}}
|
||||
{{else}}
|
||||
{{#if hasUserThemes}}
|
||||
{{#each userThemes as |theme|}}
|
||||
{{themes-list-item theme=theme navigateToTheme=(action "navigateToTheme" theme)}}
|
||||
{{/each}}
|
||||
|
||||
{{#if hasInactiveThemes}}
|
||||
<div class="themes-list-item inactive-indicator">
|
||||
<span class="empty">{{I18n "admin.customize.theme.inactive_themes"}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
{{#if hasInactiveThemes}}
|
||||
{{#each inactiveThemes as |theme|}}
|
||||
{{themes-list-item theme=theme navigateToTheme=(action "navigateToTheme" theme)}}
|
||||
{{/each}}
|
||||
<div class="themes-list-item inactive-indicator">
|
||||
<span class="empty">
|
||||
{{#if themesTabActive}}
|
||||
{{I18n "admin.customize.theme.inactive_themes"}}
|
||||
{{else}}
|
||||
{{I18n "admin.customize.theme.inactive_components"}}
|
||||
{{/if}}
|
||||
</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
{{#if hasInactiveThemes}}
|
||||
{{#each inactiveThemes as |theme|}}
|
||||
{{themes-list-item theme=theme navigateToTheme=(action "navigateToTheme" theme)}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<div class="themes-list-item">
|
||||
<span class="empty">{{I18n "admin.customize.theme.empty"}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
@ -11,7 +11,7 @@
|
||||
{{i18n "admin.customize.theme_owner"}}
|
||||
{{#link-to "adminCustomizeThemes.show" model.theme_id}}{{model.theme_name}}{{/link-to}}
|
||||
{{else}}
|
||||
<button {{action "destroy"}} class='btn btn-danger'>{{d-icon "trash-o"}} {{i18n 'admin.customize.delete'}}</button>
|
||||
<button {{action "destroy"}} class='btn btn-danger'>{{d-icon "far-trash-alt"}} {{i18n 'admin.customize.delete'}}</button>
|
||||
{{/if}}
|
||||
<span class="saving {{unless model.savingStatus 'hidden'}}">{{model.savingStatus}}</span>
|
||||
</div>
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<h1>{{I18n "admin.customize.theme.themes_intro"}}</h1>
|
||||
<div class="external-resources">
|
||||
{{#each externalResources as |resource|}}
|
||||
<a href={{resource.link}} class="external-link" target="_blank">
|
||||
<a href={{resource.link}} class="external-link-alt" target="_blank">
|
||||
{{d-icon resource.icon}}
|
||||
{{I18n resource.key}}
|
||||
</a>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
{{d-button action=(action "finishedEditingName") class="btn-primary submit-edit" icon="check"}}
|
||||
{{d-button action=(action "cancelEditingName") class="btn-default cancel-edit" icon="times"}}
|
||||
{{else}}
|
||||
{{model.name}} <a {{action "startEditingName"}}>{{d-icon "pencil"}}</a>
|
||||
{{model.name}} <a {{action "startEditingName"}}>{{d-icon "pencil-alt"}}</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
@ -16,33 +16,91 @@
|
||||
</div>
|
||||
{{/each}}
|
||||
|
||||
{{#if model.remote_theme}}
|
||||
{{#if model.remote_theme.remote_url}}
|
||||
<a class="remote-url" href="{{model.remote_theme.remote_url}}">{{model.remote_theme.remote_url}}</a>
|
||||
{{/if}}
|
||||
<a class="url about-url" href="{{model.remote_theme.about_url}}">{{i18n "admin.customize.theme.about_theme"}}</a>
|
||||
{{#if model.remote_theme.license_url}}
|
||||
<a class="url license-url" href="{{model.remote_theme.license_url}}">{{i18n "admin.customize.theme.license"}} {{d-icon "copyright"}}</a>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
{{#if parentThemes}}
|
||||
<div class="control-unit">
|
||||
<div class="mini-title">{{i18n "admin.customize.theme.component_of"}}</div>
|
||||
<ul>
|
||||
{{#each parentThemes as |theme|}}
|
||||
<li>{{#link-to 'adminCustomizeThemes.show' theme replace=true}}{{theme.name}}{{/link-to}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{#unless model.enabled}}
|
||||
<div class="alert alert-error">
|
||||
{{i18n "admin.customize.theme.required_version.error"}}
|
||||
{{#if model.remote_theme.minimum_discourse_version}}
|
||||
{{i18n "admin.customize.theme.required_version.minimum" version=model.remote_theme.minimum_discourse_version}}
|
||||
{{/if}}
|
||||
{{#if model.remote_theme.maximum_discourse_version}}
|
||||
{{i18n "admin.customize.theme.required_version.minimum" version=model.remote_theme.maximum_discourse_version}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
|
||||
{{#unless model.component}}
|
||||
<div class="control-unit">
|
||||
{{inline-edit-checkbox action=(action "applyDefault") labelKey="admin.customize.theme.is_default" checked=model.default}}
|
||||
{{inline-edit-checkbox action=(action "applyUserSelectable") labelKey="admin.customize.theme.user_selectable" checked=model.user_selectable}}
|
||||
</div>
|
||||
{{/unless}}
|
||||
|
||||
{{#if model.remote_theme}}
|
||||
|
||||
{{#if model.remote_theme.remote_url}}
|
||||
<a class="remote-url" href="{{model.remote_theme.remote_url}}">{{i18n "admin.customize.theme.source_url"}} {{d-icon "link"}}</a>
|
||||
{{/if}}
|
||||
{{#if model.remote_theme.about_url}}
|
||||
<a class="url about-url" href="{{model.remote_theme.about_url}}">{{i18n "admin.customize.theme.about_theme"}} {{d-icon "link"}}</a>
|
||||
{{/if}}
|
||||
{{#if model.remote_theme.license_url}}
|
||||
<a class="url license-url" href="{{model.remote_theme.license_url}}">{{i18n "admin.customize.theme.license"}} {{d-icon "link"}}</a>
|
||||
{{/if}}
|
||||
|
||||
{{#if model.description}}
|
||||
<span class="theme-description">{{model.description}}</span>
|
||||
{{/if}}
|
||||
|
||||
<span class="metadata">
|
||||
{{#if model.remote_theme.authors}}<span class="authors"><span class="heading">{{i18n "admin.customize.theme.authors"}}</span> {{model.remote_theme.authors}}</span>{{/if}}
|
||||
{{#if model.remote_theme.theme_version}}<span class="version"><span class="heading">{{i18n "admin.customize.theme.version"}}</span> {{model.remote_theme.theme_version}}</span>{{/if}}
|
||||
</span>
|
||||
|
||||
<div class="control-unit">
|
||||
{{#if model.remote_theme.is_git}}
|
||||
|
||||
{{#if showRemoteError}}
|
||||
<div class="error-message">
|
||||
{{d-icon "exclamation-triangle"}} {{I18n "admin.customize.theme.repo_unreachable"}}
|
||||
</div>
|
||||
<div class="raw-error">
|
||||
<code>{{model.remoteError}}</code>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if model.remote_theme.commits_behind}}
|
||||
{{#d-button action=(action "updateToLatest") icon="download" class='btn-primary'}}{{i18n "admin.customize.theme.update_to_latest"}}{{/d-button}}
|
||||
{{else}}
|
||||
{{#d-button action=(action "checkForThemeUpdates") icon="refresh" class="btn-default"}}{{i18n "admin.customize.theme.check_for_updates"}}{{/d-button}}
|
||||
{{/if}}
|
||||
|
||||
<span class='status-message'>
|
||||
{{#if updatingRemote}}
|
||||
{{i18n 'admin.customize.theme.updating'}}
|
||||
{{else}}
|
||||
{{#if model.remote_theme.commits_behind}}
|
||||
{{i18n 'admin.customize.theme.commits_behind' count=model.remote_theme.commits_behind}}
|
||||
{{#if model.remote_theme.github_diff_link}}
|
||||
<a href="{{model.remote_theme.github_diff_link}}">
|
||||
{{i18n 'admin.customize.theme.compare_commits'}}
|
||||
</a>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{#unless showRemoteError}}
|
||||
{{i18n 'admin.customize.theme.up_to_date'}} {{format-date model.remote_theme.updated_at leaveAgo="true"}}
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</span>
|
||||
{{else}}
|
||||
<span class='status-message'>
|
||||
{{d-icon "info-circle"}} {{i18n "admin.customize.theme.imported_from_archive"}}
|
||||
</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#unless model.component}}
|
||||
<div class="control-unit">
|
||||
<div class="mini-title">{{i18n "admin.customize.theme.color_scheme"}}</div>
|
||||
<div class="description">{{i18n "admin.customize.theme.color_scheme_select"}}</div>
|
||||
@ -60,6 +118,17 @@
|
||||
</div>
|
||||
{{/unless}}
|
||||
|
||||
{{#if parentThemes}}
|
||||
<div class="control-unit">
|
||||
<div class="mini-title">{{i18n "admin.customize.theme.component_of"}}</div>
|
||||
<ul>
|
||||
{{#each parentThemes as |theme|}}
|
||||
<li>{{#link-to 'adminCustomizeThemes.show' theme replace=true}}{{theme.name}}{{/link-to}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="control-unit">
|
||||
<div class="mini-title">{{i18n "admin.customize.theme.css_html"}}</div>
|
||||
{{#if model.hasEditedFields}}
|
||||
@ -75,43 +144,7 @@
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if model.remote_theme}}
|
||||
{{#if model.remote_theme.commits_behind}}
|
||||
{{#d-button action=(action "updateToLatest") icon="download" class='btn-primary'}}{{i18n "admin.customize.theme.update_to_latest"}}{{/d-button}}
|
||||
{{else}}
|
||||
{{#d-button action=(action "checkForThemeUpdates") icon="refresh" class="btn-default"}}{{i18n "admin.customize.theme.check_for_updates"}}{{/d-button}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
{{#d-button action=(action "editTheme") class="btn btn-default edit"}}{{i18n 'admin.customize.theme.edit_css_html'}}{{/d-button}}
|
||||
{{#if model.remote_theme}}
|
||||
<span class='status-message'>
|
||||
{{#if updatingRemote}}
|
||||
{{i18n 'admin.customize.theme.updating'}}
|
||||
{{else}}
|
||||
{{#if model.remote_theme.commits_behind}}
|
||||
{{i18n 'admin.customize.theme.commits_behind' count=model.remote_theme.commits_behind}}
|
||||
{{#if model.remote_theme.github_diff_link}}
|
||||
<a href="{{model.remote_theme.github_diff_link}}">
|
||||
{{i18n 'admin.customize.theme.compare_commits'}}
|
||||
</a>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{#unless showRemoteError}}
|
||||
{{i18n 'admin.customize.theme.up_to_date'}} {{format-date model.remote_theme.updated_at leaveAgo="true"}}
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</span>
|
||||
{{#if showRemoteError}}
|
||||
<div class="error-message">
|
||||
{{d-icon "exclamation-triangle"}} {{I18n "admin.customize.theme.repo_unreachable"}}
|
||||
</div>
|
||||
<div class="raw-error">
|
||||
<code>{{model.remoteError}}</code>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<div class="control-unit">
|
||||
@ -178,5 +211,5 @@
|
||||
<a class="btn btn-default export" target="_blank" href={{downloadUrl}}>{{d-icon "download"}} {{i18n 'admin.export_json.button_text'}}</a>
|
||||
|
||||
{{d-button action=(action "switchType") label="admin.customize.theme.convert" icon=convertIcon class="btn-default btn-normal" title=convertTooltip}}
|
||||
{{d-button action=(action "destroy") label="admin.customize.delete" icon="trash" class="btn-danger"}}
|
||||
{{d-button action=(action "destroy") label="admin.customize.delete" icon="trash-alt" class="btn-danger"}}
|
||||
</div>
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
<tr>
|
||||
<th><img class="emoji emoji-custom" src="{{unbound e.url}}" title="{{unbound e.name}}"></th>
|
||||
<th>:{{e.name}}:</th>
|
||||
<th><button {{action "destroy" e}} class='btn btn-danger no-text pull-right'>{{d-icon 'trash-o'}} </button></th>
|
||||
<th><button {{action "destroy" e}} class='btn btn-danger no-text pull-right'>{{d-icon "far-trash-alt"}} </button></th>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
|
||||
@ -1,26 +1,38 @@
|
||||
<p>{{i18n 'admin.logs.screened_ips.description'}}</p>
|
||||
<p>{{i18n "admin.logs.screened_ips.description"}}</p>
|
||||
|
||||
<div class="screened-ip-controls">
|
||||
<div class="filter-screened-ip-address">
|
||||
{{text-field value=filter class="ip-address-input" placeholderKey="admin.logs.screened_ips.form.filter" autocorrect="off" autocapitalize="off"}}
|
||||
{{d-button class="btn-default" action=(action "rollUp") title="admin.logs.screened_ips.roll_up.title" label="admin.logs.screened_ips.roll_up.text"}}
|
||||
{{d-button class="btn-default" action=(action "exportScreenedIpList") icon="download" title="admin.export_csv.button_title.screened_ip" label="admin.export_csv.button_text"}}
|
||||
<div class="filter-screened-ip-address">
|
||||
{{text-field
|
||||
value=filter
|
||||
class="ip-address-input"
|
||||
placeholderKey="admin.logs.screened_ips.form.filter"
|
||||
autocorrect="off"
|
||||
autocapitalize="off"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "rollUp")
|
||||
title="admin.logs.screened_ips.roll_up.title"
|
||||
label="admin.logs.screened_ips.roll_up.text"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "exportScreenedIpList")
|
||||
icon="download"
|
||||
title="admin.export_csv.button_title.screened_ip"
|
||||
label="admin.export_csv.button_text"}}
|
||||
</div>
|
||||
{{screened-ip-address-form action=(action "recordAdded")}}
|
||||
|
||||
{{screened-ip-address-form action=(action "recordAdded")}}
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{{#conditional-loading-spinner condition=loading}}
|
||||
{{#if model.length}}
|
||||
|
||||
<table class='admin-logs-table screened-ip-addresses grid'>
|
||||
<table class="admin-logs-table screened-ip-addresses grid">
|
||||
<thead class="heading-container">
|
||||
<th class="col heading first ip_address">{{i18n 'admin.logs.ip_address'}}</th>
|
||||
<th class="col heading action">{{i18n 'admin.logs.action'}}</th>
|
||||
<th class="col heading match_count">{{i18n 'admin.logs.match_count'}}</th>
|
||||
<th class="col heading created_at">{{i18n 'admin.logs.created_at'}}</th>
|
||||
<th class="col heading last_match_at">{{i18n 'admin.logs.last_match_at'}}</th>
|
||||
<th class="col heading first ip_address">{{i18n "admin.logs.ip_address"}}</th>
|
||||
<th class="col heading action">{{i18n "admin.logs.action"}}</th>
|
||||
<th class="col heading match_count">{{i18n "admin.logs.match_count"}}</th>
|
||||
<th class="col heading created_at">{{i18n "admin.logs.created_at"}}</th>
|
||||
<th class="col heading last_match_at">{{i18n "admin.logs.last_match_at"}}</th>
|
||||
<th class="col heading actions"></th>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -47,34 +59,64 @@
|
||||
{{/if}}
|
||||
{{item.actionName}}
|
||||
</td>
|
||||
<td class="col match_count"><div class="label">{{i18n 'admin.logs.match_count'}}</div> {{item.match_count}}</td>
|
||||
<td class="col created_at"><div class="label">{{i18n 'admin.logs.created_at'}}</div> {{age-with-tooltip item.created_at}}</td>
|
||||
|
||||
<td class="col match_count">
|
||||
<div class="label">{{i18n "admin.logs.match_count"}}</div>
|
||||
{{item.match_count}}
|
||||
</td>
|
||||
<td class="col created_at">
|
||||
<div class="label">{{i18n "admin.logs.created_at"}}</div>
|
||||
{{age-with-tooltip item.created_at}}
|
||||
</td>
|
||||
<td class="col last_match_at">
|
||||
{{#if item.last_match_at}}
|
||||
<div class="label">{{i18n 'admin.logs.last_match_at'}} {{age-with-tooltip item.last_match_at}}</div>
|
||||
<div class="label">
|
||||
{{i18n "admin.logs.last_match_at"}}
|
||||
{{age-with-tooltip item.last_match_at}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</td>
|
||||
<td class="col actions">
|
||||
{{#unless item.editing}}
|
||||
{{d-button class="btn-default" action=(action "destroy") actionParam=item icon="trash-o" class="btn-danger"}}
|
||||
{{d-button class="btn-default"action=(action "edit") actionParam=item icon="pencil"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "destroy")
|
||||
actionParam=item
|
||||
icon="far-trash-alt"
|
||||
class="btn-danger"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "edit")
|
||||
actionParam=item
|
||||
icon="pencil-alt"}}
|
||||
{{#if item.isBlocked}}
|
||||
{{d-button class="btn-default" action=(action "allow") actionParam=item icon="check" label="admin.logs.screened_ips.actions.do_nothing"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "allow")
|
||||
actionParam=item
|
||||
icon="check"
|
||||
label="admin.logs.screened_ips.actions.do_nothing"}}
|
||||
{{else}}
|
||||
{{d-button class="btn-default" action=(action "block") actionParam=item icon="ban" label="admin.logs.screened_ips.actions.block"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "block")
|
||||
actionParam=item
|
||||
icon="ban"
|
||||
label="admin.logs.screened_ips.actions.block"}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{d-button class="btn-default" action=(action "save") actionParam=item label="admin.logs.save"}}
|
||||
<a {{action "cancel" item}}>{{i18n 'cancel'}}</a>
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "save")
|
||||
actionParam=item
|
||||
label="admin.logs.save"}}
|
||||
<a {{action "cancel" item}}>{{i18n "cancel"}}</a>
|
||||
{{/unless}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{{else}}
|
||||
{{i18n 'search.no_results'}}
|
||||
{{i18n "search.no_results"}}
|
||||
{{/if}}
|
||||
{{/conditional-loading-spinner}}
|
||||
|
||||
@ -62,7 +62,7 @@
|
||||
<a {{action "filterByStaffUser" item.acting_user}}>{{item.acting_user.username}}</a>
|
||||
{{else}}
|
||||
<span class="deleted-user" title="{{i18n 'admin.user.deleted'}}">
|
||||
{{d-icon "trash-o"}}
|
||||
{{d-icon "far-trash-alt"}}
|
||||
</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
@ -1,30 +1,30 @@
|
||||
{{#d-modal-body title="admin.badges.badge_groupings.modal_title"}}
|
||||
<div>
|
||||
<ul class='badge-groupings'>
|
||||
{{#each workingCopy as |wc|}}
|
||||
<li class="badge-grouping-item">
|
||||
<div class="badge-grouping">
|
||||
{{#if wc.editing}}
|
||||
{{input value=wc.name class="badge-grouping-name-input"}}
|
||||
<button {{action "save" wc}} class="btn no-text">{{d-icon 'check'}}</button>
|
||||
{{else}}
|
||||
{{wc.displayName}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class='actions'>
|
||||
<button {{action "edit" wc}} class="btn no-text" disabled={{wc.system}}>{{d-icon 'pencil'}}</button>
|
||||
<button {{action "up" wc}} class="btn no-text">{{d-icon 'toggle-up'}}</button>
|
||||
<button {{action "down" wc}} class="btn no-text">{{d-icon 'toggle-down'}}</button>
|
||||
<button {{action "delete" wc}} class="btn no-text btn-danger" disabled={{wc.system}}>{{d-icon 'times'}}</button>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
{{#d-modal-body title="admin.badges.badge_groupings.modal_title" class="badge-groupings-modal"}}
|
||||
<div class="badge-groupings">
|
||||
<ul class='badge-groupings-list'>
|
||||
{{#each workingCopy as |wc|}}
|
||||
<li class="badge-grouping-item">
|
||||
<div class="badge-grouping">
|
||||
{{#if wc.editing}}
|
||||
{{input value=wc.name class="badge-grouping-name-input"}}
|
||||
<button {{action "save" wc}} class="btn no-text">{{d-icon 'check'}}</button>
|
||||
{{else}}
|
||||
<span>{{wc.displayName}}</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class='actions'>
|
||||
<button {{action "edit" wc}} class="btn no-text" disabled={{wc.system}}>{{d-icon 'pencil-alt'}}</button>
|
||||
<button {{action "up" wc}} class="btn no-text">{{d-icon 'chevron-up'}}</button>
|
||||
<button {{action "down" wc}} class="btn no-text">{{d-icon 'chevron-down'}}</button>
|
||||
<button {{action "delete" wc}} class="btn no-text btn-danger"
|
||||
disabled={{wc.system}}>{{d-icon 'times'}}</button>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
<button class='btn' {{action "add"}}>{{i18n 'admin.badges.new'}}</button>
|
||||
<button class='btn new-badge-grouping' {{action "add"}}>{{i18n 'admin.badges.new'}}</button>
|
||||
{{/d-modal-body}}
|
||||
|
||||
<div class="modal-footer">
|
||||
<button class='btn btn-primary' {{action "saveAll"}} disabled={{submitDisabled}}>{{i18n 'admin.badges.save'}}</button>
|
||||
{{d-modal-cancel close=(route-action "closeModal")}}
|
||||
</div>
|
||||
</div>
|
||||
@ -4,7 +4,7 @@
|
||||
<label class="radio" for="local">{{i18n 'upload_selector.from_my_computer'}}</label>
|
||||
{{#if local}}
|
||||
<div class="inputs">
|
||||
<input onchange={{action "uploadLocaleFile"}} type="file" id="file-input" accept='.dcstyle.json,application/json'><br>
|
||||
<input onchange={{action "uploadLocaleFile"}} type="file" id="file-input" accept='.dcstyle.json,application/json,.tar.gz,application/x-gzip'><br>
|
||||
<span class="description">{{i18n 'admin.customize.theme.import_file_tip'}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
@ -19,7 +19,7 @@
|
||||
<span class="description">{{i18n 'admin.customize.theme.import_web_tip'}}</span>
|
||||
</div>
|
||||
<div class='branch'>
|
||||
{{input value=branch placeholder="beta"}}
|
||||
{{input value=branch placeholder="master"}}
|
||||
<span class="description">{{i18n 'admin.customize.theme.remote_branch'}}</span>
|
||||
</div>
|
||||
<div class='check-private'>
|
||||
|
||||
@ -42,7 +42,7 @@
|
||||
{{/if}}
|
||||
</td>
|
||||
<td class="col action">
|
||||
{{d-button action=(action "destroy") actionParam=pl icon="trash-o" class="btn-danger"}}
|
||||
{{d-button action=(action "destroy") actionParam=pl icon="far-trash-alt" class="btn-danger"}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
|
||||
@ -49,7 +49,7 @@
|
||||
<td class="settings">
|
||||
{{#if currentUser.admin}}
|
||||
{{#if plugin.enabled_setting}}
|
||||
{{d-button class="btn-default" action=(route-action "showSettings") actionParam=plugin icon="gear" label="admin.plugins.change_settings_short"}}
|
||||
{{d-button class="btn-default" action=(route-action "showSettings") actionParam=plugin icon="cog" label="admin.plugins.change_settings_short"}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</td>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
|
||||
{{#if currentUser.admin}}
|
||||
{{d-button label="admin.plugins.change_settings"
|
||||
icon="gear"
|
||||
icon="cog"
|
||||
class="btn-default settings-button"
|
||||
action=(route-action "showSettings")}}
|
||||
{{/if}}
|
||||
|
||||
@ -1,58 +1,80 @@
|
||||
<section class="details {{unless model.active 'not-activated'}}">
|
||||
<div class='user-controls'>
|
||||
<div class="user-controls">
|
||||
{{#if model.canViewProfile}}
|
||||
{{#link-to 'user' model class="btn btn-default"}}
|
||||
{{#link-to "user" model class="btn btn-default"}}
|
||||
{{d-icon "user"}}
|
||||
{{i18n 'admin.user.show_public_profile'}}
|
||||
{{i18n "admin.user.show_public_profile"}}
|
||||
{{/link-to}}
|
||||
{{/if}}
|
||||
|
||||
{{#if model.can_view_action_logs}}
|
||||
{{d-button action=(action "viewActionLogs") class="btn-default" actionParam=model.username icon="list-alt" label="admin.user.action_logs"}}
|
||||
{{d-button
|
||||
action=(action "viewActionLogs")
|
||||
class="btn-default"
|
||||
actionParam=model.username
|
||||
icon="far-list-alt"
|
||||
label="admin.user.action_logs"}}
|
||||
{{/if}}
|
||||
{{#if model.active}}
|
||||
{{#if currentUser.admin}}
|
||||
{{d-button class="btn-default" action=(action "logOut") icon="power-off" label="admin.user.log_out"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "logOut")
|
||||
icon="power-off"
|
||||
label="admin.user.log_out"}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{plugin-outlet name="admin-user-controls-after" args=(hash model=model) tagName="" connectorTagName=""}}
|
||||
{{plugin-outlet
|
||||
name="admin-user-controls-after"
|
||||
args=(hash model=model)
|
||||
tagName=""
|
||||
connectorTagName=""}}
|
||||
</div>
|
||||
|
||||
<div class='display-row username'>
|
||||
{{admin-editable-field name='user.username.title'
|
||||
<div class="display-row username">
|
||||
{{admin-editable-field name="user.username.title"
|
||||
value=model.username
|
||||
action=(action 'saveUsername')
|
||||
action=(action "saveUsername")
|
||||
editing=editingUsername}}
|
||||
</div>
|
||||
|
||||
<div class='display-row'>
|
||||
{{admin-editable-field name='user.name.title'
|
||||
<div class="display-row">
|
||||
{{admin-editable-field name="user.name.title"
|
||||
value=model.name
|
||||
action=(action 'saveName')
|
||||
action=(action "saveName")
|
||||
editing=editingName}}
|
||||
</div>
|
||||
|
||||
{{plugin-outlet name="admin-user-below-names" args=(hash user=model) tagName='' connectorTagName=''}}
|
||||
{{plugin-outlet
|
||||
name="admin-user-below-names"
|
||||
args=(hash user=model)
|
||||
tagName=""
|
||||
connectorTagName=""}}
|
||||
|
||||
{{#if canCheckEmails}}
|
||||
<div class='display-row email'>
|
||||
<div class='field'>{{i18n 'user.email.primary'}}</div>
|
||||
<div class='value'>
|
||||
<div class="display-row email">
|
||||
<div class="field">{{i18n "user.email.primary"}}</div>
|
||||
<div class="value">
|
||||
{{#unless model.active}}
|
||||
<div class='controls'>{{i18n 'admin.users.not_verified'}}</div>
|
||||
<div class="controls">{{i18n "admin.users.not_verified"}}</div>
|
||||
{{/unless}}
|
||||
{{#if model.email}}
|
||||
<a href="mailto:{{unbound model.email}}">{{model.email}}</a>
|
||||
{{else}}
|
||||
{{d-button class="btn-default" action=(route-action "checkEmail") actionParam=model icon="envelope-o" label="admin.users.check_email.text" title="admin.users.check_email.title"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(route-action "checkEmail")
|
||||
actionParam=model icon="far-envelope"
|
||||
label="admin.users.check_email.text"
|
||||
title="admin.users.check_email.title"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='display-row secondary-emails'>
|
||||
<div class='field'>{{i18n 'user.email.secondary'}}</div>
|
||||
<div class="display-row secondary-emails">
|
||||
<div class="field">{{i18n "user.email.secondary"}}</div>
|
||||
|
||||
<div class='value'>
|
||||
<div class="value">
|
||||
{{#if model.email}}
|
||||
{{#if model.secondary_emails}}
|
||||
<ul>
|
||||
@ -61,13 +83,13 @@
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{else}}
|
||||
{{i18n 'user.email.no_secondary'}}
|
||||
{{i18n "user.email.no_secondary"}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{d-button action=(route-action "checkEmail")
|
||||
class="btn-default"
|
||||
actionParam=model
|
||||
icon="envelope-o"
|
||||
icon="far-envelope"
|
||||
label="admin.users.check_email.text"
|
||||
title="admin.users.check_email.title"}}
|
||||
{{/if}}
|
||||
@ -75,58 +97,70 @@
|
||||
</div>
|
||||
|
||||
<div class="display-row bounce-score">
|
||||
<div class='field'><a href="{{model.bounceLink}}">{{i18n 'admin.user.bounce_score'}}</a></div>
|
||||
<div class='value'>{{model.bounceScore}}</div>
|
||||
<div class='controls'>
|
||||
<div class="field"><a href="{{model.bounceLink}}">{{i18n "admin.user.bounce_score"}}</a></div>
|
||||
<div class="value">{{model.bounceScore}}</div>
|
||||
<div class="controls">
|
||||
{{#if model.canResetBounceScore}}
|
||||
{{d-button class="btn-default" action=(action "resetBounceScore") label="admin.user.reset_bounce_score.label" title="admin.user.reset_bounce_score.title"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "resetBounceScore")
|
||||
label="admin.user.reset_bounce_score.label"
|
||||
title="admin.user.reset_bounce_score.title"}}
|
||||
{{/if}}
|
||||
{{model.bounceScoreExplanation}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='display-row associations'>
|
||||
<div class='field'>{{i18n 'user.associated_accounts.title'}}</div>
|
||||
<div class='value'>
|
||||
<div class="display-row associations">
|
||||
<div class="field">{{i18n "user.associated_accounts.title"}}</div>
|
||||
<div class="value">
|
||||
{{#if associatedAccountsLoaded}}
|
||||
{{associatedAccounts}}
|
||||
{{else}}
|
||||
{{d-button class="btn-default" action=(route-action "checkEmail") actionParam=model icon="envelope-o" label="admin.users.check_email.text" title="admin.users.check_email.title"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(route-action "checkEmail")
|
||||
actionParam=model icon="far-envelope"
|
||||
label="admin.users.check_email.text"
|
||||
title="admin.users.check_email.title"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'user.avatar.title'}}</div>
|
||||
<div class='value'>{{avatar model imageSize="large"}}</div>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "user.avatar.title"}}</div>
|
||||
<div class="value">{{avatar model imageSize="large"}}</div>
|
||||
<div class="controls">
|
||||
{{{i18n "admin.user.visit_profile" url=preferencesPath}}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='display-row'>
|
||||
{{admin-editable-field name='user.title.title'
|
||||
<div class="display-row">
|
||||
{{admin-editable-field name="user.title.title"
|
||||
value=model.title
|
||||
action=(action 'saveTitle')
|
||||
action=(action "saveTitle")
|
||||
editing=editingTitle}}
|
||||
</div>
|
||||
|
||||
<div class='display-row last-ip'>
|
||||
<div class='field'>{{i18n 'user.ip_address.title'}}</div>
|
||||
<div class='value'>{{model.ip_address}}</div>
|
||||
<div class='controls'>
|
||||
<div class="display-row last-ip">
|
||||
<div class="field">{{i18n "user.ip_address.title"}}</div>
|
||||
<div class="value">{{model.ip_address}}</div>
|
||||
<div class="controls">
|
||||
{{#if currentUser.staff}}
|
||||
{{d-button class="btn-default" action=(action "refreshBrowsers") label="admin.user.refresh_browsers"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "refreshBrowsers")
|
||||
label="admin.user.refresh_browsers"}}
|
||||
{{ip-lookup ip=model.ip_address userId=model.id}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='display-row registration-ip'>
|
||||
<div class='field'>{{i18n 'user.registration_ip_address.title'}}</div>
|
||||
<div class='value'>{{model.registration_ip_address}}</div>
|
||||
<div class='controls'>
|
||||
<div class="display-row registration-ip">
|
||||
<div class="field">{{i18n "user.registration_ip_address.title"}}</div>
|
||||
<div class="value">{{model.registration_ip_address}}</div>
|
||||
<div class="controls">
|
||||
{{#if currentUser.staff}}
|
||||
{{ip-lookup ip=model.registration_ip_address userId=model.id}}
|
||||
{{/if}}
|
||||
@ -134,40 +168,47 @@
|
||||
</div>
|
||||
|
||||
{{#if showBadges}}
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.badges.title'}}</div>
|
||||
<div class='value'>
|
||||
{{i18n 'badges.badge_count' count=model.badge_count}}
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.badges.title"}}</div>
|
||||
<div class="value">
|
||||
{{i18n "badges.badge_count" count=model.badge_count}}
|
||||
</div>
|
||||
<div class='controls'>
|
||||
{{#link-to 'adminUser.badges' model class="btn"}}{{d-icon "certificate"}}{{i18n 'admin.badges.edit_badges'}}{{/link-to}}
|
||||
<div class="controls">
|
||||
{{#link-to "adminUser.badges" model class="btn"}}
|
||||
{{d-icon "certificate"}}
|
||||
{{i18n "admin.badges.edit_badges"}}
|
||||
{{/link-to}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'user.second_factor.title'}}</div>
|
||||
<div class='value'>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "user.second_factor.title"}}</div>
|
||||
<div class="value">
|
||||
{{#if model.second_factor_enabled}}
|
||||
{{i18n "yes_value"}}
|
||||
{{else}}
|
||||
{{i18n "no_value"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class='controls'>
|
||||
<div class="controls">
|
||||
{{#if canDisableSecondFactor}}
|
||||
{{d-button class="btn-default" action=(action "disableSecondFactor") icon="unlock-alt" label="user.second_factor.disable"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "disableSecondFactor")
|
||||
icon="unlock-alt"
|
||||
label="user.second_factor.disable"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{{#if userFields}}
|
||||
<section class='details'>
|
||||
<section class="details">
|
||||
{{#each userFields as |uf|}}
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{uf.name}}</div>
|
||||
<div class='value'>
|
||||
<div class="display-row">
|
||||
<div class="field">{{uf.name}}</div>
|
||||
<div class="value">
|
||||
{{#if uf.value}}
|
||||
{{uf.value}}
|
||||
{{else}}
|
||||
@ -181,107 +222,154 @@
|
||||
|
||||
{{plugin-outlet name="admin-user-details" args=(hash model=model)}}
|
||||
|
||||
<section class='details'>
|
||||
<h1>{{i18n 'admin.user.permissions'}}</h1>
|
||||
<section class="details">
|
||||
<h1>{{i18n "admin.user.permissions"}}</h1>
|
||||
|
||||
{{#if showApproval}}
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.users.approved'}}</div>
|
||||
<div class='value'>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.users.approved"}}</div>
|
||||
<div class="value">
|
||||
{{#if model.approved}}
|
||||
{{i18n 'admin.user.approved_by'}}
|
||||
{{#link-to 'adminUser' model.approvedBy}}{{avatar model.approvedBy imageSize="small"}}{{/link-to}}
|
||||
{{#link-to 'adminUser' model.approvedBy}}{{model.approvedBy.username}}{{/link-to}}
|
||||
{{i18n "admin.user.approved_by"}}
|
||||
{{#link-to "adminUser" model.approvedBy}}
|
||||
{{avatar model.approvedBy imageSize="small"}}
|
||||
{{/link-to}}
|
||||
{{#link-to "adminUser" model.approvedBy}}
|
||||
{{model.approvedBy.username}}
|
||||
{{/link-to}}
|
||||
{{else}}
|
||||
{{i18n 'no_value'}}
|
||||
{{i18n "no_value"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class='controls'>
|
||||
<div class="controls">
|
||||
{{#if model.approved}}
|
||||
{{i18n 'admin.user.approve_success'}}
|
||||
{{i18n "admin.user.approve_success"}}
|
||||
{{else}}
|
||||
{{#if model.can_approve}}
|
||||
{{d-button class="btn-default" action=(action "approve") icon="check" label="admin.user.approve"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "approve")
|
||||
icon="check"
|
||||
label="admin.user.approve"}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.users.active'}}</div>
|
||||
<div class='value'>{{i18n-yes-no model.active}}</div>
|
||||
<div class='controls'>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.users.active"}}</div>
|
||||
<div class="value">{{i18n-yes-no model.active}}</div>
|
||||
<div class="controls">
|
||||
{{#if model.active}}
|
||||
{{#if model.can_deactivate}}
|
||||
{{d-button class="btn-default" action=(action "deactivate") label="admin.user.deactivate_account"}}
|
||||
{{i18n 'admin.user.deactivate_explanation'}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "deactivate")
|
||||
label="admin.user.deactivate_account"}}
|
||||
{{i18n "admin.user.deactivate_explanation"}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{#if model.can_send_activation_email}}
|
||||
{{d-button class="btn-default" action=(action "sendActivationEmail") icon="envelope" label="admin.user.send_activation_email"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "sendActivationEmail")
|
||||
icon="envelope"
|
||||
label="admin.user.send_activation_email"}}
|
||||
{{/if}}
|
||||
{{#if model.can_activate}}
|
||||
{{d-button class="btn-default" action=(action "activate") icon="check" label="admin.user.activate"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "activate")
|
||||
icon="check"
|
||||
label="admin.user.activate"}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="display-row">
|
||||
<div class='field'>{{i18n 'admin.user.staged'}}</div>
|
||||
<div class='value'>{{i18n-yes-no model.staged}}</div>
|
||||
<div class='controls'>{{i18n 'admin.user.staged_explanation'}}</div>
|
||||
<div class="field">{{i18n "admin.user.staged"}}</div>
|
||||
<div class="value">{{i18n-yes-no model.staged}}</div>
|
||||
<div class="controls">{{i18n "admin.user.staged_explanation"}}</div>
|
||||
</div>
|
||||
|
||||
{{#if currentUser.admin}}
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.api.key'}}</div>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.api.key"}}</div>
|
||||
{{#if model.api_key}}
|
||||
<div class='long-value'>
|
||||
<div class="long-value">
|
||||
{{model.api_key.key}}
|
||||
{{d-button class="btn-default" action=(action "regenerateApiKey") icon="undo" label="admin.api.regenerate"}}
|
||||
{{d-button class="btn-default" action=(action "revokeApiKey") icon="times" label="admin.api.revoke"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "regenerateApiKey")
|
||||
icon="undo"
|
||||
label="admin.api.regenerate"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "revokeApiKey")
|
||||
icon="times"
|
||||
label="admin.api.revoke"}}
|
||||
</div>
|
||||
{{else}}
|
||||
<div class='value'>
|
||||
<div class="value">
|
||||
—
|
||||
</div>
|
||||
<div class='controls'>
|
||||
{{d-button class="btn-default" action=(action "generateApiKey") icon="key" label="admin.api.generate"}}
|
||||
<div class="controls">
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "generateApiKey")
|
||||
icon="key"
|
||||
label="admin.api.generate"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.user.admin'}}</div>
|
||||
<div class='value'>{{i18n-yes-no model.admin}}</div>
|
||||
<div class='controls'>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.admin"}}</div>
|
||||
<div class="value">{{i18n-yes-no model.admin}}</div>
|
||||
<div class="controls">
|
||||
{{#if model.can_revoke_admin}}
|
||||
{{d-button class="btn-default" action=(action "revokeAdmin") icon="shield" label="admin.user.revoke_admin"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "revokeAdmin")
|
||||
icon="shield-alt"
|
||||
label="admin.user.revoke_admin"}}
|
||||
{{/if}}
|
||||
{{#if model.can_grant_admin}}
|
||||
{{d-button class="btn-default" action=(action "grantAdmin") icon="shield" label="admin.user.grant_admin"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "grantAdmin")
|
||||
icon="shield-alt"
|
||||
label="admin.user.grant_admin"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.user.moderator'}}</div>
|
||||
<div class='value'>{{i18n-yes-no model.moderator}}</div>
|
||||
<div class='controls'>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.moderator"}}</div>
|
||||
<div class="value">{{i18n-yes-no model.moderator}}</div>
|
||||
<div class="controls">
|
||||
{{#if model.can_revoke_moderation}}
|
||||
{{d-button class="btn-default" action=(action "revokeModeration") icon="shield" label="admin.user.revoke_moderation"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "revokeModeration")
|
||||
icon="shield-alt"
|
||||
label="admin.user.revoke_moderation"}}
|
||||
{{/if}}
|
||||
{{#if model.can_grant_moderation}}
|
||||
{{d-button class="btn-default" action=(action "grantModeration") icon="shield" label="admin.user.grant_moderation"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "grantModeration")
|
||||
icon="shield-alt"
|
||||
label="admin.user.grant_moderation"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'trust_level'}}</div>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "trust_level"}}</div>
|
||||
<div class="value">
|
||||
{{combo-box content=site.trustLevels value=model.trust_level nameProperty="detailedName"}}
|
||||
{{#if model.dirty}}
|
||||
@ -295,21 +383,31 @@
|
||||
{{#if model.canLockTrustLevel}}
|
||||
{{#if hasLockedTrustLevel}}
|
||||
{{d-icon "lock" title="admin.user.trust_level_locked_tip"}}
|
||||
{{d-button class="btn-default" action=(action "lockTrustLevel") actionParam=false label="admin.user.unlock_trust_level"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "lockTrustLevel")
|
||||
actionParam=false
|
||||
label="admin.user.unlock_trust_level"}}
|
||||
{{else}}
|
||||
{{d-icon "unlock" title="admin.user.trust_level_unlocked_tip"}}
|
||||
{{d-button class="btn-default" action=(action "lockTrustLevel") actionParam=true label="admin.user.lock_trust_level"}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "lockTrustLevel")
|
||||
actionParam=true
|
||||
label="admin.user.lock_trust_level"}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{#if model.tl3Requirements}}
|
||||
{{#link-to 'adminUser.tl3Requirements' model class="btn btn-default"}}{{i18n 'admin.user.trust_level_3_requirements'}}{{/link-to}}
|
||||
{{#link-to "adminUser.tl3Requirements" model class="btn btn-default"}}
|
||||
{{i18n "admin.user.trust_level_3_requirements"}}
|
||||
{{/link-to}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="user-suspended display-row {{if model.suspended 'highlight-danger'}}">
|
||||
<div class='field'>{{i18n 'admin.user.suspended'}}</div>
|
||||
<div class='value'>
|
||||
<div class="user-suspended display-row {{if model.suspended "highlight-danger"}}">
|
||||
<div class="field">{{i18n "admin.user.suspended"}}</div>
|
||||
<div class="value">
|
||||
{{i18n-yes-no model.suspended}}
|
||||
{{#if model.suspended}}
|
||||
{{#unless model.suspendedForever}}
|
||||
@ -317,14 +415,14 @@
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class='controls'>
|
||||
<div class="controls">
|
||||
{{#if model.suspended}}
|
||||
{{d-button
|
||||
class="btn-danger unsuspend-user"
|
||||
action=(action "unsuspend")
|
||||
icon="ban"
|
||||
label="admin.user.unsuspend"}}
|
||||
{{i18n 'admin.user.suspended_explanation'}}
|
||||
{{i18n "admin.user.suspended_explanation"}}
|
||||
{{else}}
|
||||
{{#if model.canSuspend}}
|
||||
{{d-button
|
||||
@ -332,29 +430,33 @@
|
||||
action=(action "showSuspendModal")
|
||||
icon="ban"
|
||||
label="admin.user.suspend"}}
|
||||
{{i18n 'admin.user.suspended_explanation'}}
|
||||
{{i18n "admin.user.suspended_explanation"}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if model.suspended}}
|
||||
<div class='display-row highlight-danger suspension-info'>
|
||||
<div class='field'>{{i18n 'admin.user.suspended_by'}}</div>
|
||||
<div class='value'>
|
||||
{{#link-to 'adminUser' model.suspendedBy}}{{avatar model.suspendedBy imageSize="tiny"}}{{/link-to}}
|
||||
{{#link-to 'adminUser' model.suspendedBy}}{{model.suspendedBy.username}}{{/link-to}}
|
||||
<div class="display-row highlight-danger suspension-info">
|
||||
<div class="field">{{i18n "admin.user.suspended_by"}}</div>
|
||||
<div class="value">
|
||||
{{#link-to "adminUser" model.suspendedBy}}
|
||||
{{avatar model.suspendedBy imageSize="tiny"}}
|
||||
{{/link-to}}
|
||||
{{#link-to "adminUser" model.suspendedBy}}
|
||||
{{model.suspendedBy.username}}
|
||||
{{/link-to}}
|
||||
</div>
|
||||
<div class='controls'>
|
||||
<b>{{i18n 'admin.user.suspend_reason'}}</b>:
|
||||
<div class='full-reason'>{{model.full_suspend_reason}}</div>
|
||||
<div class="controls">
|
||||
<b>{{i18n "admin.user.suspend_reason"}}</b>:
|
||||
<div class="full-reason">{{model.full_suspend_reason}}</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="display-row {{if model.silenced 'highlight-danger'}}">
|
||||
<div class='field'>{{i18n 'admin.user.silenced'}}</div>
|
||||
<div class='value'>
|
||||
<div class="display-row {{if model.silenced "highlight-danger"}}">
|
||||
<div class="field">{{i18n "admin.user.silenced"}}</div>
|
||||
<div class="value">
|
||||
{{i18n-yes-no model.silenced}}
|
||||
{{#if model.silenced}}
|
||||
{{#unless model.silencedForever}}
|
||||
@ -362,7 +464,7 @@
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class='controls'>
|
||||
<div class="controls">
|
||||
{{#conditional-loading-spinner size="small" condition=model.silencingUser}}
|
||||
{{#if model.silenced}}
|
||||
{{d-button
|
||||
@ -370,39 +472,43 @@
|
||||
action=(action "unsilence")
|
||||
icon="microphone-slash"
|
||||
label="admin.user.unsilence"}}
|
||||
{{i18n 'admin.user.silence_explanation'}}
|
||||
{{i18n "admin.user.silence_explanation"}}
|
||||
{{else}}
|
||||
{{d-button
|
||||
class="btn-danger silence-user"
|
||||
action=(action "showSilenceModal")
|
||||
icon="microphone-slash"
|
||||
label="admin.user.silence"}}
|
||||
{{i18n 'admin.user.silence_explanation'}}
|
||||
{{i18n "admin.user.silence_explanation"}}
|
||||
{{/if}}
|
||||
{{/conditional-loading-spinner}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if model.silenced}}
|
||||
<div class='display-row highlight-danger silence-info'>
|
||||
<div class='field'>{{i18n 'admin.user.silenced_by'}}</div>
|
||||
<div class='value'>
|
||||
{{#link-to 'adminUser' model.silencedBy}}{{avatar model.silencedBy imageSize="tiny"}}{{/link-to}}
|
||||
{{#link-to 'adminUser' model.silencedBy}}{{model.silencedBy.username}}{{/link-to}}
|
||||
<div class="display-row highlight-danger silence-info">
|
||||
<div class="field">{{i18n "admin.user.silenced_by"}}</div>
|
||||
<div class="value">
|
||||
{{#link-to "adminUser" model.silencedBy}}
|
||||
{{avatar model.silencedBy imageSize="tiny"}}
|
||||
{{/link-to}}
|
||||
{{#link-to "adminUser" model.silencedBy}}
|
||||
{{model.silencedBy.username}}
|
||||
{{/link-to}}
|
||||
</div>
|
||||
<div class='controls'>
|
||||
<b>{{i18n 'admin.user.silence_reason'}}</b>:
|
||||
<div class='full-reason'>{{model.silence_reason}}</div>
|
||||
<div class="controls">
|
||||
<b>{{i18n "admin.user.silence_reason"}}</b>:
|
||||
<div class="full-reason">{{model.silence_reason}}</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if model.tl3_requirements.penalty_counts.total}}
|
||||
<div class='display-row clear-penalty-history'>
|
||||
<div class='field'>{{i18n 'admin.user.penalty_count'}}</div>
|
||||
<div class='value'>{{model.tl3_requirements.penalty_counts.total}}</div>
|
||||
<div class="display-row clear-penalty-history">
|
||||
<div class="field">{{i18n "admin.user.penalty_count"}}</div>
|
||||
<div class="value">{{model.tl3_requirements.penalty_counts.total}}</div>
|
||||
{{#if currentUser.admin}}
|
||||
<div class='controls'>
|
||||
<div class="controls">
|
||||
{{d-button label="admin.user.clear_penalty_history.title"
|
||||
class="btn-default"
|
||||
icon="times"
|
||||
@ -416,32 +522,38 @@
|
||||
</section>
|
||||
|
||||
{{#if currentUser.admin}}
|
||||
<section class='details'>
|
||||
<h1>{{i18n 'admin.groups.title'}}</h1>
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.groups.automatic'}}</div>
|
||||
<div class='value'>{{{automaticGroups}}}</div>
|
||||
<section class="details">
|
||||
<h1>{{i18n "admin.groups.title"}}</h1>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.groups.automatic"}}</div>
|
||||
<div class="value">{{{automaticGroups}}}</div>
|
||||
</div>
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.groups.custom'}}</div>
|
||||
<div class='value'>
|
||||
{{admin-group-selector selected=model.customGroups available=availableGroups buffer=customGroupIdsBuffer}}
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.groups.custom"}}</div>
|
||||
<div class="value">
|
||||
{{admin-group-selector
|
||||
selected=model.customGroups
|
||||
available=availableGroups
|
||||
buffer=customGroupIdsBuffer}}
|
||||
</div>
|
||||
{{#if customGroupsDirty}}
|
||||
<div class='controls'>
|
||||
<div class="controls">
|
||||
{{d-button icon="check" class="ok" action=(action "saveCustomGroups")}}
|
||||
{{d-button icon="times" class="cancel" action=(action "resetCustomGroups")}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{#if model.customGroups}}
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.groups.primary'}}</div>
|
||||
<div class='value'>
|
||||
{{combo-box content=model.customGroups value=model.primary_group_id none="admin.groups.no_primary"}}
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.groups.primary"}}</div>
|
||||
<div class="value">
|
||||
{{combo-box
|
||||
content=model.customGroups
|
||||
value=model.primary_group_id
|
||||
none="admin.groups.no_primary"}}
|
||||
</div>
|
||||
{{#if primaryGroupDirty}}
|
||||
<div class='controls'>
|
||||
<div class="controls">
|
||||
{{d-button icon="check" class="ok" action=(action "savePrimaryGroup")}}
|
||||
{{d-button icon="times" class="cancel" action=(action "resetPrimaryGroup")}}
|
||||
</div>
|
||||
@ -451,56 +563,60 @@
|
||||
</section>
|
||||
{{/if}}
|
||||
|
||||
<section class='details'>
|
||||
<h1>{{i18n 'admin.user.activity'}}</h1>
|
||||
<section class="details">
|
||||
<h1>{{i18n "admin.user.activity"}}</h1>
|
||||
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'created'}}</div>
|
||||
<div class='value'>{{format-date model.created_at leaveAgo="true"}}</div>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "created"}}</div>
|
||||
<div class="value">{{format-date model.created_at leaveAgo="true"}}</div>
|
||||
</div>
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.users.last_emailed'}}</div>
|
||||
<div class='value'>{{format-date model.last_emailed_at}}</div>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.users.last_emailed"}}</div>
|
||||
<div class="value">{{format-date model.last_emailed_at}}</div>
|
||||
</div>
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'last_seen'}}</div>
|
||||
<div class='value'>{{format-date model.last_seen_at leaveAgo="true"}}</div>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "last_seen"}}</div>
|
||||
<div class="value">{{format-date model.last_seen_at leaveAgo="true"}}</div>
|
||||
</div>
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.user.like_count'}}</div>
|
||||
<div class='value'>{{model.like_given_count}} / {{model.like_count}}</div>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.like_count"}}</div>
|
||||
<div class="value">{{model.like_given_count}} / {{model.like_count}}</div>
|
||||
</div>
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.user.topics_entered'}}</div>
|
||||
<div class='value'>{{model.topics_entered}}</div>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.topics_entered"}}</div>
|
||||
<div class="value">{{model.topics_entered}}</div>
|
||||
</div>
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.user.post_count'}}</div>
|
||||
<div class='value'>{{model.post_count}}</div>
|
||||
<div class='controls'>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.post_count"}}</div>
|
||||
<div class="value">{{model.post_count}}</div>
|
||||
<div class="controls">
|
||||
{{#if model.can_delete_all_posts}}
|
||||
{{#if model.post_count}}
|
||||
{{d-button class="btn-danger" action=(action "deleteAllPosts") icon="trash-o" label="admin.user.delete_all_posts"}}
|
||||
{{d-button
|
||||
class="btn-danger"
|
||||
action=(action "deleteAllPosts")
|
||||
icon="far-trash-alt"
|
||||
label="admin.user.delete_all_posts"}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{deleteAllPostsExplanation}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.user.posts_read_count'}}</div>
|
||||
<div class='value'>{{model.posts_read_count}}</div>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.posts_read_count"}}</div>
|
||||
<div class="value">{{model.posts_read_count}}</div>
|
||||
</div>
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.user.warnings_received_count'}}</div>
|
||||
<div class='value'>{{model.warnings_received_count}}</div>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.warnings_received_count"}}</div>
|
||||
<div class="value">{{model.warnings_received_count}}</div>
|
||||
</div>
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.user.flags_given_received_count'}}</div>
|
||||
<div class='value'>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.flags_given_received_count"}}</div>
|
||||
<div class="value">
|
||||
{{model.flags_given_count}} / {{model.flags_received_count}}
|
||||
</div>
|
||||
<div class='controls'>
|
||||
<div class="controls">
|
||||
{{#if model.flags_received_count}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
@ -511,46 +627,46 @@
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.user.private_topics_count'}}</div>
|
||||
<div class='value'>{{model.private_topics_count}}</div>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.private_topics_count"}}</div>
|
||||
<div class="value">{{model.private_topics_count}}</div>
|
||||
</div>
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.user.time_read'}}</div>
|
||||
<div class='value'>{{{format-duration model.time_read}}}</div>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.time_read"}}</div>
|
||||
<div class="value">{{{format-duration model.time_read}}}</div>
|
||||
</div>
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'user.invited.days_visited'}}</div>
|
||||
<div class='value'>{{{model.days_visited}}}</div>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "user.invited.days_visited"}}</div>
|
||||
<div class="value">{{{model.days_visited}}}</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{{#if model.single_sign_on_record}}
|
||||
<section class='details'>
|
||||
<h1>{{i18n 'admin.user.sso.title'}}</h1>
|
||||
<section class="details">
|
||||
<h1>{{i18n "admin.user.sso.title"}}</h1>
|
||||
|
||||
{{#with model.single_sign_on_record as |sso|}}
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.user.sso.external_id'}}</div>
|
||||
<div class='value'>{{sso.external_id}}</div>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.sso.external_id"}}</div>
|
||||
<div class="value">{{sso.external_id}}</div>
|
||||
</div>
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.user.sso.external_username'}}</div>
|
||||
<div class='value'>{{sso.external_username}}</div>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.sso.external_username"}}</div>
|
||||
<div class="value">{{sso.external_username}}</div>
|
||||
</div>
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.user.sso.external_name'}}</div>
|
||||
<div class='value'>{{sso.external_name}}</div>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.sso.external_name"}}</div>
|
||||
<div class="value">{{sso.external_name}}</div>
|
||||
</div>
|
||||
{{#if sso.external_email}}
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.user.sso.external_email'}}</div>
|
||||
<div class='value'>{{sso.external_email}}</div>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.sso.external_email"}}</div>
|
||||
<div class="value">{{sso.external_email}}</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class='display-row'>
|
||||
<div class='field'>{{i18n 'admin.user.sso.external_avatar_url'}}</div>
|
||||
<div class='value'>{{sso.external_avatar_url}}</div>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.sso.external_avatar_url"}}</div>
|
||||
<div class="value">{{sso.external_avatar_url}}</div>
|
||||
</div>
|
||||
{{/with}}
|
||||
</section>
|
||||
@ -563,7 +679,12 @@
|
||||
<div class="pull-right">
|
||||
{{#if model.active}}
|
||||
{{#if model.can_impersonate}}
|
||||
{{d-button class="btn-danger" action=(action "impersonate") icon="crosshairs" label="admin.impersonate.title" title="admin.impersonate.help"}}
|
||||
{{d-button
|
||||
class="btn-danger"
|
||||
action=(action "impersonate")
|
||||
icon="crosshairs"
|
||||
label="admin.impersonate.title"
|
||||
title="admin.impersonate.help"}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
@ -590,4 +711,5 @@
|
||||
</div>
|
||||
{{/if}}
|
||||
</section>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
|
||||
@ -52,7 +52,7 @@
|
||||
</a>
|
||||
{{#link-to 'adminUser' user}}{{unbound user.username}}{{/link-to}}
|
||||
{{#if user.staged}}
|
||||
{{d-icon "envelope-o" title="user.staged" }}
|
||||
{{d-icon "far-envelope" title="user.staged" }}
|
||||
{{/if}}
|
||||
</td>
|
||||
<td class='email'>
|
||||
|
||||
@ -9,13 +9,13 @@
|
||||
</div>
|
||||
|
||||
{{#if versionCheck.noCheckPerformed}}
|
||||
<div class="version-number">
|
||||
<h4>{{i18n 'admin.dashboard.latest_version'}}</h4>
|
||||
<div class="version-number">
|
||||
<h4>{{i18n 'admin.dashboard.latest_version'}}</h4>
|
||||
<h3>—</h3>
|
||||
</div>
|
||||
<div class="version-status">
|
||||
<div class="face">
|
||||
<span class="icon critical-updates-available">{{d-icon "frown-o"}}</span>
|
||||
<span class="icon critical-updates-available">{{d-icon "far-frown"}}</span>
|
||||
</div>
|
||||
<div class="version-notes">
|
||||
<span class="normal-note">{{i18n 'admin.dashboard.no_check_performed'}}</span>
|
||||
@ -24,15 +24,15 @@
|
||||
{{else}}
|
||||
{{#if versionCheck.stale_data}}
|
||||
<div class="version-number">
|
||||
<h4>{{i18n 'admin.dashboard.latest_version'}}</h4>
|
||||
<h4>{{i18n 'admin.dashboard.latest_version'}}</h4>
|
||||
<h3>{{#if versionCheck.version_check_pending}}{{dash-if-empty versionCheck.installed_version}}{{/if}}</h3>
|
||||
</div>
|
||||
<div class="version-status">
|
||||
<div class="face">
|
||||
{{#if versionCheck.version_check_pending}}
|
||||
<span class='icon up-to-date'>{{d-icon "smile-o"}}</span>
|
||||
<span class='icon up-to-date'>{{d-icon "far-smile"}}</span>
|
||||
{{else}}
|
||||
<span class="icon critical-updates-available">{{d-icon "frown-o"}}</span>
|
||||
<span class="icon critical-updates-available">{{d-icon "far-frown"}}</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="version-notes">
|
||||
@ -47,19 +47,19 @@
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="version-number">
|
||||
<h4>{{i18n 'admin.dashboard.latest_version'}}</h4>
|
||||
<h4>{{i18n 'admin.dashboard.latest_version'}}</h4>
|
||||
<h3>{{dash-if-empty versionCheck.latest_version}}</h3>
|
||||
</div>
|
||||
<div class="version-status">
|
||||
<div class="face">
|
||||
{{#if versionCheck.upToDate }}
|
||||
<span class='icon up-to-date'>{{d-icon "smile-o"}}</span>
|
||||
<span class='icon up-to-date'>{{d-icon "far-smile"}}</span>
|
||||
{{else}}
|
||||
<span class="icon {{if versionCheck.critical_updates 'critical-updates-available' 'updates-available'}}">
|
||||
{{#if versionCheck.behindByOneVersion}}
|
||||
{{d-icon "meh-o"}}
|
||||
{{else}}
|
||||
{{d-icon "frown-o"}}
|
||||
{{d-icon "far-frown"}}
|
||||
{{/if}}
|
||||
</span>
|
||||
{{/if}}
|
||||
|
||||
@ -32,7 +32,7 @@ const REPLACEMENTS = {
|
||||
"notification.moved_post": "sign-out",
|
||||
"notification.linked": "link",
|
||||
"notification.granted_badge": "certificate",
|
||||
"notification.topic_reminder": "hand-point-right",
|
||||
"notification.topic_reminder": "far-clock",
|
||||
"notification.watching_first_post": "far-dot-circle",
|
||||
"notification.group_message_summary": "group"
|
||||
};
|
||||
|
||||
@ -16,7 +16,7 @@ export default DropdownSelectBoxComponent.extend({
|
||||
},
|
||||
{
|
||||
id: "logOut",
|
||||
icon: "sign-out",
|
||||
icon: "sign-out-alt",
|
||||
name: I18n.t("user.log_out"),
|
||||
description: ""
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ export default Ember.Component.extend({
|
||||
|
||||
if (originalUser) {
|
||||
editTitle += `
|
||||
${iconHTML("mail-forward", { class: "reply-to-glyph" })}
|
||||
${iconHTML("share", { class: "reply-to-glyph" })}
|
||||
${originalUser.avatar}
|
||||
<span class="original-username">${originalUser.username}</span>
|
||||
`;
|
||||
|
||||
@ -163,7 +163,11 @@ export default Ember.Component.extend({
|
||||
includeMentionableGroups: true
|
||||
}),
|
||||
key: "@",
|
||||
transformComplete: v => v.username || v.name
|
||||
transformComplete: v => v.username || v.name,
|
||||
afterComplete() {
|
||||
// ensures textarea scroll position is correct
|
||||
Ember.run.scheduleOnce("afterRender", () => $input.blur().focus());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -816,7 +820,7 @@ export default Ember.Component.extend({
|
||||
toolbar.addButton({
|
||||
id: "quote",
|
||||
group: "fontStyles",
|
||||
icon: "comment-o",
|
||||
icon: "far-comment",
|
||||
sendAction: this.get("importQuote"),
|
||||
title: "composer.quote_post_title",
|
||||
unshift: true
|
||||
@ -835,7 +839,7 @@ export default Ember.Component.extend({
|
||||
toolbar.addButton({
|
||||
id: "options",
|
||||
group: "extras",
|
||||
icon: "gear",
|
||||
icon: "cog",
|
||||
title: "composer.options",
|
||||
sendAction: this.onExpandPopupMenuOptions.bind(this),
|
||||
popupMenu: true
|
||||
|
||||
@ -134,7 +134,7 @@ class Toolbar {
|
||||
this.addButton({
|
||||
id: "toggle-direction",
|
||||
group: "extras",
|
||||
icon: "exchange",
|
||||
icon: "exchange-alt",
|
||||
shortcut: "Shift+6",
|
||||
title: "composer.toggle_direction",
|
||||
perform: e => e.toggleDirection()
|
||||
@ -385,10 +385,14 @@ export default Ember.Component.extend({
|
||||
|
||||
_applyCategoryHashtagAutocomplete() {
|
||||
const siteSettings = this.siteSettings;
|
||||
const self = this;
|
||||
|
||||
this.$(".d-editor-input").autocomplete({
|
||||
template: findRawTemplate("category-tag-autocomplete"),
|
||||
key: "#",
|
||||
afterComplete() {
|
||||
self._focusTextArea();
|
||||
},
|
||||
transformComplete(obj) {
|
||||
return obj.text;
|
||||
},
|
||||
@ -416,6 +420,7 @@ export default Ember.Component.extend({
|
||||
key: ":",
|
||||
afterComplete(text) {
|
||||
self.set("value", text);
|
||||
self._focusTextArea();
|
||||
},
|
||||
|
||||
onKeyUp(text, cp) {
|
||||
@ -722,7 +727,7 @@ export default Ember.Component.extend({
|
||||
$textarea.prop("selectionStart", (pre + text).length + 2);
|
||||
$textarea.prop("selectionEnd", (pre + text).length + 2);
|
||||
|
||||
Ember.run.scheduleOnce("afterRender", () => $textarea.focus());
|
||||
this._focusTextArea();
|
||||
},
|
||||
|
||||
_addText(sel, text, options) {
|
||||
@ -747,7 +752,8 @@ export default Ember.Component.extend({
|
||||
$textarea.val(value);
|
||||
$textarea.prop("selectionStart", insert.length);
|
||||
$textarea.prop("selectionEnd", insert.length);
|
||||
Ember.run.scheduleOnce("afterRender", () => $textarea.focus());
|
||||
|
||||
this._focusTextArea();
|
||||
},
|
||||
|
||||
_extractTable(text) {
|
||||
@ -838,6 +844,12 @@ export default Ember.Component.extend({
|
||||
}
|
||||
},
|
||||
|
||||
// ensures textarea scroll position is correct
|
||||
_focusTextArea() {
|
||||
const $textarea = this.$("textarea.d-editor-input");
|
||||
Ember.run.scheduleOnce("afterRender", () => $textarea.blur().focus());
|
||||
},
|
||||
|
||||
actions: {
|
||||
emoji() {
|
||||
if (this.get("disabled")) {
|
||||
@ -850,6 +862,7 @@ export default Ember.Component.extend({
|
||||
emojiSelected(code) {
|
||||
let selected = this._getSelected();
|
||||
const captures = selected.pre.match(/\B:(\w*)$/);
|
||||
|
||||
if (_.isEmpty(captures)) {
|
||||
this._addText(selected, `:${code}:`);
|
||||
} else {
|
||||
|
||||
@ -1,15 +1,16 @@
|
||||
import { default as computed } from "ember-addons/ember-computed-decorators";
|
||||
import UploadMixin from "discourse/mixins/upload";
|
||||
|
||||
export default Ember.Component.extend(UploadMixin, {
|
||||
type: "emoji",
|
||||
uploadUrl: "/admin/customize/emojis",
|
||||
|
||||
hasName: Ember.computed.notEmpty("name"),
|
||||
addDisabled: Ember.computed.not("hasName"),
|
||||
|
||||
data: function() {
|
||||
return Ember.isBlank(this.get("name")) ? {} : { name: this.get("name") };
|
||||
}.property("name"),
|
||||
@computed("hasName", "name")
|
||||
data(hasName, name) {
|
||||
return hasName ? { name } : {};
|
||||
},
|
||||
|
||||
validateUploadedFilesOptions() {
|
||||
return { imagesOnly: true };
|
||||
|
||||
@ -32,7 +32,7 @@ export default DropdownSelectBoxComponent.extend({
|
||||
description: I18n.t("groups.members.remove_owner_description", {
|
||||
username: this.get("member.username")
|
||||
}),
|
||||
icon: "shield"
|
||||
icon: "shield-alt"
|
||||
});
|
||||
} else {
|
||||
items.push({
|
||||
@ -41,7 +41,7 @@ export default DropdownSelectBoxComponent.extend({
|
||||
description: I18n.t("groups.members.make_owner_description", {
|
||||
username: this.get("member.username")
|
||||
}),
|
||||
icon: "shield"
|
||||
icon: "shield-alt"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ export default Ember.Component.extend(
|
||||
|
||||
let autoCloseHours = this.get("duration") || 0;
|
||||
|
||||
buffer.push(`<h3>${iconHTML("clock-o")} `);
|
||||
buffer.push(`<h3>${iconHTML("far-clock")} `);
|
||||
|
||||
let options = {
|
||||
timeLeft: duration.humanize(true),
|
||||
|
||||
@ -222,7 +222,7 @@ export default Ember.Controller.extend({
|
||||
@computed("model.action", "isWhispering")
|
||||
saveIcon(action, isWhispering) {
|
||||
if (isWhispering) {
|
||||
return "eye-slash";
|
||||
return "far-eye-slash";
|
||||
}
|
||||
return SAVE_ICONS[action];
|
||||
},
|
||||
@ -267,7 +267,7 @@ export default Ember.Controller.extend({
|
||||
this._setupPopupMenuOption(() => {
|
||||
return {
|
||||
action: "toggleInvisible",
|
||||
icon: "eye-slash",
|
||||
icon: "far-eye-slash",
|
||||
label: "composer.toggle_unlisted",
|
||||
condition: "canUnlistTopic"
|
||||
};
|
||||
@ -278,7 +278,7 @@ export default Ember.Controller.extend({
|
||||
this._setupPopupMenuOption(() => {
|
||||
return {
|
||||
action: "toggleWhisper",
|
||||
icon: "eye-slash",
|
||||
icon: "far-eye-slash",
|
||||
label: "composer.toggle_whisper",
|
||||
condition: "showWhisperToggle"
|
||||
};
|
||||
|
||||
@ -47,6 +47,7 @@ export default Ember.Controller.extend(PreferencesTabController, {
|
||||
|
||||
preferencesController: Ember.inject.controller("preferences"),
|
||||
makeThemeDefault: true,
|
||||
makeTextSizeDefault: true,
|
||||
|
||||
@computed()
|
||||
availableLocales() {
|
||||
@ -109,6 +110,11 @@ export default Ember.Controller.extend(PreferencesTabController, {
|
||||
this.set("model.user_option.theme_ids", [this.get("themeId")]);
|
||||
}
|
||||
|
||||
const makeTextSizeDefault = this.get("makeTextSizeDefault");
|
||||
if (makeTextSizeDefault) {
|
||||
this.set("model.user_option.text_size", this.get("textSize"));
|
||||
}
|
||||
|
||||
return this.get("model")
|
||||
.save(this.get("saveAttrNames"))
|
||||
.then(() => {
|
||||
@ -120,6 +126,9 @@ export default Ember.Controller.extend(PreferencesTabController, {
|
||||
this.get("model.user_option.theme_key_seq")
|
||||
);
|
||||
}
|
||||
if (!makeTextSizeDefault) {
|
||||
this.get("model").updateTextSizeCookie(this.get("textSize"));
|
||||
}
|
||||
|
||||
this.homeChanged();
|
||||
})
|
||||
|
||||
@ -1,16 +1,18 @@
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
import BufferedContent from "discourse/mixins/buffered-content";
|
||||
import { extractError } from "discourse/lib/ajax-error";
|
||||
|
||||
export default Ember.Controller.extend(ModalFunctionality, BufferedContent, {
|
||||
renameDisabled: function() {
|
||||
@computed("buffered.id", "id")
|
||||
renameDisabled(inputTagName, currentTagName) {
|
||||
const filterRegexp = new RegExp(this.site.tags_filter_regexp, "g"),
|
||||
newId = this.get("buffered.id")
|
||||
.replace(filterRegexp, "")
|
||||
.trim();
|
||||
newTagName = inputTagName
|
||||
? inputTagName.replace(filterRegexp, "").trim()
|
||||
: "";
|
||||
|
||||
return newId.length === 0 || newId === this.get("model.id");
|
||||
}.property("buffered.id", "id"),
|
||||
return newTagName.length === 0 || newTagName === currentTagName;
|
||||
},
|
||||
|
||||
actions: {
|
||||
performRename() {
|
||||
|
||||
@ -22,7 +22,7 @@ function addBulkButton(action, key, opts) {
|
||||
|
||||
// Default buttons
|
||||
addBulkButton("showChangeCategory", "change_category", {
|
||||
icon: "pencil",
|
||||
icon: "pencil-alt",
|
||||
class: "btn-default"
|
||||
});
|
||||
addBulkButton("closeTopics", "close_topics", {
|
||||
@ -42,12 +42,12 @@ addBulkButton("resetRead", "reset_read", {
|
||||
class: "btn-default"
|
||||
});
|
||||
addBulkButton("unlistTopics", "unlist_topics", {
|
||||
icon: "eye-slash",
|
||||
icon: "far-eye-slash",
|
||||
class: "btn-default",
|
||||
buttonVisible: topics => topics.some(t => t.visible)
|
||||
});
|
||||
addBulkButton("relistTopics", "relist_topics", {
|
||||
icon: "eye",
|
||||
icon: "far-eye",
|
||||
class: "btn-default",
|
||||
buttonVisible: topics => topics.some(t => !t.visible)
|
||||
});
|
||||
|
||||
@ -14,10 +14,12 @@ export default htmlHelper((user, args) => {
|
||||
}
|
||||
|
||||
if (currentUser && user.get("admin") && currentUser.get("staff")) {
|
||||
return iconHTML("shield", { label: I18n.t("user.admin", { user: name }) });
|
||||
return iconHTML("shield-alt", {
|
||||
label: I18n.t("user.admin", { user: name })
|
||||
});
|
||||
}
|
||||
if (user.get("moderator")) {
|
||||
return iconHTML("shield", {
|
||||
return iconHTML("shield-alt", {
|
||||
label: I18n.t("user.moderator", { user: name })
|
||||
});
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ export default {
|
||||
toolbar.addButton({
|
||||
id: "emoji",
|
||||
group: "extras",
|
||||
icon: "smile-o",
|
||||
icon: "far-smile",
|
||||
action: () => toolbar.context.send("emoji"),
|
||||
title: "composer.emoji"
|
||||
});
|
||||
|
||||
@ -153,6 +153,8 @@ export default {
|
||||
|
||||
replyToTopic() {
|
||||
this._replyToPost();
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
selectDown() {
|
||||
@ -194,12 +196,21 @@ export default {
|
||||
},
|
||||
|
||||
createTopic() {
|
||||
if (this.currentUser && this.currentUser.can_create_topic) {
|
||||
this.container.lookup("controller:composer").open({
|
||||
action: Composer.CREATE_TOPIC,
|
||||
draftKey: Composer.CREATE_TOPIC
|
||||
});
|
||||
if (!(this.currentUser && this.currentUser.can_create_topic)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the page has a create-topic button, use it for context sensitive attributes like category
|
||||
let $createTopicButton = $("#create-topic");
|
||||
if ($createTopicButton.length) {
|
||||
$createTopicButton.click();
|
||||
return;
|
||||
}
|
||||
|
||||
this.container.lookup("controller:composer").open({
|
||||
action: Composer.CREATE_TOPIC,
|
||||
draftKey: Composer.CREATE_TOPIC
|
||||
});
|
||||
},
|
||||
|
||||
focusComposer() {
|
||||
@ -332,6 +343,8 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
_bindToSelectedPost(action, binding) {
|
||||
|
||||
@ -45,7 +45,10 @@ function show(image) {
|
||||
};
|
||||
|
||||
copyImg.src = imageData.src;
|
||||
copyImg.srcset = imageData.srcset || copyImg.srcset;
|
||||
|
||||
if (imageData.srcset) {
|
||||
copyImg.srcset = imageData.srcset;
|
||||
}
|
||||
|
||||
copyImg.style.position = "absolute";
|
||||
copyImg.style.top = `${image.offsetTop}px`;
|
||||
|
||||
@ -133,12 +133,20 @@ class PluginApi {
|
||||
*
|
||||
* // for the place in code that render a string
|
||||
* string() {
|
||||
* return "<i class='fa fa-smile-o'></i>";
|
||||
* return "<svg class=\"fa d-icon d-icon-far-smile svg-icon\" aria-hidden=\"true\"><use xlink:href=\"#far-smile\"></use></svg>";
|
||||
* },
|
||||
*
|
||||
* // for the places in code that render virtual dom elements
|
||||
* node() {
|
||||
* return h('i', { className: 'fa fa-smile-o' });
|
||||
* return h("svg", {
|
||||
* attributes: { class: "fa d-icon d-icon-far-smile", "aria-hidden": true },
|
||||
* namespace: "http://www.w3.org/2000/svg"
|
||||
* },[
|
||||
* h("use", {
|
||||
* "xlink:href": attributeHook("http://www.w3.org/1999/xlink", `#far-smile`),
|
||||
* namespace: "http://www.w3.org/2000/svg"
|
||||
* })]
|
||||
* );
|
||||
* }
|
||||
* });
|
||||
**/
|
||||
@ -369,7 +377,7 @@ class PluginApi {
|
||||
* api.addToolbarPopupMenuOptionsCallback(() => {
|
||||
* return {
|
||||
* action: 'toggleWhisper',
|
||||
* icon: 'eye-slash',
|
||||
* icon: 'far-eye-slash',
|
||||
* label: 'composer.toggle_whisper',
|
||||
* condition: "canWhisper"
|
||||
* };
|
||||
|
||||
@ -74,9 +74,7 @@ export default {
|
||||
.finally(() => {
|
||||
_processing--;
|
||||
|
||||
// when a request is done we want to start processing queue
|
||||
// without waiting for debouncing
|
||||
debounce(this, this._processQueue, DEBOUNCING_DELAY, true);
|
||||
debounce(this, this._processQueue, DEBOUNCING_DELAY);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@ -8,6 +8,9 @@ const msoListClasses = [
|
||||
"MsoListParagraphCxSpMiddle",
|
||||
"MsoListParagraphCxSpLast"
|
||||
];
|
||||
const hasChild = (e, n) => {
|
||||
return (e.children || []).some(c => c.name === n);
|
||||
};
|
||||
|
||||
export class Tag {
|
||||
constructor(name, prefix = "", suffix = "", inline = false) {
|
||||
@ -194,14 +197,19 @@ export class Tag {
|
||||
}
|
||||
|
||||
decorate(text) {
|
||||
const attr = this.element.attributes;
|
||||
const e = this.element;
|
||||
const attr = e.attributes;
|
||||
|
||||
if (/^mention/.test(attr.class) && "@" === text[0]) {
|
||||
return text;
|
||||
}
|
||||
|
||||
if ("hashtag" === attr.class && "#" === text[0]) {
|
||||
} else if ("hashtag" === attr.class && "#" === text[0]) {
|
||||
return text;
|
||||
} else if (
|
||||
["lightbox", "d-lazyload"].includes(attr.class) &&
|
||||
hasChild(e, "img")
|
||||
) {
|
||||
text = attr.title || "";
|
||||
return "";
|
||||
}
|
||||
|
||||
if (attr.href && text !== attr.href) {
|
||||
|
||||
@ -415,7 +415,7 @@ export function allowsAttachments() {
|
||||
}
|
||||
|
||||
export function uploadIcon() {
|
||||
return allowsAttachments() ? "upload" : "picture-o";
|
||||
return allowsAttachments() ? "upload" : "far-image";
|
||||
}
|
||||
|
||||
export function uploadLocation(url) {
|
||||
|
||||
@ -59,6 +59,40 @@ const Topic = RestModel.extend({
|
||||
return user || this.get("creator");
|
||||
},
|
||||
|
||||
@computed("posters.[]", "participants.[]")
|
||||
featuredUsers(posters, participants) {
|
||||
let users = posters;
|
||||
const maxUserCount = 5;
|
||||
const posterCount = users.length;
|
||||
|
||||
if (
|
||||
this.get("isPrivateMessage") &&
|
||||
participants &&
|
||||
posterCount < maxUserCount
|
||||
) {
|
||||
let pushOffset = 0;
|
||||
if (posterCount > 1) {
|
||||
const lastUser = users[posterCount - 1];
|
||||
if (lastUser.extras && lastUser.extras.includes("latest")) {
|
||||
pushOffset = 1;
|
||||
}
|
||||
}
|
||||
|
||||
const poster_ids = _.pluck(posters, "user_id");
|
||||
participants.some(p => {
|
||||
if (!poster_ids.includes(p.user_id)) {
|
||||
users.splice(users.length - pushOffset, 0, p);
|
||||
if (users.length === maxUserCount) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
return users;
|
||||
},
|
||||
|
||||
@computed("fancy_title")
|
||||
fancyTitle(title) {
|
||||
let fancyTitle = censor(
|
||||
|
||||
@ -141,7 +141,7 @@ const UserAction = RestModel.extend({
|
||||
groups = {
|
||||
likes: UserActionGroup.create({ icon: "heart" }),
|
||||
stars: UserActionGroup.create({ icon: "star" }),
|
||||
edits: UserActionGroup.create({ icon: "pencil" }),
|
||||
edits: UserActionGroup.create({ icon: "pencil-alt" }),
|
||||
bookmarks: UserActionGroup.create({ icon: "bookmark" })
|
||||
};
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ export default RestModel.extend({
|
||||
|
||||
remove(draft) {
|
||||
let content = this.get("content").filter(
|
||||
item => item.sequence !== draft.sequence
|
||||
item => item.draft_key !== draft.draft_key
|
||||
);
|
||||
this.setProperties({ content, itemsLoaded: content.length });
|
||||
},
|
||||
|
||||
@ -705,6 +705,25 @@ const User = RestModel.extend({
|
||||
});
|
||||
|
||||
return _.uniq(titles).sort();
|
||||
},
|
||||
|
||||
@computed("user_option.text_size_seq", "user_option.text_size")
|
||||
currentTextSize(serverSeq, serverSize) {
|
||||
if ($.cookie("text_size")) {
|
||||
const [cookieSize, cookieSeq] = $.cookie("text_size").split("|");
|
||||
if (cookieSeq >= serverSeq) {
|
||||
return cookieSize;
|
||||
}
|
||||
}
|
||||
return serverSize;
|
||||
},
|
||||
|
||||
updateTextSizeCookie(newSize) {
|
||||
const seq = this.get("user_option.text_size_seq");
|
||||
$.cookie("text_size", `${newSize}|${seq}`, {
|
||||
path: "/",
|
||||
expires: 9999
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -5,7 +5,8 @@ export default RestrictedUserRoute.extend({
|
||||
|
||||
setupController(controller, user) {
|
||||
controller.setProperties({
|
||||
model: user
|
||||
model: user,
|
||||
textSize: user.get("currentTextSize")
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@ -6,6 +6,11 @@ import PermissionType from "discourse/models/permission-type";
|
||||
export default Discourse.Route.extend({
|
||||
navMode: "latest",
|
||||
|
||||
queryParams: {
|
||||
ascending: { refreshModel: true },
|
||||
order: { refreshModel: true }
|
||||
},
|
||||
|
||||
renderTemplate() {
|
||||
const controller = this.controllerFor("tags.show");
|
||||
this.render("tags.show", { controller });
|
||||
@ -60,11 +65,13 @@ export default Discourse.Route.extend({
|
||||
return tag;
|
||||
},
|
||||
|
||||
afterModel(tag) {
|
||||
afterModel(tag, transition) {
|
||||
const controller = this.controllerFor("tags.show");
|
||||
controller.set("loading", true);
|
||||
|
||||
const params = controller.getProperties("order", "ascending");
|
||||
params.order = transition.queryParams.order || params.order;
|
||||
params.ascending = transition.queryParams.ascending || params.ascending;
|
||||
|
||||
const categorySlug = this.get("categorySlug");
|
||||
const parentCategorySlug = this.get("parentCategorySlug");
|
||||
|
||||
@ -11,8 +11,7 @@ export default Discourse.Route.extend(ViewingActionType, {
|
||||
this.controllerFor("user-activity").set("userActionType", userActionType);
|
||||
this.controllerFor("user-topics-list").setProperties({
|
||||
model,
|
||||
hideCategory: false,
|
||||
showParticipants: false
|
||||
hideCategory: false
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@ -97,7 +97,7 @@
|
||||
|
||||
{{#if contactInfo}}
|
||||
<section class='about contact'>
|
||||
<h3>{{d-icon "envelope-o"}} {{i18n 'about.contact'}}</h3>
|
||||
<h3>{{d-icon "far-envelope"}} {{i18n 'about.contact'}}</h3>
|
||||
<p>{{{contactInfo}}}</p>
|
||||
</section>
|
||||
{{/if}}
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
{{d-button
|
||||
class="btn btn-default pad-left no-text"
|
||||
action=(action "toggleSetUserTitle")
|
||||
icon="pencil"}}
|
||||
icon="pencil-alt"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if model.multiple_grant}}
|
||||
|
||||
@ -7,5 +7,5 @@
|
||||
|
||||
{{d-button action=editActivationEmail
|
||||
label="login.change_email"
|
||||
icon="pencil"
|
||||
icon="pencil-alt"
|
||||
class="edit-email"}}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<label class="btn" disabled={{uploading}} title="{{i18n 'user.change_avatar.upload_title'}}">
|
||||
{{d-icon "picture-o"}} {{uploadButtonText}}
|
||||
{{d-icon "far-image"}} {{uploadButtonText}}
|
||||
<input class="hidden-upload-field" disabled={{uploading}} type="file" accept="image/*" />
|
||||
</label>
|
||||
{{#if uploading}}
|
||||
|
||||
@ -10,8 +10,7 @@
|
||||
{{/if}}
|
||||
|
||||
{{#if topics}}
|
||||
{{topic-list showParticipants=showParticipants
|
||||
showPosters=showPosters
|
||||
{{topic-list showPosters=showPosters
|
||||
hideCategory=hideCategory
|
||||
topics=topics
|
||||
expandExcerpts=expandExcerpts
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{{#if isEditing}}
|
||||
{{d-icon "pencil"}}
|
||||
{{d-icon "pencil-alt"}}
|
||||
{{else}}
|
||||
{{composer-actions
|
||||
composerModel=model
|
||||
|
||||
@ -6,10 +6,10 @@
|
||||
{{i18n "user.desktop_notifications.perm_denied_expl"}}
|
||||
{{else}}
|
||||
{{#if isEnabled}}
|
||||
{{d-button icon="bell-slash-o" class="btn-default" label="user.desktop_notifications.disable" action=(action "turnoff")}}
|
||||
{{d-button icon="far-bell-slash" class="btn-default" label="user.desktop_notifications.disable" action=(action "turnoff")}}
|
||||
{{i18n "user.desktop_notifications.currently_enabled"}}
|
||||
{{else}}
|
||||
{{d-button icon="bell-o" class="btn-default" label="user.desktop_notifications.enable" action=(action "turnon")}}
|
||||
{{d-button icon="far-bell" class="btn-default" label="user.desktop_notifications.enable" action=(action "turnon")}}
|
||||
{{i18n "user.desktop_notifications.currently_disabled"}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
{{/if}}
|
||||
{{#if category.topic_url}}
|
||||
<br>
|
||||
{{d-button class="btn-default" action=(action "showCategoryTopic") icon="pencil" label="category.change_in_category_topic"}}
|
||||
{{d-button class="btn-default" action=(action "showCategoryTopic") icon="pencil-alt" label="category.change_in_category_topic"}}
|
||||
{{/if}}
|
||||
</section>
|
||||
{{/if}}
|
||||
@ -56,7 +56,7 @@
|
||||
<span class='add-on'>#</span>{{text-field value=category.text_color placeholderKey="category.color_placeholder" maxlength="6"}}
|
||||
{{color-picker colors=foregroundColors value=category.text_color id='edit-text-color'}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{{/unless}}
|
||||
|
||||
@ -147,7 +147,7 @@
|
||||
|
||||
<section class='field'>
|
||||
<label for="category-email-in">
|
||||
{{d-icon "envelope-o"}}
|
||||
{{d-icon "far-envelope"}}
|
||||
{{i18n 'category.email_in'}}
|
||||
</label>
|
||||
{{text-field id="category-email-in" class="email-in" value=category.email_in}}
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
{{text-field name="name" placeholderKey="admin.emoji.name" value=name}}
|
||||
|
||||
<label class="btn btn-primary {{if addDisabled 'disabled'}}">
|
||||
{{d-icon "plus"}}
|
||||
{{i18n 'admin.emoji.add'}}
|
||||
<input class="hidden-upload-field" disabled={{addDisabled}} type="file" accept=".png,.gif" />
|
||||
{{i18n "admin.emoji.add"}}
|
||||
<input
|
||||
class="hidden-upload-field"
|
||||
disabled={{addDisabled}}
|
||||
type="file"
|
||||
accept=".png,.gif" />
|
||||
</label>
|
||||
|
||||
@ -14,11 +14,11 @@
|
||||
|
||||
{{#if isCustom}}
|
||||
<div class="control-group">
|
||||
{{d-icon "calendar"}} {{date-picker-future value=date defaultDate=date}}
|
||||
{{d-icon "calendar-alt"}} {{date-picker-future value=date defaultDate=date}}
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
{{d-icon "clock-o"}}
|
||||
{{d-icon "far-clock"}}
|
||||
{{input type="time" value=time}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<div class="uploaded-image-preview input-xxlarge" style={{backgroundStyle}}>
|
||||
<div class="image-upload-controls">
|
||||
<label class="btn btn-default pad-left no-text {{if uploading 'disabled'}}">
|
||||
{{d-icon "picture-o"}}
|
||||
{{d-icon "far-image"}}
|
||||
<input class="hidden-upload-field" disabled={{uploading}} type="file" accept="image/*" />
|
||||
</label>
|
||||
{{#if hasBackgroundStyle}}
|
||||
<button {{action "trash"}} class="btn btn-danger pad-left no-text">{{d-icon "trash-o"}}</button>
|
||||
<button {{action "trash"}} class="btn btn-danger pad-left no-text">{{d-icon "far-trash-alt"}}</button>
|
||||
{{/if}}
|
||||
<span class="btn {{unless uploading 'hidden'}}">{{i18n 'upload_selector.uploading'}} {{uploadProgress}}%</span>
|
||||
</div>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<label class="btn" disabled={{uploading}} title="{{i18n "admin.site_settings.uploaded_image_list.upload.title"}}">
|
||||
{{d-icon "picture-o"}} {{uploadButtonText}}
|
||||
{{d-icon "far-image"}} {{uploadButtonText}}
|
||||
<input class="hidden-upload-field" disabled={{uploading}} type="file" accept="image/*" multiple />
|
||||
</label>
|
||||
{{#if uploading}}
|
||||
|
||||
@ -1,36 +1,44 @@
|
||||
{{#if ip}}
|
||||
<button class="btn btn-default" {{action "lookup"}}>
|
||||
{{d-icon "globe"}}{{i18n 'admin.user.ip_lookup'}}
|
||||
{{d-icon "globe"}}
|
||||
{{i18n "admin.user.ip_lookup"}}
|
||||
</button>
|
||||
{{/if}}
|
||||
{{#if show}}
|
||||
<div class="location-box">
|
||||
<a class="close pull-right" {{action "hide"}}>{{d-icon "times"}}</a>
|
||||
{{#if copied}}
|
||||
<a class="btn btn-default btn-hover pull-right">{{d-icon "copy"}} {{i18n "ip_lookup.copied"}}</a>
|
||||
<a class="btn btn-default btn-hover pull-right">
|
||||
{{d-icon "copy"}}
|
||||
{{i18n "ip_lookup.copied"}}
|
||||
</a>
|
||||
{{else}}
|
||||
<a class="btn btn-default pull-right no-text" {{action "copy"}}>{{d-icon "copy"}}</a>
|
||||
<a class="btn btn-default pull-right no-text" {{action "copy"}}>
|
||||
{{d-icon "copy"}}
|
||||
</a>
|
||||
{{/if}}
|
||||
<h4>{{i18n 'ip_lookup.title'}}</h4>
|
||||
<p class='powered-by'>{{{i18n 'ip_lookup.powered_by'}}}</p>
|
||||
<h4>{{i18n "ip_lookup.title"}}</h4>
|
||||
<p class='powered-by'>{{{i18n "ip_lookup.powered_by"}}}</p>
|
||||
<dl>
|
||||
{{#if location}}
|
||||
{{#if location.hostname}}
|
||||
<dt>{{i18n 'ip_lookup.hostname'}}</dt>
|
||||
<dt>{{i18n "ip_lookup.hostname"}}</dt>
|
||||
<dd>{{location.hostname}}</dd>
|
||||
{{/if}}
|
||||
|
||||
<dt>{{i18n 'ip_lookup.location'}}</dt>
|
||||
<dt>{{i18n "ip_lookup.location"}}</dt>
|
||||
<dd>
|
||||
{{#if location.location}}
|
||||
<a href="https://maps.google.com/maps?q={{unbound location.latitude}},{{unbound location.longitude}}" target="_blank">{{location.location}}</a>
|
||||
<a href="https://maps.google.com/maps?q={{unbound location.latitude}},{{unbound location.longitude}}" target="_blank">
|
||||
{{location.location}}
|
||||
</a>
|
||||
{{else}}
|
||||
{{i18n 'ip_lookup.location_not_found'}}
|
||||
{{i18n "ip_lookup.location_not_found"}}
|
||||
{{/if}}
|
||||
</dd>
|
||||
|
||||
{{#if location.organization}}
|
||||
<dt>{{i18n 'ip_lookup.organisation'}}</dt>
|
||||
<dt>{{i18n "ip_lookup.organisation"}}</dt>
|
||||
<dd>{{location.organization}}</dd>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
@ -38,31 +46,39 @@
|
||||
{{/if}}
|
||||
|
||||
<dt>
|
||||
{{i18n 'ip_lookup.other_accounts'}}
|
||||
{{i18n "ip_lookup.other_accounts"}}
|
||||
<strong>{{totalOthersWithSameIP}}</strong>
|
||||
{{#if other_accounts.length}}
|
||||
<button class="btn btn-danger pull-right" {{action "deleteOtherAccounts"}}>
|
||||
{{d-icon "warning"}}{{i18n 'ip_lookup.delete_other_accounts' count=otherAccountsToDelete}}
|
||||
{{d-icon "warning"}}
|
||||
{{i18n "ip_lookup.delete_other_accounts" count=otherAccountsToDelete}}
|
||||
</button>
|
||||
{{/if}}
|
||||
</dt>
|
||||
|
||||
{{#conditional-loading-spinner size="small" condition=otherAccountsLoading}}
|
||||
{{#if other_accounts.length}}
|
||||
<dd class="other-accounts">
|
||||
<table class="table table-condensed table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{i18n 'ip_lookup.username'}}</th>
|
||||
<th>{{i18n 'ip_lookup.trust_level'}}</th>
|
||||
<th>{{i18n 'ip_lookup.read_time'}}</th>
|
||||
<th>{{i18n 'ip_lookup.topics_entered'}}</th>
|
||||
<th>{{i18n 'ip_lookup.post_count'}}</th>
|
||||
<th>{{i18n "ip_lookup.username"}}</th>
|
||||
<th>{{i18n "ip_lookup.trust_level"}}</th>
|
||||
<th>{{i18n "ip_lookup.read_time"}}</th>
|
||||
<th>{{i18n "ip_lookup.topics_entered"}}</th>
|
||||
<th>{{i18n "ip_lookup.post_count"}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each other_accounts as |a|}}
|
||||
<tr>
|
||||
<td>{{#link-to "adminUser" a}}{{avatar a usernamePath="user.username" imageSize="small"}} {{a.username}}{{/link-to}}</td>
|
||||
<td>
|
||||
{{#link-to "adminUser" a}}
|
||||
{{avatar a usernamePath="user.username" imageSize="small"}}
|
||||
|
||||
<span>{{a.username}}</span>
|
||||
{{/link-to}}
|
||||
</td>
|
||||
<td>{{a.trustLevel.id}}</td>
|
||||
<td>{{a.time_read}}</td>
|
||||
<td>{{a.topics_entered}}</td>
|
||||
|
||||
@ -81,13 +81,13 @@
|
||||
{{d-button action=(action "deleteUser")
|
||||
disabled=post.isSaving
|
||||
label="queue.delete_user"
|
||||
icon="trash"
|
||||
icon="trash-alt"
|
||||
class="btn-danger delete-user"}}
|
||||
{{/if}}
|
||||
{{d-button action=(action "edit")
|
||||
disabled=post.isSaving
|
||||
label="queue.edit"
|
||||
icon="pencil"
|
||||
icon="pencil-alt"
|
||||
class="edit"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
@ -24,5 +24,5 @@
|
||||
{{/if}}
|
||||
|
||||
<div class='link'>
|
||||
<a href {{action "close"}} class="close-share" aria-label={{i18n 'share.close'}} title={{i18n 'share.close'}}>{{d-icon "close"}}</a>
|
||||
<a href {{action "close"}} class="close-share" aria-label={{i18n 'share.close'}} title={{i18n 'share.close'}}>{{d-icon "times"}}</a>
|
||||
</div>
|
||||
|
||||
@ -64,7 +64,7 @@
|
||||
{{d-button class="btn-default edit-message"
|
||||
title="topic.edit_message.help"
|
||||
label="topic.edit_message.title"
|
||||
icon="pencil"
|
||||
icon="pencil-alt"
|
||||
action=editFirstPost}}
|
||||
{{/if}}
|
||||
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
showPosters=showPosters
|
||||
showLikes=showLikes
|
||||
showOpLikes=showOpLikes
|
||||
showParticipants=showParticipants
|
||||
order=order
|
||||
ascending=ascending
|
||||
sortable=sortable
|
||||
@ -35,7 +34,6 @@
|
||||
showTopicPostBadges=showTopicPostBadges
|
||||
hideCategory=hideCategory
|
||||
showPosters=showPosters
|
||||
showParticipants=showParticipants
|
||||
showLikes=showLikes
|
||||
showOpLikes=showOpLikes
|
||||
expandGloballyPinned=expandGloballyPinned
|
||||
|
||||
@ -133,11 +133,11 @@
|
||||
</h3>
|
||||
{{#if showCheckEmail}}
|
||||
<h3 class="email">
|
||||
{{d-icon "envelope-o" title="user.email.title"}}
|
||||
{{d-icon "far-envelope" title="user.email.title"}}
|
||||
{{#if user.email}}
|
||||
{{user.email}}
|
||||
{{else}}
|
||||
{{d-button action=(action "checkEmail") actionParam=user icon="envelope-o" label="admin.users.check_email.text" class="btn-primary"}}
|
||||
{{d-button action=(action "checkEmail") actionParam=user icon="far-envelope" label="admin.users.check_email.text" class="btn-primary"}}
|
||||
{{/if}}
|
||||
</h3>
|
||||
{{/if}}
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
|
||||
{{#if item.deleted_by}}
|
||||
<span class="delete-info">
|
||||
{{d-icon "trash-o"}}
|
||||
{{d-icon "far-trash-alt"}}
|
||||
{{avatar item.deleted_by imageSize="tiny" extraClasses="actor" ignoreTitle="true"}}
|
||||
{{format-date item.deleted_at leaveAgo="true"}}
|
||||
</span>
|
||||
@ -61,7 +61,7 @@
|
||||
|
||||
{{#if item.editableDraft}}
|
||||
<div class='user-stream-item-draft-actions'>
|
||||
{{d-button action=resumeDraft actionParam=item icon="pencil" label='drafts.resume' class="btn-default resume-draft"}}
|
||||
{{d-button action=removeDraft actionParam=item icon="trash-o" label='drafts.remove' class="btn-default remove-draft"}}
|
||||
{{d-button action=resumeDraft actionParam=item icon="pencil-alt" label='drafts.resume' class="btn-default resume-draft"}}
|
||||
{{d-button action=removeDraft actionParam=item icon="far-trash-alt" label='drafts.remove' class="btn-default remove-draft"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
|
||||
{{#unless site.mobileView}}
|
||||
{{#if isWhispering}}
|
||||
<span class='whisper'>{{d-icon 'eye-slash'}}</span>
|
||||
<span class='whisper'>{{d-icon "far-eye-slash"}}</span>
|
||||
{{/if}}
|
||||
{{#if model.unlistTopic}}
|
||||
<span class='whisper'>({{i18n 'composer.unlist'}})</span>
|
||||
@ -128,7 +128,7 @@
|
||||
{{#if canEdit}}
|
||||
{{d-icon "times"}}
|
||||
{{else}}
|
||||
{{d-icon "trash-o"}}
|
||||
{{d-icon "far-trash-alt"}}
|
||||
{{/if}}
|
||||
</a>
|
||||
{{else}}
|
||||
@ -140,7 +140,7 @@
|
||||
{{#if site.mobileView}}
|
||||
{{#if whisperOrUnlistTopic}}
|
||||
<span class='whisper'>
|
||||
{{d-icon "eye-slash"}}
|
||||
{{d-icon "far-eye-slash"}}
|
||||
</span>
|
||||
{{/if}}
|
||||
{{#if model.noBump}}
|
||||
@ -195,7 +195,7 @@
|
||||
|
||||
<div class='draft-text'>
|
||||
{{#if model.topic}}
|
||||
{{d-icon "mail-forward"}} {{{draftTitle}}}
|
||||
{{d-icon "share"}} {{{draftTitle}}}
|
||||
{{else}}
|
||||
{{i18n "composer.saved_draft"}}
|
||||
{{/if}}
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
<a href {{action "closeMessage"}} class='close'>{{d-icon "close"}}</a>
|
||||
<a href {{action "closeMessage"}} class='close'>{{d-icon "times"}}</a>
|
||||
{{#if message.title}}<h3>{{message.title}}</h3>{{/if}}
|
||||
<p>{{{message.body}}}</p>
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
<a href {{action "closeMessage"}} class='close'>{{d-icon "close"}}</a>
|
||||
<a href {{action "closeMessage"}} class='close'>{{d-icon "times"}}</a>
|
||||
{{{message.body}}}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<a href {{action "closeMessage"}} class='close'>{{d-icon "close"}}</a>
|
||||
<a href {{action "closeMessage"}} class='close'>{{d-icon "times"}}</a>
|
||||
<h3>{{i18n 'composer.similar_topics'}}</h3>
|
||||
|
||||
<ul class='topics'>
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
<div class='section' data-section='recent'>
|
||||
<div class='section-header'>
|
||||
<span class="title">{{i18n 'emoji_picker.recent'}}</span>
|
||||
<a href='#' class='clear-recent'>{{d-icon 'trash'}}</a>
|
||||
<a href='#' class='clear-recent'>{{d-icon "trash-alt"}}</a>
|
||||
</div>
|
||||
<div class='section-group'></div>
|
||||
</div>
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
{{#if currentUser.admin}}
|
||||
{{d-button action=(action "destroy")
|
||||
disabled=destroying
|
||||
icon="trash"
|
||||
icon="trash-alt"
|
||||
class='btn-danger'
|
||||
label="admin.groups.delete"}}
|
||||
{{/if}}
|
||||
|
||||
@ -60,7 +60,7 @@
|
||||
{{#if group.public_admission}}
|
||||
{{i18n 'groups.index.public'}}
|
||||
{{else if group.isPrivate}}
|
||||
{{d-icon "eye-slash"}}
|
||||
{{d-icon "far-eye-slash"}}
|
||||
{{i18n 'groups.index.private'}}
|
||||
{{else}}
|
||||
{{#if group.automatic}}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user