Version bump
This commit is contained in:
commit
a4c03a6496
4
Gemfile
4
Gemfile
@ -34,7 +34,7 @@ gem 'redis-namespace'
|
||||
|
||||
gem 'active_model_serializers', '~> 0.8.3'
|
||||
|
||||
gem 'onebox', '1.8.63'
|
||||
gem 'onebox', '1.8.65'
|
||||
|
||||
gem 'http_accept_language', '~>2.0.5', require: false
|
||||
|
||||
@ -187,7 +187,7 @@ if ENV["IMPORT"] == "1"
|
||||
gem 'mysql2'
|
||||
gem 'redcarpet'
|
||||
gem 'sqlite3', '~> 1.3.13'
|
||||
gem 'ruby-bbcode-to-md', github: 'nlalonde/ruby-bbcode-to-md'
|
||||
gem 'ruby-bbcode-to-md', git: 'https://github.com/nlalonde/ruby-bbcode-to-md'
|
||||
gem 'reverse_markdown'
|
||||
gem 'tiny_tds'
|
||||
end
|
||||
|
||||
@ -193,7 +193,7 @@ GEM
|
||||
mini_mime (>= 0.1.1)
|
||||
maxminddb (0.1.21)
|
||||
memory_profiler (0.9.12)
|
||||
message_bus (2.1.5)
|
||||
message_bus (2.1.6)
|
||||
rack (>= 1.1.3)
|
||||
metaclass (0.0.4)
|
||||
method_source (0.8.2)
|
||||
@ -258,7 +258,7 @@ GEM
|
||||
omniauth-twitter (1.4.0)
|
||||
omniauth-oauth (~> 1.1)
|
||||
rack
|
||||
onebox (1.8.63)
|
||||
onebox (1.8.65)
|
||||
htmlentities (~> 4.3)
|
||||
moneta (~> 1.0)
|
||||
multi_json (~> 1.11)
|
||||
@ -512,7 +512,7 @@ DEPENDENCIES
|
||||
omniauth-oauth2
|
||||
omniauth-openid
|
||||
omniauth-twitter
|
||||
onebox (= 1.8.63)
|
||||
onebox (= 1.8.65)
|
||||
openid-redis-store
|
||||
pg
|
||||
pry-nav
|
||||
|
||||
24
app/assets/javascripts/activate-account.js.no-module.es6
Normal file
24
app/assets/javascripts/activate-account.js.no-module.es6
Normal file
@ -0,0 +1,24 @@
|
||||
(function() {
|
||||
setTimeout(function() {
|
||||
const $activateButton = $("#activate-account-button");
|
||||
$activateButton.on("click", function() {
|
||||
$activateButton.prop("disabled", true);
|
||||
const hpPath = document.getElementById("data-activate-account").dataset
|
||||
.path;
|
||||
$.ajax(hpPath)
|
||||
.then(function(hp) {
|
||||
$("#password_confirmation").val(hp.value);
|
||||
$("#challenge").val(
|
||||
hp.challenge
|
||||
.split("")
|
||||
.reverse()
|
||||
.join("")
|
||||
);
|
||||
$("#activate-account-form").submit();
|
||||
})
|
||||
.fail(function() {
|
||||
$activateButton.prop("disabled", false);
|
||||
});
|
||||
});
|
||||
}, 50);
|
||||
})();
|
||||
@ -89,7 +89,12 @@ export default Ember.Component.extend({
|
||||
yAxes: [
|
||||
{
|
||||
display: true,
|
||||
ticks: { callback: label => number(label) }
|
||||
ticks: {
|
||||
userCallback: label => {
|
||||
if (Math.floor(label) === label) return label;
|
||||
},
|
||||
callback: label => number(label)
|
||||
}
|
||||
}
|
||||
],
|
||||
xAxes: [
|
||||
|
||||
@ -140,7 +140,7 @@ export default Ember.Component.extend({
|
||||
const modes = forcedModes ? forcedModes.split(",") : reportModes;
|
||||
|
||||
return Ember.makeArray(modes).map(mode => {
|
||||
const base = `mode-btn ${mode}`;
|
||||
const base = `btn-default mode-btn ${mode}`;
|
||||
const cssClass = currentMode === mode ? `${base} is-current` : base;
|
||||
|
||||
return {
|
||||
|
||||
@ -5,16 +5,6 @@ import copyText from "discourse/lib/copy-text";
|
||||
export default Ember.Component.extend({
|
||||
classNames: ["ip-lookup"],
|
||||
|
||||
city: function() {
|
||||
return [
|
||||
this.get("location.city"),
|
||||
this.get("location.region"),
|
||||
this.get("location.country")
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(", ");
|
||||
}.property("location.{city,region,country}"),
|
||||
|
||||
otherAccountsToDelete: function() {
|
||||
// can only delete up to 50 accounts at a time
|
||||
var total = Math.min(50, this.get("totalOthersWithSameIP") || 0);
|
||||
@ -72,24 +62,19 @@ export default Ember.Component.extend({
|
||||
}
|
||||
|
||||
text += I18n.t("ip_lookup.location");
|
||||
if (location.loc) {
|
||||
text += `: ${location.loc} ${this.get("city")}\n`;
|
||||
if (location.location) {
|
||||
text += `: ${location.location}\n`;
|
||||
} else {
|
||||
text += `: ${I18n.t("ip_lookup.location_not_found")}\n`;
|
||||
}
|
||||
|
||||
if (location.org) {
|
||||
if (location.organization) {
|
||||
text += I18n.t("ip_lookup.organisation");
|
||||
text += `: ${location.org}\n`;
|
||||
}
|
||||
|
||||
if (location.phone) {
|
||||
text += I18n.t("ip_lookup.phone");
|
||||
text += `: ${location.phone}\n`;
|
||||
text += `: ${location.organization}\n`;
|
||||
}
|
||||
}
|
||||
const copyRange = $('<p id="copy-range"></p>');
|
||||
copyRange.html(text.trim().replace("\n", "<br>"));
|
||||
copyRange.html(text.trim().replace(/\n/g, "<br>"));
|
||||
$(document.body).append(copyRange);
|
||||
if (copyText(text, copyRange[0])) {
|
||||
this.set("copied", true);
|
||||
|
||||
102
app/assets/javascripts/admin/components/secret-value-list.js.es6
Normal file
102
app/assets/javascripts/admin/components/secret-value-list.js.es6
Normal file
@ -0,0 +1,102 @@
|
||||
import { on } from "ember-addons/ember-computed-decorators";
|
||||
|
||||
export default Ember.Component.extend({
|
||||
classNameBindings: [":value-list", ":secret-value-list"],
|
||||
inputDelimiter: null,
|
||||
collection: null,
|
||||
values: null,
|
||||
validationMessage: null,
|
||||
|
||||
@on("didReceiveAttrs")
|
||||
_setupCollection() {
|
||||
const values = this.get("values");
|
||||
|
||||
this.set(
|
||||
"collection",
|
||||
this._splitValues(values, this.get("inputDelimiter") || "\n")
|
||||
);
|
||||
},
|
||||
|
||||
actions: {
|
||||
changeKey(index, newValue) {
|
||||
if (this._checkInvalidInput(newValue)) return;
|
||||
this._replaceValue(index, newValue, "key");
|
||||
},
|
||||
|
||||
changeSecret(index, newValue) {
|
||||
if (this._checkInvalidInput(newValue)) return;
|
||||
this._replaceValue(index, newValue, "secret");
|
||||
},
|
||||
|
||||
addValue() {
|
||||
if (this._checkInvalidInput([this.get("newKey"), this.get("newSecret")]))
|
||||
return;
|
||||
this._addValue(this.get("newKey"), this.get("newSecret"));
|
||||
this.setProperties({ newKey: "", newSecret: "" });
|
||||
},
|
||||
|
||||
removeValue(value) {
|
||||
this._removeValue(value);
|
||||
}
|
||||
},
|
||||
|
||||
_checkInvalidInput(inputs) {
|
||||
this.set("validationMessage", null);
|
||||
for (let input of inputs) {
|
||||
if (Ember.isEmpty(input) || input.includes("|")) {
|
||||
this.set(
|
||||
"validationMessage",
|
||||
I18n.t("admin.site_settings.secret_list.invalid_input")
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_addValue(value, secret) {
|
||||
this.get("collection").addObject({ key: value, secret: secret });
|
||||
this._saveValues();
|
||||
},
|
||||
|
||||
_removeValue(value) {
|
||||
const collection = this.get("collection");
|
||||
collection.removeObject(value);
|
||||
this._saveValues();
|
||||
},
|
||||
|
||||
_replaceValue(index, newValue, keyName) {
|
||||
let item = this.get("collection")[index];
|
||||
Ember.set(item, keyName, newValue);
|
||||
|
||||
this._saveValues();
|
||||
},
|
||||
|
||||
_saveValues() {
|
||||
this.set(
|
||||
"values",
|
||||
this.get("collection")
|
||||
.map(function(elem) {
|
||||
return `${elem.key}|${elem.secret}`;
|
||||
})
|
||||
.join("\n")
|
||||
);
|
||||
},
|
||||
|
||||
_splitValues(values, delimiter) {
|
||||
if (values && values.length) {
|
||||
const keys = ["key", "secret"];
|
||||
var res = [];
|
||||
values.split(delimiter).forEach(function(str) {
|
||||
var object = {};
|
||||
str.split("|").forEach(function(a, i) {
|
||||
object[keys[i]] = a;
|
||||
});
|
||||
res.push(object);
|
||||
});
|
||||
|
||||
return res;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
});
|
||||
19
app/assets/javascripts/admin/components/tags-uploader.js.es6
Normal file
19
app/assets/javascripts/admin/components/tags-uploader.js.es6
Normal file
@ -0,0 +1,19 @@
|
||||
import UploadMixin from "discourse/mixins/upload";
|
||||
|
||||
export default Em.Component.extend(UploadMixin, {
|
||||
type: "csv",
|
||||
uploadUrl: "/tags/upload",
|
||||
addDisabled: Em.computed.alias("uploading"),
|
||||
elementId: "tag-uploader",
|
||||
|
||||
validateUploadedFilesOptions() {
|
||||
return { csvOnly: true };
|
||||
},
|
||||
|
||||
uploadDone() {
|
||||
bootbox.alert(I18n.t("tagging.upload_successful"), () => {
|
||||
this.sendAction("refresh");
|
||||
this.sendAction("closeModal");
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,53 @@
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
|
||||
export default Ember.Component.extend({
|
||||
tagName: "",
|
||||
|
||||
@computed("percentage")
|
||||
showPercentage(percentage) {
|
||||
return percentage.total >= 3;
|
||||
},
|
||||
|
||||
// We do a little logic to choose which icon to display and which text
|
||||
@computed("user.flags_agreed", "user.flags_disagreed", "user.flags_ignored")
|
||||
percentage(agreed, disagreed, ignored) {
|
||||
let total = agreed + disagreed + ignored;
|
||||
let result = { total };
|
||||
|
||||
if (total > 0) {
|
||||
result.agreed = Math.round((agreed / total) * 100);
|
||||
result.disagreed = Math.round((disagreed / total) * 100);
|
||||
result.ignored = Math.round((ignored / total) * 100);
|
||||
}
|
||||
|
||||
let highest = Math.max(agreed, disagreed, ignored);
|
||||
if (highest === agreed) {
|
||||
result.icon = "thumbs-up";
|
||||
result.className = "agreed";
|
||||
result.label = `${result.agreed}%`;
|
||||
} else if (highest === disagreed) {
|
||||
result.icon = "thumbs-down";
|
||||
result.className = "disagreed";
|
||||
result.label = `${result.disagreed}%`;
|
||||
} else {
|
||||
result.icon = "external-link";
|
||||
result.className = "ignored";
|
||||
result.label = `${result.ignored}%`;
|
||||
}
|
||||
|
||||
result.title = I18n.t("admin.flags.user_percentage.summary", {
|
||||
agreed: I18n.t("admin.flags.user_percentage.agreed", {
|
||||
count: result.agreed
|
||||
}),
|
||||
disagreed: I18n.t("admin.flags.user_percentage.disagreed", {
|
||||
count: result.disagreed
|
||||
}),
|
||||
ignored: I18n.t("admin.flags.user_percentage.ignored", {
|
||||
count: result.ignored
|
||||
}),
|
||||
count: total
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
});
|
||||
@ -1,9 +1,15 @@
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
adminBackups: Ember.inject.controller(),
|
||||
status: Ember.computed.alias("adminBackups.model"),
|
||||
|
||||
@computed
|
||||
localBackupStorage() {
|
||||
return this.siteSettings.backup_location === "local";
|
||||
},
|
||||
|
||||
uploadLabel: function() {
|
||||
return I18n.t("admin.backups.upload.label");
|
||||
}.property(),
|
||||
|
||||
@ -12,6 +12,16 @@ export default Ember.Controller.extend(PeriodComputationMixin, {
|
||||
};
|
||||
},
|
||||
|
||||
@computed
|
||||
mostDisagreedFlaggersOptions() {
|
||||
return {
|
||||
table: {
|
||||
total: false,
|
||||
perPage: 10
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
@computed("startDate", "endDate")
|
||||
filters(startDate, endDate) {
|
||||
return { startDate, endDate };
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import { observes } from "ember-addons/ember-computed-decorators";
|
||||
import {
|
||||
default as computed,
|
||||
observes
|
||||
} from "ember-addons/ember-computed-decorators";
|
||||
|
||||
export default Ember.Controller.extend(ModalFunctionality, {
|
||||
local: Ember.computed.equal("selection", "local"),
|
||||
@ -11,8 +14,14 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
loading: false,
|
||||
keyGenUrl: "/admin/themes/generate_key_pair",
|
||||
importUrl: "/admin/themes/import",
|
||||
|
||||
checkPrivate: Ember.computed.match("uploadUrl", /^git/),
|
||||
localFile: null,
|
||||
uploadUrl: null,
|
||||
|
||||
@computed("loading", "remote", "uploadUrl", "local", "localFile")
|
||||
importDisabled(isLoading, isRemote, uploadUrl, isLocal, localFile) {
|
||||
return isLoading || (isRemote && !uploadUrl) || (isLocal && !localFile);
|
||||
},
|
||||
|
||||
@observes("privateChecked")
|
||||
privateWasChecked() {
|
||||
@ -32,6 +41,10 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
},
|
||||
|
||||
actions: {
|
||||
uploadLocaleFile() {
|
||||
this.set("localFile", $("#file-input")[0].files[0]);
|
||||
},
|
||||
|
||||
importTheme() {
|
||||
let options = {
|
||||
type: "POST"
|
||||
@ -41,7 +54,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
options.processData = false;
|
||||
options.contentType = false;
|
||||
options.data = new FormData();
|
||||
options.data.append("theme", $("#file-input")[0].files[0]);
|
||||
options.data.append("theme", this.get("localFile"));
|
||||
} else {
|
||||
options.data = {
|
||||
remote: this.get("uploadUrl"),
|
||||
|
||||
@ -11,7 +11,8 @@ const CUSTOM_TYPES = [
|
||||
"value_list",
|
||||
"category",
|
||||
"uploaded_image_list",
|
||||
"compact_list"
|
||||
"compact_list",
|
||||
"secret_list"
|
||||
];
|
||||
|
||||
export default Ember.Mixin.create({
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import PreloadStore from "preload-store";
|
||||
|
||||
const Backup = Discourse.Model.extend({
|
||||
destroy() {
|
||||
@ -16,9 +15,9 @@ const Backup = Discourse.Model.extend({
|
||||
|
||||
Backup.reopenClass({
|
||||
find() {
|
||||
return PreloadStore.getAndRemove("backups", () =>
|
||||
ajax("/admin/backups.json")
|
||||
).then(backups => backups.map(backup => Backup.create(backup)));
|
||||
return ajax("/admin/backups.json").then(backups =>
|
||||
backups.map(backup => Backup.create(backup))
|
||||
);
|
||||
},
|
||||
|
||||
start(withUploads) {
|
||||
|
||||
@ -304,7 +304,7 @@ const Report = Discourse.Model.extend({
|
||||
avatar_template: row[properties.avatar]
|
||||
});
|
||||
|
||||
const href = `/admin/users/${userId}/${username}`;
|
||||
const href = Discourse.getURL(`/admin/users/${userId}/${username}`);
|
||||
|
||||
const avatarImg = renderAvatar(user, {
|
||||
imageSize: "tiny",
|
||||
@ -327,7 +327,7 @@ const Report = Discourse.Model.extend({
|
||||
|
||||
const formatedValue = () => {
|
||||
const topicId = row[properties.id];
|
||||
const href = `/t/-/${topicId}`;
|
||||
const href = Discourse.getURL(`/t/-/${topicId}`);
|
||||
return `<a href='${href}'>${topicTitle}</a>`;
|
||||
};
|
||||
|
||||
@ -341,7 +341,7 @@ const Report = Discourse.Model.extend({
|
||||
const postTitle = row[properties.truncated_raw];
|
||||
const postNumber = row[properties.number];
|
||||
const topicId = row[properties.topic_id];
|
||||
const href = `/t/-/${topicId}/${postNumber}`;
|
||||
const href = Discourse.getURL(`/t/-/${topicId}/${postNumber}`);
|
||||
|
||||
return {
|
||||
property: properties.title,
|
||||
@ -395,7 +395,7 @@ const Report = Discourse.Model.extend({
|
||||
|
||||
_linkLabel(properties, row) {
|
||||
const property = properties[0];
|
||||
const value = row[property];
|
||||
const value = Discourse.getURL(row[property]);
|
||||
const formatedValue = (href, anchor) => {
|
||||
return `<a href="${escapeExpression(href)}">${escapeExpression(
|
||||
anchor
|
||||
|
||||
@ -151,6 +151,15 @@ export default Discourse.Route.extend({
|
||||
message: message
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
remoteUploadSuccess() {
|
||||
Backup.find().then(backups => {
|
||||
this.controllerFor("adminBackupsIndex").set(
|
||||
"model",
|
||||
backups.map(backup => Backup.create(backup))
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -19,8 +19,8 @@
|
||||
{{/if}}
|
||||
</td>
|
||||
<td class="key-controls">
|
||||
{{d-button action="regenerateKey" actionParam=k icon="undo" label='admin.api.regenerate'}}
|
||||
{{d-button action="revokeKey" actionParam=k icon="times" label='admin.api.revoke'}}
|
||||
{{d-button class="btn-default" action="regenerateKey" actionParam=k icon="undo" label='admin.api.regenerate'}}
|
||||
{{d-button class="btn-default" action="revokeKey" actionParam=k icon="times" label='admin.api.revoke'}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
|
||||
@ -1,16 +1,21 @@
|
||||
<div class="backup-options">
|
||||
{{resumable-upload target="/admin/backups/upload" success="uploadSuccess" error="uploadError" uploadText=uploadLabel title="admin.backups.upload.title"}}
|
||||
{{#if site.isReadOnly}}
|
||||
{{d-button icon="eye" action="toggleReadOnlyMode" disabled=status.isOperationRunning title="admin.backups.read_only.disable.title" label="admin.backups.read_only.disable.label"}}
|
||||
{{#if localBackupStorage}}
|
||||
{{resumable-upload target="/admin/backups/upload" success="uploadSuccess" error="uploadError" uploadText=uploadLabel title="admin.backups.upload.title" class="btn-default"}}
|
||||
{{else}}
|
||||
{{d-button icon="eye" action="toggleReadOnlyMode" disabled=status.isOperationRunning title="admin.backups.read_only.enable.title" label="admin.backups.read_only.enable.label"}}
|
||||
{{backup-uploader done="remoteUploadSuccess"}}
|
||||
{{/if}}
|
||||
|
||||
{{#if site.isReadOnly}}
|
||||
{{d-button class="btn-default" icon="eye" 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="eye" 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></th>
|
||||
<th></th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each model as |backup|}}
|
||||
@ -19,7 +24,7 @@
|
||||
<td class="backup-size">{{human-size backup.size}}</td>
|
||||
<td class="backup-controls">
|
||||
<div>
|
||||
{{d-button class="download"
|
||||
{{d-button class="btn-default download"
|
||||
action="download"
|
||||
actionParam=backup
|
||||
icon="download"
|
||||
@ -27,10 +32,10 @@
|
||||
label="admin.backups.operations.download.label"}}
|
||||
{{#if status.isOperationRunning}}
|
||||
{{d-button icon="trash-o" action="destroyBackup" actionParam=backup class="btn-danger" disabled="true" title="admin.backups.operations.is_running"}}
|
||||
{{d-button icon="play" action="startRestore" actionParam=backup disabled=status.restoreDisabled title=restoreTitle label="admin.backups.operations.restore.label"}}
|
||||
{{d-button icon="play" action="startRestore" actionParam=backup disabled=status.restoreDisabled class="btn-default" title=restoreTitle label="admin.backups.operations.restore.label"}}
|
||||
{{else}}
|
||||
{{d-button icon="trash-o" action="destroyBackup" actionParam=backup class="btn-danger" title="admin.backups.operations.destroy.title"}}
|
||||
{{d-button icon="play" action="startRestore" actionParam=backup disabled=status.restoreDisabled title=restoreTitle label="admin.backups.operations.restore.label"}}
|
||||
{{d-button icon="play" action="startRestore" actionParam=backup disabled=status.restoreDisabled class="btn-default" title=restoreTitle label="admin.backups.operations.restore.label"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</td>
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
<div class="admin-actions">
|
||||
{{#if model.canRollback}}
|
||||
{{d-button action="rollback"
|
||||
class="btn-rollback"
|
||||
class="btn-default btn-rollback"
|
||||
label="admin.backups.operations.rollback.label"
|
||||
title="admin.backups.operations.rollback.title"
|
||||
icon="ambulance"
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<p>{{i18n 'admin.badges.none_selected'}}</p>
|
||||
|
||||
<div>
|
||||
{{#link-to 'adminBadges.show' 'new' class="btn"}}
|
||||
{{#link-to 'adminBadges.show' 'new' class="btn btn-default"}}
|
||||
{{d-icon "plus"}} {{i18n 'admin.badges.new'}}
|
||||
{{/link-to}}
|
||||
</div>
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
value=buffered.badge_grouping_id
|
||||
content=badgeGroupings
|
||||
nameProperty="name"}}
|
||||
<button {{action "editGroupings"}} class='btn'>{{d-icon 'pencil'}}</button>
|
||||
<button {{action "editGroupings"}} class='btn btn-icon btn-default'>{{d-icon 'pencil'}}</button>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{#link-to 'adminBadges.show' 'new' class="btn"}}
|
||||
{{#link-to 'adminBadges.show' 'new' class="btn btn-default"}}
|
||||
{{d-icon "plus"}} {{i18n 'admin.badges.new'}}
|
||||
{{/link-to}}
|
||||
<br>
|
||||
|
||||
@ -167,7 +167,7 @@
|
||||
<div class="control">
|
||||
<div class="input">
|
||||
{{d-button
|
||||
class="export-csv-btn"
|
||||
class="btn-default export-csv-btn"
|
||||
action="exportCsv"
|
||||
label="admin.export_csv.button_text"
|
||||
icon="download"}}
|
||||
|
||||
@ -48,8 +48,8 @@
|
||||
<div class='form-element controls'>
|
||||
{{d-button action="edit" class="btn-default" icon="pencil" label="admin.user_fields.edit"}}
|
||||
{{d-button action="destroy" class="btn-danger" icon="trash-o" label="admin.user_fields.delete"}}
|
||||
{{d-button action="moveUp" icon="arrow-up" disabled=cantMoveUp}}
|
||||
{{d-button action="moveDown" icon="arrow-down" disabled=cantMoveDown}}
|
||||
{{d-button action="moveUp" class="btn-default" icon="arrow-up" disabled=cantMoveUp}}
|
||||
{{d-button action="moveDown" class="btn-default" icon="arrow-down" disabled=cantMoveDown}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">{{flags}}</div>
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
<div class='flagger-flag-type'>
|
||||
{{post-action-title postAction.post_action_type_id postAction.name_key}}
|
||||
</div>
|
||||
{{user-flag-percentage user=postAction.user}}
|
||||
{{/flag-user}}
|
||||
{{/each}}
|
||||
</div>
|
||||
|
||||
@ -77,21 +77,21 @@
|
||||
{{#if flaggedPost.postHidden}}
|
||||
{{d-button
|
||||
title="admin.flags.disagree_flag_unhide_post_title"
|
||||
class="disagree-flag"
|
||||
class="btn-default disagree-flag"
|
||||
action="disagree"
|
||||
icon="thumbs-o-down"
|
||||
label="admin.flags.disagree_flag_unhide_post"}}
|
||||
{{else}}
|
||||
{{d-button
|
||||
title="admin.flags.disagree_flag_title"
|
||||
class="disagree-flag"
|
||||
class="btn-default disagree-flag"
|
||||
action="disagree"
|
||||
icon="thumbs-o-down"
|
||||
label="admin.flags.disagree_flag"}}
|
||||
{{/if}}
|
||||
|
||||
{{d-button
|
||||
class="defer-flag"
|
||||
class="btn-default defer-flag"
|
||||
title="admin.flags.ignore_flag_title"
|
||||
action="defer"
|
||||
icon="external-link"
|
||||
@ -103,6 +103,7 @@
|
||||
{{/if}}
|
||||
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
icon="list"
|
||||
label="admin.flags.moderation_history"
|
||||
action=(action "showModerationHistory")}}
|
||||
|
||||
@ -2,4 +2,4 @@
|
||||
{{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 action="submit" disabled=formSubmitted label="admin.permalink.form.add"}}
|
||||
{{d-button class="btn-default" action="submit" disabled=formSubmitted label="admin.permalink.form.add"}}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<b>{{i18n 'admin.logs.screened_ips.form.label'}}</b>
|
||||
{{text-field value=ip_address disabled=formSubmitted class="ip-address-input" placeholderKey="admin.logs.screened_ips.form.ip_address" autocorrect="off" autocapitalize="off"}}
|
||||
{{combo-box content=actionNames value=actionName}}
|
||||
{{d-button action="submit" disabled=formSubmitted label="admin.logs.screened_ips.form.add"}}
|
||||
{{d-button class="btn-default" action="submit" disabled=formSubmitted label="admin.logs.screened_ips.form.add"}}
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
{{#if collection}}
|
||||
<div class="values">
|
||||
{{#each collection as |value index|}}
|
||||
<div class="value" data-index={{index}}>
|
||||
{{d-button action="removeValue"
|
||||
actionParam=value
|
||||
icon="times"
|
||||
class="remove-value-btn btn-small"}}
|
||||
{{input value=value.key class="value-input" focus-out=(action "changeKey" index)}}
|
||||
{{input value=value.secret class="value-input" focus-out=(action "changeSecret" index) type=(if isSecret "password" "text")}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="value">
|
||||
{{text-field value=newKey class="new-value-input key" placeholder=setting.placeholder.key}}
|
||||
{{input type="password" value=newSecret class="new-value-input secret" placeholder=setting.placeholder.value}}
|
||||
{{d-button action="addValue"
|
||||
icon="plus"
|
||||
class="add-value-btn btn-small"}}
|
||||
</div>
|
||||
|
||||
{{setting-validation-message message=validationMessage}}
|
||||
@ -13,5 +13,5 @@
|
||||
{{#if setting.secret}}
|
||||
{{d-button action="toggleSecret" icon="eye-slash"}}
|
||||
{{/if}}
|
||||
{{d-button class="undo" action="resetDefault" icon="undo" label="admin.settings.reset"}}
|
||||
{{d-button class="btn-default undo" action="resetDefault" icon="undo" label="admin.settings.reset"}}
|
||||
{{/if}}
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
{{secret-value-list setting=setting values=value isSecret=isSecret}}
|
||||
{{setting-validation-message message=validationMessage}}
|
||||
<div class='desc'>{{{unbound setting.description}}}</div>
|
||||
@ -1,4 +1,4 @@
|
||||
{{d-button label="admin.site_text.edit" class='edit' action="edit"}}
|
||||
{{d-button label="admin.site_text.edit" class='btn-default edit' action="edit"}}
|
||||
<h3 class='site-text-id'>{{siteText.id}}</h3>
|
||||
<div class='site-text-value'>{{siteText.value}}</div>
|
||||
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
<label class="btn {{if addDisabled 'disabled'}}">
|
||||
{{d-icon "upload"}}
|
||||
{{i18n 'admin.watched_words.form.upload'}}
|
||||
<input class="hidden-upload-field" disabled={{addDisabled}} type="file" accept="text/plain,text/csv" />
|
||||
</label>
|
||||
<span class="instructions">{{i18n 'tagging.upload_instructions'}}</span>
|
||||
@ -0,0 +1,6 @@
|
||||
{{#if showPercentage}}
|
||||
<div class='user-flag-percentage' title={{percentage.title}}>
|
||||
<span class="percentage-label {{percentage.className}}">{{percentage.label}}</span>
|
||||
{{d-icon percentage.icon}}
|
||||
</div>
|
||||
{{/if}}
|
||||
@ -5,7 +5,7 @@
|
||||
{{d-button action="removeValue"
|
||||
actionParam=value
|
||||
icon="times"
|
||||
class="remove-value-btn btn-small"}}
|
||||
class="btn-default remove-value-btn btn-small"}}
|
||||
|
||||
{{input title=value value=value class="value-input" focus-out=(action "changeValue" index)}}
|
||||
</div>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<b>{{i18n 'admin.watched_words.form.label'}}</b>
|
||||
{{text-field value=word disabled=formSubmitted class="watched-word-input" autocorrect="off" autocapitalize="off" placeholderKey=placeholderKey}}
|
||||
{{d-button action="submit" disabled=formSubmitted label="admin.watched_words.form.add"}}
|
||||
{{d-button class="btn-default" action="submit" disabled=formSubmitted label="admin.watched_words.form.add"}}
|
||||
|
||||
{{#if showMessage}}
|
||||
<span class="success-message">{{message}}</span>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<label class="btn {{if addDisabled 'disabled'}}">
|
||||
<label class="btn btn-default {{if addDisabled 'disabled'}}">
|
||||
{{d-icon "upload"}}
|
||||
{{i18n 'admin.watched_words.form.upload'}}
|
||||
<input disabled={{addDisabled}} type="file" accept="text/plain,text/csv" style="visibility: hidden; position: absolute;" />
|
||||
<input class="hidden-upload-field" disabled={{addDisabled}} type="file" accept="text/plain,text/csv" />
|
||||
</label>
|
||||
<br/>
|
||||
<span class="instructions">One word per line</span>
|
||||
|
||||
@ -3,10 +3,10 @@
|
||||
<h1>{{#if model.theme_id}}{{model.name}}{{else}}{{text-field class="style-name" value=model.name}}{{/if}}</h1>
|
||||
<div class="controls">
|
||||
{{#unless model.theme_id}}
|
||||
<button {{action "save"}} disabled={{model.disableSave}} class='btn'>{{i18n 'admin.customize.save'}}</button>
|
||||
<button {{action "save"}} disabled={{model.disableSave}} class='btn btn-primary'>{{i18n 'admin.customize.save'}}</button>
|
||||
{{/unless}}
|
||||
<button {{action "copy" model}} class='btn'>{{d-icon "copy"}} {{i18n 'admin.customize.copy'}}</button>
|
||||
<button {{action "copyToClipboard" model}} class='btn'>{{d-icon "clipboard"}} {{i18n 'admin.customize.copy_to_clipboard'}}</button>
|
||||
<button {{action "copy" model}} class='btn btn-default'>{{d-icon "copy"}} {{i18n 'admin.customize.copy'}}</button>
|
||||
<button {{action "copyToClipboard" model}} class='btn btn-default'>{{d-icon "clipboard"}} {{i18n 'admin.customize.copy_to_clipboard'}}</button>
|
||||
{{#if model.theme_id}}
|
||||
{{i18n "admin.customize.theme_owner"}}
|
||||
{{#link-to "adminCustomizeThemes.show" model.theme_id}}{{model.theme_name}}{{/link-to}}
|
||||
@ -47,8 +47,8 @@
|
||||
<td class="hex">{{color-input hexValue=c.hex brightnessValue=c.brightness valid=c.valid}}</td>
|
||||
<td class="actions">
|
||||
{{#unless model.theme_id}}
|
||||
<button class="btn revert {{unless c.savedIsOverriden 'invisible'}}" {{action "revert" c}} title="{{i18n 'admin.customize.colors.revert_title'}}">{{i18n 'revert'}}</button>
|
||||
<button class="btn undo {{unless c.changed 'invisible'}}" {{action "undo" c}} title="{{i18n 'admin.customize.colors.undo_title'}}">{{i18n 'undo'}}</button>
|
||||
<button class="btn btn-default revert {{unless c.savedIsOverriden 'invisible'}}" {{action "revert" c}} title="{{i18n 'admin.customize.colors.revert_title'}}">{{i18n 'revert'}}</button>
|
||||
<button class="btn btn-default undo {{unless c.changed 'invisible'}}" {{action "undo" c}} title="{{i18n 'admin.customize.colors.undo_title'}}">{{i18n 'undo'}}</button>
|
||||
{{/unless}}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
{{/unless}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
<button {{action "newColorScheme"}} class='btn'>{{d-icon 'plus'}}{{i18n 'admin.customize.new'}}</button>
|
||||
<button {{action "newColorScheme"}} class='btn btn-default'>{{d-icon 'plus'}}{{i18n 'admin.customize.new'}}</button>
|
||||
</div>
|
||||
|
||||
{{outlet}}
|
||||
|
||||
@ -50,10 +50,10 @@
|
||||
icon="paint-brush"}}
|
||||
{{#if colorSchemeChanged}}
|
||||
{{d-button action="changeScheme" class="btn-primary btn-small submit-edit" icon="check"}}
|
||||
{{d-button action="cancelChangeScheme" class="btn-small cancel-edit" icon="times"}}
|
||||
{{d-button action="cancelChangeScheme" class="btn-default btn-small cancel-edit" icon="times"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{#link-to 'adminCustomize.colors' class="btn edit"}}{{i18n 'admin.customize.colors.edit'}}{{/link-to}}
|
||||
{{#link-to 'adminCustomize.colors' class="btn btn-default edit"}}{{i18n 'admin.customize.colors.edit'}}{{/link-to}}
|
||||
</div>
|
||||
{{/unless}}
|
||||
|
||||
@ -76,11 +76,11 @@
|
||||
{{#if model.remote_theme.commits_behind}}
|
||||
{{#d-button action="updateToLatest" icon="download" class='btn-primary'}}{{i18n "admin.customize.theme.update_to_latest"}}{{/d-button}}
|
||||
{{else}}
|
||||
{{#d-button action="checkForThemeUpdates" icon="refresh"}}{{i18n "admin.customize.theme.check_for_updates"}}{{/d-button}}
|
||||
{{#d-button action="checkForThemeUpdates" icon="refresh" class="btn-default"}}{{i18n "admin.customize.theme.check_for_updates"}}{{/d-button}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
{{#d-button action="editTheme" class="btn edit"}}{{i18n 'admin.customize.theme.edit_css_html'}}{{/d-button}}
|
||||
{{#d-button 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}}
|
||||
@ -119,7 +119,7 @@
|
||||
<li>
|
||||
<span class='col'>${{upload.name}}: <a href={{upload.url}} target='_blank'>{{upload.filename}}</a></span>
|
||||
<span class='col'>
|
||||
{{d-button action="removeUpload" actionParam=upload class="second btn-small cancel-edit" icon="times"}}
|
||||
{{d-button action="removeUpload" actionParam=upload class="second btn-default btn-small cancel-edit" icon="times"}}
|
||||
</span>
|
||||
</li>
|
||||
{{/each}}
|
||||
@ -127,7 +127,7 @@
|
||||
{{else}}
|
||||
<div class="description">{{i18n "admin.customize.theme.no_uploads"}}</div>
|
||||
{{/if}}
|
||||
{{#d-button action="addUploadModal" icon="plus"}}{{i18n "admin.customize.theme.add"}}{{/d-button}}
|
||||
{{#d-button action="addUploadModal" class="btn-default" icon="plus"}}{{i18n "admin.customize.theme.add"}}{{/d-button}}
|
||||
</div>
|
||||
|
||||
{{#if hasSettings}}
|
||||
@ -147,22 +147,22 @@
|
||||
{{#if model.childThemes.length}}
|
||||
<ul class='removable-list'>
|
||||
{{#each model.childThemes as |child|}}
|
||||
<li>{{#link-to 'adminCustomizeThemes.show' child replace=true class='col'}}{{child.name}}{{/link-to}} {{d-button action="removeChildTheme" actionParam=child class="btn-small cancel-edit col" icon="times"}}</li>
|
||||
<li>{{#link-to 'adminCustomizeThemes.show' child replace=true class='col'}}{{child.name}}{{/link-to}} {{d-button action="removeChildTheme" actionParam=child class="btn-default btn-small cancel-edit col" icon="times"}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{/if}}
|
||||
{{#if selectableChildThemes}}
|
||||
<div class="description">
|
||||
{{combo-box forceEscape=true filterable=true content=selectableChildThemes value=selectedChildThemeId none="admin.customize.theme.select_component"}}
|
||||
{{#d-button action="addChildTheme" icon="plus" disabled=addButtonDisabled class="add-component-button"}}{{i18n "admin.customize.theme.add"}}{{/d-button}}
|
||||
{{#d-button action="addChildTheme" icon="plus" disabled=addButtonDisabled class="btn-default add-component-button"}}{{i18n "admin.customize.theme.add"}}{{/d-button}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<a href='{{previewUrl}}' title="{{i18n 'admin.customize.explain_preview'}}" target='_blank' class='btn'>{{d-icon 'desktop'}}{{i18n 'admin.customize.theme.preview'}}</a>
|
||||
<a class="btn export" target="_blank" href={{downloadUrl}}>{{d-icon "download"}} {{i18n 'admin.export_json.button_text'}}</a>
|
||||
<a href='{{previewUrl}}' title="{{i18n 'admin.customize.explain_preview'}}" target='_blank' class='btn btn-default'>{{d-icon 'desktop'}}{{i18n 'admin.customize.theme.preview'}}</a>
|
||||
<a class="btn btn-default export" target="_blank" href={{downloadUrl}}>{{d-icon "download"}} {{i18n 'admin.export_json.button_text'}}</a>
|
||||
|
||||
{{d-button action="switchType" label="admin.customize.theme.convert" icon=convertIcon class="btn-normal" title=convertTooltip}}
|
||||
{{d-button action="switchType" label="admin.customize.theme.convert" icon=convertIcon class="btn-default btn-normal" title=convertTooltip}}
|
||||
{{d-button action="destroy" label="admin.customize.delete" icon="trash" class="btn-danger"}}
|
||||
</div>
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
<div class="create-actions">
|
||||
{{d-button label="admin.customize.new" icon="plus" action="showCreateModal" class="btn-primary"}}
|
||||
{{d-button action="importModal" icon="upload" label="admin.customize.import"}}
|
||||
{{d-button action="importModal" icon="upload" label="admin.customize.import" class="btn-default"}}
|
||||
</div>
|
||||
</div>
|
||||
{{themes-list themes=fullThemes components=childThemes currentTab=currentTab}}
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
|
||||
<p class="actions">
|
||||
<small>{{i18n 'admin.dashboard.last_checked'}}: {{problemsTimestamp}}</small>
|
||||
{{d-button action="refreshProblems" class="btn-small" icon="refresh" label="admin.dashboard.refresh_problems"}}
|
||||
{{d-button action="refreshProblems" class="btn-default btn-small" icon="refresh" label="admin.dashboard.refresh_problems"}}
|
||||
</p>
|
||||
{{/conditional-loading-section}}
|
||||
</div>
|
||||
|
||||
@ -137,7 +137,7 @@
|
||||
<div>
|
||||
<h4>{{i18n "admin.dashboard.last_updated"}} </h4>
|
||||
<p>{{updatedTimestamp}}</p>
|
||||
<a rel="noopener" target="_blank" href="https://meta.discourse.org/tags/release-notes" class="btn">
|
||||
<a rel="noopener" target="_blank" href="https://meta.discourse.org/tags/release-notes" class="btn btn-default">
|
||||
{{i18n "admin.dashboard.whats_new_in_discourse"}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@ -33,6 +33,11 @@
|
||||
dataSourceName="post_edits"
|
||||
filters=lastWeekfilters}}
|
||||
|
||||
{{admin-report
|
||||
dataSourceName="most_disagreed_flaggers"
|
||||
filters=lastWeekfilters
|
||||
reportOptions=mostDisagreedFlaggersOptions}}
|
||||
|
||||
{{plugin-outlet name="admin-dashboard-moderation-bottom"}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
{{else}}
|
||||
<label>{{i18n 'admin.email.send_digest_label'}}</label>
|
||||
{{text-field value=email placeholderKey="admin.email.test_email_address"}}
|
||||
<button class='btn' {{action "sendEmail"}} disabled={{sendEmailDisabled}}>{{i18n 'admin.email.send_digest'}}</button>
|
||||
<button class='btn btn-default' {{action "sendEmail"}} disabled={{sendEmailDisabled}}>{{i18n 'admin.email.send_digest'}}</button>
|
||||
{{#if sentEmail}}
|
||||
<span class='result-message'>{{i18n 'admin.email.sent_test'}}</span>
|
||||
{{/if}}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<p>
|
||||
{{i18n 'admin.logs.screened_emails.description'}}
|
||||
</p>
|
||||
<button class="btn screened-email-export" {{action "exportScreenedEmailList"}} title="{{i18n 'admin.export_csv.button_title.screened_email'}}">{{d-icon "download"}}{{i18n 'admin.export_csv.button_text'}}</button>
|
||||
<button class="btn btn-default screened-email-export" {{action "exportScreenedEmailList"}} title="{{i18n 'admin.export_csv.button_title.screened_email'}}">{{d-icon "download"}}{{i18n 'admin.export_csv.button_text'}}</button>
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
<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 action="rollUp" title="admin.logs.screened_ips.roll_up.title" label="admin.logs.screened_ips.roll_up.text"}}
|
||||
{{d-button action="exportScreenedIpList" icon="download" title="admin.export_csv.button_title.screened_ip" label="admin.export_csv.button_text"}}
|
||||
{{d-button class="btn-default" action="rollUp" title="admin.logs.screened_ips.roll_up.title" label="admin.logs.screened_ips.roll_up.text"}}
|
||||
{{d-button class="btn-default" action="exportScreenedIpList" icon="download" title="admin.export_csv.button_title.screened_ip" label="admin.export_csv.button_text"}}
|
||||
</div>
|
||||
{{screened-ip-address-form action="recordAdded"}}
|
||||
</div>
|
||||
@ -57,15 +57,15 @@
|
||||
</td>
|
||||
<td class="col actions">
|
||||
{{#unless item.editing}}
|
||||
{{d-button action="destroy" actionParam=item icon="trash-o" class="btn-danger"}}
|
||||
{{d-button action="edit" actionParam=item icon="pencil"}}
|
||||
{{d-button class="btn-default" action="destroy" actionParam=item icon="trash-o" class="btn-danger"}}
|
||||
{{d-button class="btn-default"action="edit" actionParam=item icon="pencil"}}
|
||||
{{#if item.isBlocked}}
|
||||
{{d-button action="allow" actionParam=item icon="check" label="admin.logs.screened_ips.actions.do_nothing"}}
|
||||
{{d-button class="btn-default" action="allow" actionParam=item icon="check" label="admin.logs.screened_ips.actions.do_nothing"}}
|
||||
{{else}}
|
||||
{{d-button action="block" actionParam=item icon="ban" label="admin.logs.screened_ips.actions.block"}}
|
||||
{{d-button class="btn-default" action="block" actionParam=item icon="ban" label="admin.logs.screened_ips.actions.block"}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{d-button action="save" actionParam=item label="admin.logs.save"}}
|
||||
{{d-button class="btn-default" action="save" actionParam=item label="admin.logs.save"}}
|
||||
<a {{action "cancel" item}}>{{i18n 'cancel'}}</a>
|
||||
{{/unless}}
|
||||
</td>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<p>
|
||||
{{i18n 'admin.logs.screened_urls.description'}}
|
||||
</p>
|
||||
<button class="btn" {{action "exportScreenedUrlList"}} title="{{i18n 'admin.export_csv.button_title.screened_url'}}">{{d-icon "download"}}{{i18n 'admin.export_csv.button_text'}}</button>
|
||||
<button class="btn btn-default" {{action "exportScreenedUrlList"}} title="{{i18n 'admin.export_csv.button_title.screened_url'}}">{{d-icon "download"}}{{i18n 'admin.export_csv.button_text'}}</button>
|
||||
<br>
|
||||
|
||||
{{#conditional-loading-spinner condition=loading}}
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
{{i18n "admin.logs.staff_actions.filter"}} {{combo-box content=userHistoryActions value=filterActionId none="admin.logs.staff_actions.all"}}
|
||||
{{/if}}
|
||||
|
||||
{{d-button action="exportStaffActionLogs" label="admin.export_csv.button_text" icon="download"}}
|
||||
{{d-button class="btn-default" action="exportStaffActionLogs" label="admin.export_csv.button_text" icon="download"}}
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<label class="radio" for="local">{{i18n 'upload_selector.from_my_computer'}}</label>
|
||||
{{#if local}}
|
||||
<div class="inputs">
|
||||
<input 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'><br>
|
||||
<span class="description">{{i18n 'admin.customize.theme.import_file_tip'}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
@ -44,6 +44,6 @@
|
||||
{{/d-modal-body}}
|
||||
|
||||
<div class="modal-footer">
|
||||
{{d-button action="importTheme" disabled=loading class='btn btn-primary' icon='upload' label='admin.customize.import'}}
|
||||
{{d-button action="importTheme" disabled=importDisabled class='btn btn-primary' icon='upload' label='admin.customize.import'}}
|
||||
{{d-modal-cancel close=(action "closeModal")}}
|
||||
</div>
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
class="silence-until"
|
||||
label="admin.user.silence_duration"
|
||||
includeFarFuture=true
|
||||
clearable=false
|
||||
input=silenceUntil}}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
class="suspend-until"
|
||||
label="admin.user.suspend_duration"
|
||||
includeFarFuture=true
|
||||
clearable=false
|
||||
input=suspendUntil}}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
<div class="permalink-title"><h2>{{i18n 'admin.permalink.title'}}</h2></div>
|
||||
<div class="pull-right">
|
||||
<div class="permalink-title">
|
||||
<h2>{{i18n 'admin.permalink.title'}}</h2>
|
||||
</div>
|
||||
<div class="permalink-search">
|
||||
{{text-field value=filter class="url-input" placeholderKey="admin.permalink.form.filter" autocorrect="off" autocapitalize="off"}}
|
||||
</div>
|
||||
{{permalink-form action="recordAdded"}}
|
||||
|
||||
@ -49,7 +49,7 @@
|
||||
<td class="settings">
|
||||
{{#if currentUser.admin}}
|
||||
{{#if plugin.enabled_setting}}
|
||||
{{d-button action="showSettings" actionParam=plugin icon="gear" label="admin.plugins.change_settings_short"}}
|
||||
{{d-button class="btn-default" action="showSettings" actionParam=plugin icon="gear" label="admin.plugins.change_settings_short"}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</td>
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
{{#if currentUser.admin}}
|
||||
{{d-button label="admin.plugins.change_settings"
|
||||
icon="gear"
|
||||
class='settings-button'
|
||||
class="btn-default settings-button"
|
||||
action="showSettings"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<div class='controls'>
|
||||
{{d-button action="toggleMenu" class="menu-toggle" icon="bars"}}
|
||||
{{text-field id="setting-filter" value=filter placeholderKey="type_to_filter" class="no-blur"}}
|
||||
{{d-button id="clear-filter" action="clearFilter" label="admin.site_settings.clear_filter"}}
|
||||
{{d-button class="btn-default" id="clear-filter" action="clearFilter" label="admin.site_settings.clear_filter"}}
|
||||
</div>
|
||||
<div class='search controls'>
|
||||
<label>
|
||||
|
||||
@ -18,10 +18,10 @@
|
||||
<label>{{i18n 'admin.badges.badge'}}</label>
|
||||
{{combo-box filterable=true value=selectedBadgeId content=grantableBadges}}
|
||||
</div>
|
||||
<label>
|
||||
<div>
|
||||
<label>{{i18n 'admin.badges.reason'}}</label>
|
||||
{{input type="text" value=badgeReason}}<br><small>{{i18n 'admin.badges.reason_help'}}</small>
|
||||
</label>
|
||||
</div>
|
||||
<button class='btn btn-primary' {{action "grantBadge"}}>{{i18n 'admin.badges.grant'}}</button>
|
||||
</form>
|
||||
{{/if}}
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
<section class="details {{unless model.active 'not-activated'}}">
|
||||
<div class='user-controls'>
|
||||
{{#if model.canViewProfile}}
|
||||
{{#link-to 'user' model class="btn"}}
|
||||
{{#link-to 'user' model class="btn btn-default"}}
|
||||
{{d-icon "user"}}
|
||||
{{i18n 'admin.user.show_public_profile'}}
|
||||
{{/link-to}}
|
||||
{{/if}}
|
||||
|
||||
{{#if model.can_view_action_logs}}
|
||||
{{d-button action="viewActionLogs" actionParam=model.username icon="list-alt" label="admin.user.action_logs"}}
|
||||
{{d-button action="viewActionLogs" class="btn-default" actionParam=model.username icon="list-alt" label="admin.user.action_logs"}}
|
||||
{{/if}}
|
||||
{{#if model.active}}
|
||||
{{#if currentUser.admin}}
|
||||
{{d-button action="logOut" icon="power-off" label="admin.user.log_out"}}
|
||||
{{d-button class="btn-default" 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=""}}
|
||||
@ -29,10 +29,10 @@
|
||||
</div>
|
||||
<div class='controls'>
|
||||
{{#if editingUsername}}
|
||||
{{d-button action="saveUsername" label="admin.user_fields.save"}}
|
||||
{{d-button class="btn-default" action="saveUsername" label="admin.user_fields.save"}}
|
||||
<a href {{action "toggleUsernameEdit"}}>{{i18n 'cancel'}}</a>
|
||||
{{else}}
|
||||
{{d-button action="toggleUsernameEdit" icon="pencil"}}
|
||||
{{d-button class="btn-default" action="toggleUsernameEdit" icon="pencil"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
@ -48,10 +48,10 @@
|
||||
</div>
|
||||
<div class='controls'>
|
||||
{{#if editingName}}
|
||||
{{d-button action="saveName" label="admin.user_fields.save"}}
|
||||
{{d-button class="btn-default" action="saveName" label="admin.user_fields.save"}}
|
||||
<a href {{action "toggleNameEdit"}}>{{i18n 'cancel'}}</a>
|
||||
{{else}}
|
||||
{{d-button action="toggleNameEdit" icon="pencil"}}
|
||||
{{d-button class="btn-default" action="toggleNameEdit" icon="pencil"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
@ -68,7 +68,7 @@
|
||||
{{#if model.email}}
|
||||
<a href="mailto:{{unbound model.email}}">{{model.email}}</a>
|
||||
{{else}}
|
||||
{{d-button 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="checkEmail" actionParam=model icon="envelope-o" label="admin.users.check_email.text" title="admin.users.check_email.title"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
@ -89,6 +89,7 @@
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{d-button action="checkEmail"
|
||||
class="btn-default"
|
||||
actionParam=model
|
||||
icon="envelope-o"
|
||||
label="admin.users.check_email.text"
|
||||
@ -102,7 +103,7 @@
|
||||
<div class='value'>{{model.bounceScore}}</div>
|
||||
<div class='controls'>
|
||||
{{#if model.canResetBounceScore}}
|
||||
{{d-button action="resetBounceScore" label="admin.user.reset_bounce_score.label" title="admin.user.reset_bounce_score.title"}}
|
||||
{{d-button class="btn-default" action="resetBounceScore" label="admin.user.reset_bounce_score.label" title="admin.user.reset_bounce_score.title"}}
|
||||
{{/if}}
|
||||
{{model.bounceScoreExplanation}}
|
||||
</div>
|
||||
@ -114,7 +115,7 @@
|
||||
{{#if associatedAccountsLoaded}}
|
||||
{{associatedAccounts}}
|
||||
{{else}}
|
||||
{{d-button 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="checkEmail" actionParam=model icon="envelope-o" label="admin.users.check_email.text" title="admin.users.check_email.title"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
@ -139,10 +140,10 @@
|
||||
</div>
|
||||
<div class='controls'>
|
||||
{{#if editingTitle}}
|
||||
{{d-button action="saveTitle" label="admin.user_fields.save"}}
|
||||
{{d-button class="btn-default" action="saveTitle" label="admin.user_fields.save"}}
|
||||
<a href {{action "toggleTitleEdit"}}>{{i18n 'cancel'}}</a>
|
||||
{{else}}
|
||||
{{d-button action="toggleTitleEdit" icon="pencil"}}
|
||||
{{d-button class="btn-default" action="toggleTitleEdit" icon="pencil"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
@ -152,7 +153,7 @@
|
||||
<div class='value'>{{model.ip_address}}</div>
|
||||
<div class='controls'>
|
||||
{{#if currentUser.staff}}
|
||||
{{d-button action="refreshBrowsers" label="admin.user.refresh_browsers"}}
|
||||
{{d-button class="btn-default" action="refreshBrowsers" label="admin.user.refresh_browsers"}}
|
||||
{{ip-lookup ip=model.ip_address userId=model.id}}
|
||||
{{/if}}
|
||||
</div>
|
||||
@ -191,7 +192,7 @@
|
||||
</div>
|
||||
<div class='controls'>
|
||||
{{#if canDisableSecondFactor}}
|
||||
{{d-button action="disableSecondFactor" icon="unlock-alt" label="user.second_factor.disable"}}
|
||||
{{d-button class="btn-default" action="disableSecondFactor" icon="unlock-alt" label="user.second_factor.disable"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
@ -236,7 +237,7 @@
|
||||
{{i18n 'admin.user.approve_success'}}
|
||||
{{else}}
|
||||
{{#if model.can_approve}}
|
||||
{{d-button action="approve" icon="check" label="admin.user.approve"}}
|
||||
{{d-button class="btn-default" action="approve" icon="check" label="admin.user.approve"}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
@ -249,15 +250,15 @@
|
||||
<div class='controls'>
|
||||
{{#if model.active}}
|
||||
{{#if model.can_deactivate}}
|
||||
{{d-button action="deactivate" label="admin.user.deactivate_account"}}
|
||||
{{d-button class="btn-default" action="deactivate" label="admin.user.deactivate_account"}}
|
||||
{{i18n 'admin.user.deactivate_explanation'}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{#if model.can_send_activation_email}}
|
||||
{{d-button action="sendActivationEmail" icon="envelope" label="admin.user.send_activation_email"}}
|
||||
{{d-button class="btn-default" action="sendActivationEmail" icon="envelope" label="admin.user.send_activation_email"}}
|
||||
{{/if}}
|
||||
{{#if model.can_activate}}
|
||||
{{d-button action="activate" icon="check" label="admin.user.activate"}}
|
||||
{{d-button class="btn-default" action="activate" icon="check" label="admin.user.activate"}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
@ -275,15 +276,15 @@
|
||||
{{#if model.api_key}}
|
||||
<div class='long-value'>
|
||||
{{model.api_key.key}}
|
||||
{{d-button action="regenerateApiKey" icon="undo" label="admin.api.regenerate"}}
|
||||
{{d-button action="revokeApiKey" icon="times" label="admin.api.revoke"}}
|
||||
{{d-button class="btn-default" action="regenerateApiKey" icon="undo" label="admin.api.regenerate"}}
|
||||
{{d-button class="btn-default" action="revokeApiKey" icon="times" label="admin.api.revoke"}}
|
||||
</div>
|
||||
{{else}}
|
||||
<div class='value'>
|
||||
—
|
||||
</div>
|
||||
<div class='controls'>
|
||||
{{d-button action="generateApiKey" icon="key" label="admin.api.generate"}}
|
||||
{{d-button class="btn-default" action="generateApiKey" icon="key" label="admin.api.generate"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
@ -294,10 +295,10 @@
|
||||
<div class='value'>{{i18n-yes-no model.admin}}</div>
|
||||
<div class='controls'>
|
||||
{{#if model.can_revoke_admin}}
|
||||
{{d-button action="revokeAdmin" icon="shield" label="admin.user.revoke_admin"}}
|
||||
{{d-button class="btn-default" action="revokeAdmin" icon="shield" label="admin.user.revoke_admin"}}
|
||||
{{/if}}
|
||||
{{#if model.can_grant_admin}}
|
||||
{{d-button action="grantAdmin" icon="shield" label="admin.user.grant_admin"}}
|
||||
{{d-button class="btn-default" action="grantAdmin" icon="shield" label="admin.user.grant_admin"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
@ -307,10 +308,10 @@
|
||||
<div class='value'>{{i18n-yes-no model.moderator}}</div>
|
||||
<div class='controls'>
|
||||
{{#if model.can_revoke_moderation}}
|
||||
{{d-button action="revokeModeration" icon="shield" label="admin.user.revoke_moderation"}}
|
||||
{{d-button class="btn-default" action="revokeModeration" icon="shield" label="admin.user.revoke_moderation"}}
|
||||
{{/if}}
|
||||
{{#if model.can_grant_moderation}}
|
||||
{{d-button action="grantModeration" icon="shield" label="admin.user.grant_moderation"}}
|
||||
{{d-button class="btn-default" action="grantModeration" icon="shield" label="admin.user.grant_moderation"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
@ -330,14 +331,14 @@
|
||||
{{#if model.canLockTrustLevel}}
|
||||
{{#if hasLockedTrustLevel}}
|
||||
{{d-icon "lock" title="admin.user.trust_level_locked_tip"}}
|
||||
{{d-button action="lockTrustLevel" actionParam=false label="admin.user.unlock_trust_level"}}
|
||||
{{d-button class="btn-default" action="lockTrustLevel" actionParam=false label="admin.user.unlock_trust_level"}}
|
||||
{{else}}
|
||||
{{d-icon "unlock" title="admin.user.trust_level_unlocked_tip"}}
|
||||
{{d-button action="lockTrustLevel" actionParam=true label="admin.user.lock_trust_level"}}
|
||||
{{d-button class="btn-default" action="lockTrustLevel" actionParam=true label="admin.user.lock_trust_level"}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{#if model.tl3Requirements}}
|
||||
{{#link-to 'adminUser.tl3Requirements' model class="btn"}}{{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>
|
||||
@ -439,6 +440,7 @@
|
||||
{{#if currentUser.admin}}
|
||||
<div class='controls'>
|
||||
{{d-button label="admin.user.clear_penalty_history.title"
|
||||
class="btn-default"
|
||||
icon="times"
|
||||
action=(action "clearPenaltyHistory")}}
|
||||
{{i18n "admin.user.clear_penalty_history.description"}}
|
||||
@ -537,6 +539,7 @@
|
||||
<div class='controls'>
|
||||
{{#if model.flags_received_count}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
action=(action "showFlagsReceived")
|
||||
label="admin.user.show_flags_received"
|
||||
icon="flag"
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
<div class="admin-title">
|
||||
<h2>{{title}}</h2>
|
||||
{{#unless showEmails}}
|
||||
<button {{action "showEmails"}} class="show-emails btn">{{i18n 'admin.users.show_emails'}}</button>
|
||||
<button {{action "showEmails"}} class="show-emails btn btn-default">{{i18n 'admin.users.show_emails'}}</button>
|
||||
{{/unless}}
|
||||
</div>
|
||||
<div class='username controls'>
|
||||
|
||||
@ -14,10 +14,10 @@
|
||||
{{nav-item route='groups' label='groups.index.title'}}
|
||||
<div class="admin-actions">
|
||||
{{#unless siteSettings.enable_sso}}
|
||||
{{d-button action="sendInvites" title="admin.invite.button_title" icon="user-plus" label="admin.invite.button_text"}}
|
||||
{{d-button class="btn-default" action="sendInvites" title="admin.invite.button_title" icon="user-plus" label="admin.invite.button_text"}}
|
||||
{{/unless}}
|
||||
{{#if currentUser.admin}}
|
||||
{{d-button action="exportUsers" title="admin.export_csv.button_title.user" icon="download" label="admin.export_csv.button_text"}}
|
||||
{{d-button class="btn-default" action="exportUsers" title="admin.export_csv.button_title.user" icon="download" label="admin.export_csv.button_text"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</ul>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class='web-hooks-listing'>
|
||||
<p>{{i18n 'admin.web_hooks.instruction'}}</p>
|
||||
<div class='new-webhook'>
|
||||
{{#link-to 'adminWebHooks.show' 'new' tagName='button' classNames='btn'}}
|
||||
{{#link-to 'adminWebHooks.show' 'new' tagName='button' classNames='btn btn-default'}}
|
||||
{{d-icon 'plus'}} {{i18n 'admin.web_hooks.new'}}
|
||||
{{/link-to}}
|
||||
</div>
|
||||
|
||||
6
app/assets/javascripts/auto-redirect.js.no-module.es6
Normal file
6
app/assets/javascripts/auto-redirect.js.no-module.es6
Normal file
@ -0,0 +1,6 @@
|
||||
(function() {
|
||||
const path = document.getElementById("data-auto-redirect").dataset.path;
|
||||
setTimeout(function() {
|
||||
window.location.href = path;
|
||||
}, 2000);
|
||||
})();
|
||||
@ -0,0 +1,51 @@
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
import UploadMixin from "discourse/mixins/upload";
|
||||
|
||||
export default Em.Component.extend(UploadMixin, {
|
||||
tagName: "span",
|
||||
|
||||
@computed("uploading", "uploadProgress")
|
||||
uploadButtonText(uploading, progress) {
|
||||
return uploading
|
||||
? I18n.t("admin.backups.upload.uploading_progress", { progress })
|
||||
: I18n.t("admin.backups.upload.label");
|
||||
},
|
||||
|
||||
validateUploadedFilesOptions() {
|
||||
return { skipValidation: true };
|
||||
},
|
||||
|
||||
uploadDone() {
|
||||
this.sendAction("done");
|
||||
},
|
||||
|
||||
calculateUploadUrl() {
|
||||
return "";
|
||||
},
|
||||
|
||||
uploadOptions() {
|
||||
return {
|
||||
type: "PUT",
|
||||
dataType: "xml",
|
||||
autoUpload: false
|
||||
};
|
||||
},
|
||||
|
||||
_init: function() {
|
||||
const $upload = this.$();
|
||||
|
||||
$upload.on("fileuploadadd", (e, data) => {
|
||||
ajax("/admin/backups/upload_url", {
|
||||
data: { filename: data.files[0].name }
|
||||
}).then(result => {
|
||||
if (!result.success) {
|
||||
bootbox.alert(result.message);
|
||||
} else {
|
||||
data.url = result.url;
|
||||
data.submit();
|
||||
}
|
||||
});
|
||||
});
|
||||
}.on("didInsertElement")
|
||||
});
|
||||
@ -618,7 +618,6 @@ export default Ember.Component.extend({
|
||||
|
||||
_bindUploadTarget() {
|
||||
this._unbindUploadTarget(); // in case it's still bound, let's clean it up first
|
||||
|
||||
this._pasted = false;
|
||||
|
||||
const $element = this.$();
|
||||
@ -649,12 +648,23 @@ export default Ember.Component.extend({
|
||||
});
|
||||
|
||||
$element.on("fileuploadsubmit", (e, data) => {
|
||||
const max = this.siteSettings.simultaneous_uploads;
|
||||
|
||||
// Limit the number of simultaneous uploads
|
||||
if (max > 0 && data.files.length > max) {
|
||||
bootbox.alert(
|
||||
I18n.t("post.errors.too_many_dragged_and_dropped_files", { max })
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Look for a matching file upload handler contributed from a plugin
|
||||
const matcher = handler => {
|
||||
const ext = handler.extensions.join("|");
|
||||
const regex = new RegExp(`\\.(${ext})$`, "i");
|
||||
return regex.test(data.files[0].name);
|
||||
};
|
||||
|
||||
const matchingHandler = uploadHandlers.find(matcher);
|
||||
if (data.files.length === 1 && matchingHandler) {
|
||||
matchingHandler.method(data.files[0]);
|
||||
|
||||
@ -13,7 +13,7 @@ export default Ember.Component.extend({
|
||||
_yourselfConfirm: null,
|
||||
similarTopics: null,
|
||||
|
||||
hidden: Ember.computed.not("composer.viewOpen"),
|
||||
hidden: Ember.computed.not("composer.viewOpenOrFullscreen"),
|
||||
|
||||
didInsertElement() {
|
||||
this._super();
|
||||
|
||||
@ -4,18 +4,28 @@ export default Ember.Component.extend({
|
||||
tagName: "",
|
||||
|
||||
@computed("composeState")
|
||||
title(composeState) {
|
||||
if (composeState === "draft" || composeState === "saving") {
|
||||
return "composer.abandon";
|
||||
}
|
||||
return "composer.collapse";
|
||||
toggleTitle(composeState) {
|
||||
return composeState === "draft" || composeState === "saving"
|
||||
? "composer.abandon"
|
||||
: "composer.collapse";
|
||||
},
|
||||
|
||||
@computed("composeState")
|
||||
fullscreenTitle(composeState) {
|
||||
return composeState === "fullscreen"
|
||||
? "composer.exit_fullscreen"
|
||||
: "composer.enter_fullscreen";
|
||||
},
|
||||
|
||||
@computed("composeState")
|
||||
toggleIcon(composeState) {
|
||||
if (composeState === "draft" || composeState === "saving") {
|
||||
return "times";
|
||||
}
|
||||
return "chevron-down";
|
||||
return composeState === "draft" || composeState === "saving"
|
||||
? "times"
|
||||
: "chevron-down";
|
||||
},
|
||||
|
||||
@computed("composeState")
|
||||
fullscreenIcon(composeState) {
|
||||
return composeState === "fullscreen" ? "compress" : "expand";
|
||||
}
|
||||
});
|
||||
|
||||
@ -11,7 +11,7 @@ export default Ember.Component.extend(
|
||||
let notices = [];
|
||||
|
||||
if ($.cookie("dosp") === "1") {
|
||||
$.cookie("dosp", null, { path: "/" });
|
||||
$.removeCookie("dosp", { path: "/" });
|
||||
notices.push([I18n.t("forced_anonymous"), "forced-anonymous"]);
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import Button from "discourse/components/d-button";
|
||||
|
||||
export default Button.extend({
|
||||
classNames: ["share"],
|
||||
classNames: ["btn-default", "share"],
|
||||
icon: "link",
|
||||
title: "topic.share.help",
|
||||
label: "topic.share.title",
|
||||
|
||||
@ -16,6 +16,12 @@ export default DropdownSelectBoxComponent.extend({
|
||||
name: I18n.t("tagging.manage_groups"),
|
||||
description: I18n.t("tagging.manage_groups_description"),
|
||||
icon: "wrench"
|
||||
},
|
||||
{
|
||||
id: "uploadTags",
|
||||
name: I18n.t("tagging.upload"),
|
||||
description: I18n.t("tagging.upload_description"),
|
||||
icon: "upload"
|
||||
}
|
||||
];
|
||||
|
||||
@ -23,7 +29,8 @@ export default DropdownSelectBoxComponent.extend({
|
||||
},
|
||||
|
||||
actionNames: {
|
||||
manageGroups: "showTagGroups"
|
||||
manageGroups: "showTagGroups",
|
||||
uploadTags: "showUploader"
|
||||
},
|
||||
|
||||
mutateValue(id) {
|
||||
|
||||
@ -35,7 +35,7 @@ export default Ember.Component.extend(PanEvents, {
|
||||
height -= $("#reply-control").height();
|
||||
}
|
||||
|
||||
renderTimeline = width > 960 && height > 520;
|
||||
renderTimeline = width > 924 && height > 520;
|
||||
}
|
||||
|
||||
info.setProperties({
|
||||
|
||||
@ -231,7 +231,7 @@ export default Ember.Controller.extend({
|
||||
|
||||
@computed("model.composeState", "model.creatingTopic")
|
||||
popupMenuOptions(composeState) {
|
||||
if (composeState === "open") {
|
||||
if (composeState === "open" || composeState === "fullscreen") {
|
||||
let options = [];
|
||||
|
||||
options.push(
|
||||
@ -386,7 +386,10 @@ export default Ember.Controller.extend({
|
||||
) {
|
||||
this.close();
|
||||
} else {
|
||||
if (this.get("model.composeState") === Composer.OPEN) {
|
||||
if (
|
||||
this.get("model.composeState") === Composer.OPEN ||
|
||||
this.get("model.composeState") === Composer.FULLSCREEN
|
||||
) {
|
||||
this.shrink();
|
||||
} else {
|
||||
this.cancelComposer();
|
||||
@ -396,6 +399,11 @@ export default Ember.Controller.extend({
|
||||
return false;
|
||||
},
|
||||
|
||||
fullscreenComposer() {
|
||||
this.toggleFullscreen();
|
||||
return false;
|
||||
},
|
||||
|
||||
// Import a quote from the post
|
||||
importQuote(toolbarEvent) {
|
||||
const postStream = this.get("topic.postStream");
|
||||
@ -457,7 +465,7 @@ export default Ember.Controller.extend({
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.get("model.viewOpen")) {
|
||||
if (this.get("model.viewOpen") || this.get("model.viewFullscreen")) {
|
||||
this.shrink();
|
||||
}
|
||||
},
|
||||
@ -947,7 +955,20 @@ export default Ember.Controller.extend({
|
||||
this.set("model.composeState", Composer.DRAFT);
|
||||
},
|
||||
|
||||
toggleFullscreen() {
|
||||
this._saveDraft();
|
||||
if (this.get("model.composeState") === Composer.FULLSCREEN) {
|
||||
this.set("model.composeState", Composer.OPEN);
|
||||
} else {
|
||||
this.set("model.composeState", Composer.FULLSCREEN);
|
||||
}
|
||||
},
|
||||
|
||||
close() {
|
||||
// the 'fullscreen-composer' class is added to remove scrollbars from the
|
||||
// document while in fullscreen mode. If the composer is closed for any reason
|
||||
// this class should be removed
|
||||
$("html").removeClass("fullscreen-composer");
|
||||
this.setProperties({ model: null, lastValidatedAt: null });
|
||||
},
|
||||
|
||||
|
||||
@ -9,6 +9,7 @@ import UsernameValidation from "discourse/mixins/username-validation";
|
||||
import NameValidation from "discourse/mixins/name-validation";
|
||||
import UserFieldsValidation from "discourse/mixins/user-fields-validation";
|
||||
import { userPath } from "discourse/lib/url";
|
||||
import { findAll } from "discourse/models/login-method";
|
||||
|
||||
export default Ember.Controller.extend(
|
||||
ModalFunctionality,
|
||||
@ -176,6 +177,11 @@ export default Ember.Controller.extend(
|
||||
}
|
||||
}.observes("emailValidation", "accountEmail"),
|
||||
|
||||
// Determines whether at least one login button is enabled
|
||||
hasAtLeastOneLoginButton: function() {
|
||||
return findAll(this.siteSettings).length > 0;
|
||||
}.property(),
|
||||
|
||||
@on("init")
|
||||
fetchConfirmationValue() {
|
||||
return ajax(userPath("hp.json")).then(json => {
|
||||
@ -260,12 +266,12 @@ export default Ember.Controller.extend(
|
||||
this.get("rejectedPasswords").pushObject(attrs.accountPassword);
|
||||
}
|
||||
this.set("formSubmitted", false);
|
||||
$.cookie("destination_url", null);
|
||||
$.removeCookie("destination_url");
|
||||
}
|
||||
},
|
||||
() => {
|
||||
this.set("formSubmitted", false);
|
||||
$.cookie("destination_url", null);
|
||||
$.removeCookie("destination_url");
|
||||
return this.flash(I18n.t("create_account.failed"), "error");
|
||||
}
|
||||
);
|
||||
|
||||
@ -57,9 +57,10 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
},
|
||||
|
||||
// Determines whether at least one login button is enabled
|
||||
hasAtLeastOneLoginButton: function() {
|
||||
return findAll(this.siteSettings).length > 0;
|
||||
}.property(),
|
||||
@computed("canLoginLocalWithEmail")
|
||||
hasAtLeastOneLoginButton(canLoginLocalWithEmail) {
|
||||
return findAll(this.siteSettings).length > 0 || canLoginLocalWithEmail;
|
||||
},
|
||||
|
||||
@computed("loggingIn")
|
||||
loginButtonLabel(loggingIn) {
|
||||
@ -158,12 +159,12 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
.val(self.get("loginPassword"));
|
||||
|
||||
if (ssoDestinationUrl) {
|
||||
$.cookie("sso_destination_url", null);
|
||||
$.removeCookie("sso_destination_url");
|
||||
window.location.assign(ssoDestinationUrl);
|
||||
return;
|
||||
} else if (destinationUrl) {
|
||||
// redirect client to the original URL
|
||||
$.cookie("destination_url", null);
|
||||
$.removeCookie("destination_url");
|
||||
$hidden_login_form
|
||||
.find("input[name=redirect]")
|
||||
.val(destinationUrl);
|
||||
@ -327,7 +328,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
$.cookie("destination_url") || options.destination_url;
|
||||
if (destinationUrl) {
|
||||
// redirect client to the original URL
|
||||
$.cookie("destination_url", null);
|
||||
$.removeCookie("destination_url");
|
||||
window.location.href = destinationUrl;
|
||||
} else if (window.location.pathname === Discourse.getURL("/login")) {
|
||||
window.location.pathname = Discourse.getURL("/");
|
||||
|
||||
@ -83,8 +83,12 @@ export default Ember.Controller.extend(PasswordValidation, {
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
throw new Error(error);
|
||||
.catch(e => {
|
||||
if (e.jqXHR && e.jqXHR.status === 429) {
|
||||
this.set("errorMessage", I18n.t("user.second_factor.rate_limit"));
|
||||
} else {
|
||||
throw new Error(e);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@ -107,7 +107,12 @@ export default Ember.Controller.extend(
|
||||
@computed("showAllAuthTokens", "model.user_auth_tokens")
|
||||
authTokens(showAllAuthTokens, tokens) {
|
||||
tokens.sort(
|
||||
(a, b) => (a.is_active ? -1 : b.is_active ? 1 : a.seen_at < b.seen_at)
|
||||
(a, b) =>
|
||||
a.is_active
|
||||
? -1
|
||||
: b.is_active
|
||||
? 1
|
||||
: b.seen_at.localeCompare(a.seen_at)
|
||||
);
|
||||
|
||||
return showAllAuthTokens
|
||||
@ -199,10 +204,6 @@ export default Ember.Controller.extend(
|
||||
bootbox.dialog(message, buttons, { classes: "delete-account" });
|
||||
},
|
||||
|
||||
showTwoFactorModal() {
|
||||
showModal("second-factor-intro");
|
||||
},
|
||||
|
||||
revokeAccount(account) {
|
||||
const model = this.get("model");
|
||||
this.set("revoking", true);
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
import showModal from "discourse/lib/show-modal";
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
sortProperties: ["totalCount:desc", "id"],
|
||||
@ -33,6 +34,10 @@ export default Ember.Controller.extend({
|
||||
sortedByCount: false,
|
||||
sortedByName: true
|
||||
});
|
||||
},
|
||||
|
||||
showUploader() {
|
||||
showModal("tag-upload");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -21,24 +21,45 @@ function addBulkButton(action, key, opts) {
|
||||
}
|
||||
|
||||
// Default buttons
|
||||
addBulkButton("showChangeCategory", "change_category", { icon: "pencil" });
|
||||
addBulkButton("closeTopics", "close_topics", { icon: "lock" });
|
||||
addBulkButton("archiveTopics", "archive_topics", { icon: "folder" });
|
||||
addBulkButton("showNotificationLevel", "notification_level", {
|
||||
icon: "d-regular"
|
||||
addBulkButton("showChangeCategory", "change_category", {
|
||||
icon: "pencil",
|
||||
class: "btn-default"
|
||||
});
|
||||
addBulkButton("closeTopics", "close_topics", {
|
||||
icon: "lock",
|
||||
class: "btn-default"
|
||||
});
|
||||
addBulkButton("archiveTopics", "archive_topics", {
|
||||
icon: "folder",
|
||||
class: "btn-default"
|
||||
});
|
||||
addBulkButton("showNotificationLevel", "notification_level", {
|
||||
icon: "d-regular",
|
||||
class: "btn-default"
|
||||
});
|
||||
addBulkButton("resetRead", "reset_read", {
|
||||
icon: "backward",
|
||||
class: "btn-default"
|
||||
});
|
||||
addBulkButton("resetRead", "reset_read", { icon: "backward" });
|
||||
addBulkButton("unlistTopics", "unlist_topics", {
|
||||
icon: "eye-slash",
|
||||
class: "btn-default",
|
||||
buttonVisible: topics => topics.some(t => t.visible)
|
||||
});
|
||||
addBulkButton("relistTopics", "relist_topics", {
|
||||
icon: "eye",
|
||||
class: "btn-default",
|
||||
buttonVisible: topics => topics.some(t => !t.visible)
|
||||
});
|
||||
if (Discourse.SiteSettings.tagging_enabled) {
|
||||
addBulkButton("showTagTopics", "change_tags", { icon: "tag" });
|
||||
addBulkButton("showAppendTagTopics", "append_tags", { icon: "tag" });
|
||||
addBulkButton("showTagTopics", "change_tags", {
|
||||
icon: "tag",
|
||||
class: "btn-default"
|
||||
});
|
||||
addBulkButton("showAppendTagTopics", "append_tags", {
|
||||
icon: "tag",
|
||||
class: "btn-default"
|
||||
});
|
||||
}
|
||||
addBulkButton("deleteTopics", "delete", { icon: "trash", class: "btn-danger" });
|
||||
|
||||
|
||||
@ -13,6 +13,11 @@ export function isValidLink($link) {
|
||||
|
||||
export default {
|
||||
trackClick(e) {
|
||||
// right clicks are not tracked
|
||||
if (e.which === 3) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// cancel click if triggered as part of selection.
|
||||
if (selectedText() !== "") {
|
||||
return false;
|
||||
|
||||
@ -65,6 +65,7 @@ const bindings = {
|
||||
"shift+s": { click: "#topic-footer-buttons button.share", anonymous: true }, // share topic
|
||||
"shift+u": { handler: "goToUnreadPost" },
|
||||
"shift+z shift+z": { handler: "logout" },
|
||||
"shift+f11": { handler: "fullscreenComposer" },
|
||||
t: { postAction: "replyAsNewTopic" },
|
||||
u: { handler: "goBack", anonymous: true },
|
||||
"x r": {
|
||||
@ -212,6 +213,13 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
fullscreenComposer() {
|
||||
const composer = this.container.lookup("controller:composer");
|
||||
if (composer.get("model")) {
|
||||
composer.toggleFullscreen();
|
||||
}
|
||||
},
|
||||
|
||||
pinUnpinTopic() {
|
||||
this.container.lookup("controller:topic").togglePinnedState();
|
||||
},
|
||||
|
||||
@ -9,24 +9,13 @@ import Post from "discourse/models/post";
|
||||
import Topic from "discourse/models/topic";
|
||||
|
||||
export function translateResults(results, opts) {
|
||||
if (!opts) opts = {};
|
||||
opts = opts || {};
|
||||
|
||||
// Topics might not be included
|
||||
if (!results.topics) {
|
||||
results.topics = [];
|
||||
}
|
||||
if (!results.users) {
|
||||
results.users = [];
|
||||
}
|
||||
if (!results.posts) {
|
||||
results.posts = [];
|
||||
}
|
||||
if (!results.categories) {
|
||||
results.categories = [];
|
||||
}
|
||||
if (!results.tags) {
|
||||
results.tags = [];
|
||||
}
|
||||
results.topics = results.topics || [];
|
||||
results.users = results.users || [];
|
||||
results.posts = results.posts || [];
|
||||
results.categories = results.categories || [];
|
||||
results.tags = results.tags || [];
|
||||
|
||||
const topicMap = {};
|
||||
results.topics = results.topics.map(function(topic) {
|
||||
@ -45,8 +34,7 @@ export function translateResults(results, opts) {
|
||||
});
|
||||
|
||||
results.users = results.users.map(function(user) {
|
||||
user = User.create(user);
|
||||
return user;
|
||||
return User.create(user);
|
||||
});
|
||||
|
||||
results.categories = results.categories
|
||||
@ -57,7 +45,7 @@ export function translateResults(results, opts) {
|
||||
|
||||
results.tags = results.tags
|
||||
.map(function(tag) {
|
||||
let tagName = Handlebars.Utils.escapeExpression(tag.name);
|
||||
const tagName = Handlebars.Utils.escapeExpression(tag.name);
|
||||
return Ember.Object.create({
|
||||
id: tagName,
|
||||
url: Discourse.getURL("/tags/" + tagName)
|
||||
@ -65,31 +53,31 @@ export function translateResults(results, opts) {
|
||||
})
|
||||
.compact();
|
||||
|
||||
const r = results.grouped_search_result;
|
||||
results.resultTypes = [];
|
||||
|
||||
// TODO: consider refactoring front end to take a better structure
|
||||
if (r) {
|
||||
const groupedSearchResult = results.grouped_search_result;
|
||||
if (groupedSearchResult) {
|
||||
[
|
||||
["topic", "posts"],
|
||||
["user", "users"],
|
||||
["category", "categories"],
|
||||
["tag", "tags"]
|
||||
["tag", "tags"],
|
||||
["user", "users"]
|
||||
].forEach(function(pair) {
|
||||
const type = pair[0],
|
||||
name = pair[1];
|
||||
const type = pair[0];
|
||||
const name = pair[1];
|
||||
if (results[name].length > 0) {
|
||||
var result = {
|
||||
const componentName =
|
||||
opts.searchContext &&
|
||||
opts.searchContext.type === "topic" &&
|
||||
type === "topic"
|
||||
? "post"
|
||||
: type;
|
||||
const result = {
|
||||
results: results[name],
|
||||
componentName:
|
||||
"search-result-" +
|
||||
(opts.searchContext &&
|
||||
opts.searchContext.type === "topic" &&
|
||||
type === "topic"
|
||||
? "post"
|
||||
: type),
|
||||
componentName: `search-result-${componentName}`,
|
||||
type,
|
||||
more: r["more_" + name]
|
||||
more: groupedSearchResult[`more_${name}`]
|
||||
};
|
||||
|
||||
if (result.more && name === "posts" && opts.fullSearchUrl) {
|
||||
@ -103,10 +91,10 @@ export function translateResults(results, opts) {
|
||||
}
|
||||
|
||||
const noResults = !!(
|
||||
results.topics.length === 0 &&
|
||||
results.posts.length === 0 &&
|
||||
results.users.length === 0 &&
|
||||
results.categories.length === 0
|
||||
!results.topics.length &&
|
||||
!results.posts.length &&
|
||||
!results.users.length &&
|
||||
!results.categories.length
|
||||
);
|
||||
|
||||
return noResults ? null : Em.Object.create(results);
|
||||
|
||||
@ -38,7 +38,7 @@ export function setLocalTheme(ids, themeSeq) {
|
||||
expires: 9999
|
||||
});
|
||||
} else {
|
||||
$.cookie("theme_ids", null, { path: "/", expires: 1 });
|
||||
$.removeCookie("theme_ids", { path: "/", expires: 1 });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -227,7 +227,7 @@ export class Tag {
|
||||
const src = attr.src || pAttr.src;
|
||||
const cssClass = attr.class || pAttr.class;
|
||||
|
||||
if (cssClass === "emoji") {
|
||||
if (cssClass && cssClass.includes("emoji")) {
|
||||
return attr.title || pAttr.title;
|
||||
}
|
||||
|
||||
|
||||
@ -109,6 +109,10 @@ function organizeResults(r, options) {
|
||||
}
|
||||
|
||||
export default function userSearch(options) {
|
||||
if (options.term && options.term.length > 0 && options.term[0] === "@") {
|
||||
options.term = options.term.substring(1);
|
||||
}
|
||||
|
||||
var term = options.term || "",
|
||||
includeGroups = options.includeGroups,
|
||||
includeMentionableGroups = options.includeMentionableGroups,
|
||||
|
||||
@ -225,6 +225,7 @@ export function validateUploadedFiles(files, opts) {
|
||||
}
|
||||
|
||||
export function validateUploadedFile(file, opts) {
|
||||
if (opts.skipValidation) return true;
|
||||
if (!authorizesOneOrMoreExtensions()) return false;
|
||||
|
||||
opts = opts || {};
|
||||
|
||||
@ -2,6 +2,7 @@ import {
|
||||
displayErrorForUpload,
|
||||
validateUploadedFiles
|
||||
} from "discourse/lib/utilities";
|
||||
import getUrl from "discourse-common/lib/get-url";
|
||||
|
||||
export default Em.Mixin.create({
|
||||
uploading: false,
|
||||
@ -15,13 +16,28 @@ export default Em.Mixin.create({
|
||||
return {};
|
||||
},
|
||||
|
||||
calculateUploadUrl() {
|
||||
return (
|
||||
getUrl(this.getWithDefault("uploadUrl", "/uploads")) +
|
||||
".json?client_id=" +
|
||||
this.messageBus.clientId +
|
||||
"&authenticity_token=" +
|
||||
encodeURIComponent(Discourse.Session.currentProp("csrfToken"))
|
||||
);
|
||||
},
|
||||
|
||||
uploadOptions() {
|
||||
return {};
|
||||
},
|
||||
|
||||
_initialize: function() {
|
||||
const $upload = this.$(),
|
||||
csrf = Discourse.Session.currentProp("csrfToken"),
|
||||
uploadUrl = Discourse.getURL(
|
||||
this.getWithDefault("uploadUrl", "/uploads")
|
||||
),
|
||||
reset = () => this.setProperties({ uploading: false, uploadProgress: 0 });
|
||||
const $upload = this.$();
|
||||
const reset = () =>
|
||||
this.setProperties({ uploading: false, uploadProgress: 0 });
|
||||
const maxFiles = this.getWithDefault(
|
||||
"maxFiles",
|
||||
this.siteSettings.simultaneous_uploads
|
||||
);
|
||||
|
||||
$upload.on("fileuploaddone", (e, data) => {
|
||||
let upload = data.result;
|
||||
@ -29,21 +45,26 @@ export default Em.Mixin.create({
|
||||
reset();
|
||||
});
|
||||
|
||||
$upload.fileupload({
|
||||
url:
|
||||
uploadUrl +
|
||||
".json?client_id=" +
|
||||
this.messageBus.clientId +
|
||||
"&authenticity_token=" +
|
||||
encodeURIComponent(csrf),
|
||||
dataType: "json",
|
||||
dropZone: $upload,
|
||||
pasteZone: $upload
|
||||
});
|
||||
$upload.fileupload(
|
||||
_.merge(
|
||||
{
|
||||
url: this.calculateUploadUrl(),
|
||||
dataType: "json",
|
||||
replaceFileInput: false,
|
||||
dropZone: $upload,
|
||||
pasteZone: $upload
|
||||
},
|
||||
this.uploadOptions()
|
||||
)
|
||||
);
|
||||
|
||||
$upload.on("fileuploaddrop", (e, data) => {
|
||||
if (data.files.length > 10) {
|
||||
bootbox.alert(I18n.t("post.errors.too_many_dragged_and_dropped_files"));
|
||||
if (maxFiles > 0 && data.files.length > maxFiles) {
|
||||
bootbox.alert(
|
||||
I18n.t("post.errors.too_many_dragged_and_dropped_files", {
|
||||
max: maxFiles
|
||||
})
|
||||
);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
@ -56,7 +77,8 @@ export default Em.Mixin.create({
|
||||
this.validateUploadedFilesOptions()
|
||||
);
|
||||
const isValid = validateUploadedFiles(data.files, opts);
|
||||
let form = { type: this.get("type") };
|
||||
const type = this.get("type");
|
||||
let form = type ? { type } : {};
|
||||
if (this.get("data")) {
|
||||
form = $.extend(form, this.get("data"));
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@ const CLOSED = "closed",
|
||||
SAVING = "saving",
|
||||
OPEN = "open",
|
||||
DRAFT = "draft",
|
||||
FULLSCREEN = "fullscreen",
|
||||
// When creating, these fields are moved into the post model from the composer model
|
||||
_create_serializer = {
|
||||
raw: "reply",
|
||||
@ -144,15 +145,24 @@ const Composer = RestModel.extend({
|
||||
|
||||
viewOpen: Em.computed.equal("composeState", OPEN),
|
||||
viewDraft: Em.computed.equal("composeState", DRAFT),
|
||||
viewFullscreen: Em.computed.equal("composeState", FULLSCREEN),
|
||||
viewOpenOrFullscreen: Em.computed.or("viewOpen", "viewFullscreen"),
|
||||
|
||||
composeStateChanged: function() {
|
||||
var oldOpen = this.get("composerOpened");
|
||||
let oldOpen = this.get("composerOpened"),
|
||||
elem = $("html");
|
||||
|
||||
if (this.get("composeState") === FULLSCREEN) {
|
||||
elem.addClass("fullscreen-composer");
|
||||
} else {
|
||||
elem.removeClass("fullscreen-composer");
|
||||
}
|
||||
|
||||
if (this.get("composeState") === OPEN) {
|
||||
this.set("composerOpened", oldOpen || new Date());
|
||||
} else {
|
||||
if (oldOpen) {
|
||||
var oldTotal = this.get("composerTotalOpened") || 0;
|
||||
let oldTotal = this.get("composerTotalOpened") || 0;
|
||||
this.set("composerTotalOpened", oldTotal + (new Date() - oldOpen));
|
||||
}
|
||||
this.set("composerOpened", null);
|
||||
@ -160,9 +170,8 @@ const Composer = RestModel.extend({
|
||||
}.observes("composeState"),
|
||||
|
||||
composerTime: function() {
|
||||
var total = this.get("composerTotalOpened") || 0;
|
||||
|
||||
var oldOpen = this.get("composerOpened");
|
||||
let total = this.get("composerTotalOpened") || 0,
|
||||
oldOpen = this.get("composerOpened");
|
||||
if (oldOpen) {
|
||||
total += new Date() - oldOpen;
|
||||
}
|
||||
@ -183,7 +192,7 @@ const Composer = RestModel.extend({
|
||||
// view detected user is typing
|
||||
typing: _.throttle(
|
||||
function() {
|
||||
var typingTime = this.get("typingTime") || 0;
|
||||
let typingTime = this.get("typingTime") || 0;
|
||||
this.set("typingTime", typingTime + 100);
|
||||
},
|
||||
100,
|
||||
@ -378,9 +387,14 @@ const Composer = RestModel.extend({
|
||||
return SAVE_ICONS[action];
|
||||
},
|
||||
|
||||
@computed("action", "whisper")
|
||||
saveLabel(action, whisper) {
|
||||
return whisper ? "composer.create_whisper" : SAVE_LABELS[action];
|
||||
@computed("action", "whisper", "editConflict")
|
||||
saveLabel(action, whisper, editConflict) {
|
||||
if (editConflict) {
|
||||
return "composer.overwrite_edit";
|
||||
} else if (whisper) {
|
||||
return "composer.create_whisper";
|
||||
}
|
||||
return SAVE_LABELS[action];
|
||||
},
|
||||
|
||||
hasMetaData: function() {
|
||||
@ -718,7 +732,8 @@ const Composer = RestModel.extend({
|
||||
composerOpened: null,
|
||||
composerTotalOpened: 0,
|
||||
featuredLink: null,
|
||||
noBump: false
|
||||
noBump: false,
|
||||
editConflict: false
|
||||
});
|
||||
},
|
||||
|
||||
@ -753,6 +768,7 @@ const Composer = RestModel.extend({
|
||||
|
||||
const props = {
|
||||
raw: this.get("reply"),
|
||||
raw_old: this.get("editConflict") ? null : this.get("originalText"),
|
||||
edit_reason: opts.editReason,
|
||||
image_sizes: opts.imageSizes,
|
||||
cooked: this.getCookedHtml()
|
||||
@ -760,9 +776,12 @@ const Composer = RestModel.extend({
|
||||
|
||||
this.set("composeState", SAVING);
|
||||
|
||||
let rollback = throwAjaxError(() => {
|
||||
let rollback = throwAjaxError(error => {
|
||||
post.set("cooked", oldCooked);
|
||||
this.set("composeState", OPEN);
|
||||
if (error.jqXHR && error.jqXHR.status === 409) {
|
||||
this.set("editConflict", true);
|
||||
}
|
||||
});
|
||||
|
||||
return promise
|
||||
@ -1041,6 +1060,7 @@ Composer.reopenClass({
|
||||
SAVING,
|
||||
OPEN,
|
||||
DRAFT,
|
||||
FULLSCREEN,
|
||||
|
||||
// The actions the composer can take
|
||||
CREATE_TOPIC,
|
||||
|
||||
@ -41,6 +41,10 @@ export default Discourse.Route.extend({
|
||||
showTagGroups() {
|
||||
this.transitionTo("tagGroups");
|
||||
return true;
|
||||
},
|
||||
|
||||
refresh() {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<label class="btn" disabled={{uploading}} title="{{i18n 'user.change_avatar.upload_title'}}">
|
||||
{{d-icon "picture-o"}} {{uploadButtonText}}
|
||||
<input disabled={{uploading}} type="file" accept="image/*" style="visibility: hidden; position: absolute;" />
|
||||
<input class="hidden-upload-field" disabled={{uploading}} type="file" accept="image/*" />
|
||||
</label>
|
||||
{{#if uploading}}
|
||||
<span>{{i18n 'upload_selector.uploading'}} {{uploadProgress}}%</span>
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
<label class="btn" disabled={{uploading}} title="{{i18n 'admin.backups.upload.title'}}">
|
||||
{{d-icon "upload"}} {{uploadButtonText}}
|
||||
<input class="hidden-upload-field" disabled={{uploading}} type="file" accept=".gz" />
|
||||
</label>
|
||||
@ -1,5 +1,5 @@
|
||||
{{#if selected}}
|
||||
<div id='bulk-select'>
|
||||
{{d-button action="showBulkActions" icon="wrench"}}
|
||||
{{d-button class="btn-default" action="showBulkActions" icon="wrench"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
@ -1,35 +1,38 @@
|
||||
{{#each categories as |c|}}
|
||||
<div class='category-box category-box-{{unbound c.slug}}' style={{border-color c.color}} data-url={{c.url}}>
|
||||
<div class='category-box-inner'>
|
||||
<div class='category-box-heading'>
|
||||
<div class="category-logo">
|
||||
{{#if c.uploaded_logo.url}}
|
||||
{{cdn-img src=c.uploaded_logo.url class="logo"}}
|
||||
{{/if}}
|
||||
|
||||
<h3>
|
||||
{{#if c.read_restricted}}
|
||||
{{d-icon 'lock'}}
|
||||
{{/if}}
|
||||
{{c.name}}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class='description'>
|
||||
{{{text-overflow class="overflow" text=c.description_excerpt}}}
|
||||
</div>
|
||||
|
||||
{{#if c.subcategories}}
|
||||
<div class='subcategories'>
|
||||
{{#each c.subcategories as |sc|}}
|
||||
<a class="subcategory" href={{sc.url}}>
|
||||
<span class="subcategory-image-placeholder">
|
||||
{{cdn-img src=sc.uploaded_logo.url class="logo"}}
|
||||
</span>
|
||||
<span class="subcategory-link">{{sc.name}}</span>
|
||||
</a>
|
||||
{{/each}}
|
||||
<div class="category-details">
|
||||
<div class='category-box-heading'>
|
||||
<h3>
|
||||
{{#if c.read_restricted}}
|
||||
{{d-icon 'lock'}}
|
||||
{{/if}}
|
||||
{{c.name}}
|
||||
</h3>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class='description'>
|
||||
{{{text-overflow class="overflow" text=c.description_excerpt}}}
|
||||
</div>
|
||||
|
||||
{{#if c.subcategories}}
|
||||
<div class='subcategories'>
|
||||
{{#each c.subcategories as |sc|}}
|
||||
<a class="subcategory" href={{sc.url}}>
|
||||
<span class="subcategory-image-placeholder">
|
||||
{{cdn-img src=sc.uploaded_logo.url class="logo"}}
|
||||
</span>
|
||||
<span class="subcategory-link">{{sc.name}}</span>
|
||||
</a>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
{{latest-topic-list-item topic=t}}
|
||||
{{/each}}
|
||||
<div class="more-topics">
|
||||
<a href="/{{filter}}" class="btn pull-right">{{i18n "more"}}</a>
|
||||
<a href="/{{filter}}" class="btn btn-default pull-right">{{i18n "more"}}</a>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class='no-topics'>
|
||||
|
||||
@ -10,5 +10,13 @@
|
||||
class="toggler"
|
||||
icon=toggleIcon
|
||||
action=toggleComposer
|
||||
title=title}}
|
||||
title=toggleTitle}}
|
||||
|
||||
{{#unless site.mobileView}}
|
||||
{{flat-button
|
||||
class="toggle-fullscreen"
|
||||
icon=fullscreenIcon
|
||||
action=toggleFullscreen
|
||||
title=fullscreenTitle}}
|
||||
{{/unless}}
|
||||
</div>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<label class="btn" disabled={{uploadButtonDisabled}}>
|
||||
{{d-icon "upload"}} {{uploadButtonText}}
|
||||
<input disabled={{uploading}} type="file" accept=".csv" style="visibility: hidden; position: absolute;" />
|
||||
<input class="hidden-upload-field" disabled={{uploading}} type="file" accept=".csv" />
|
||||
</label>
|
||||
{{#if uploading}}
|
||||
<span>{{i18n 'upload_selector.uploading'}} {{uploadProgress}}%</span>
|
||||
|
||||
@ -45,9 +45,7 @@
|
||||
</div>
|
||||
|
||||
<div class="d-editor-preview-wrapper {{if forcePreview 'force-preview'}}">
|
||||
<div class="d-editor-preview">
|
||||
{{{preview}}}
|
||||
</div>
|
||||
<div class="d-editor-preview">{{{preview}}}</div>
|
||||
{{plugin-outlet name="editor-preview" classNames="d-editor-plugin"}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
{{#if isNotSupported}}
|
||||
{{d-button icon="bell-slash" label="user.desktop_notifications.not_supported" disabled="true"}}
|
||||
{{d-button icon="bell-slash" class="btn-default" label="user.desktop_notifications.not_supported" disabled="true"}}
|
||||
{{/if}}
|
||||
{{#if isDeniedPermission}}
|
||||
{{d-button icon="bell-slash" label="user.desktop_notifications.perm_denied_btn" action="recheckPermission" disabled='true'}}
|
||||
{{d-button icon="bell-slash" class="btn-default" label="user.desktop_notifications.perm_denied_btn" action="recheckPermission" disabled='true'}}
|
||||
{{i18n "user.desktop_notifications.perm_denied_expl"}}
|
||||
{{else}}
|
||||
{{#if isEnabled}}
|
||||
{{d-button icon="bell-slash-o" label="user.desktop_notifications.disable" action="turnoff"}}
|
||||
{{d-button icon="bell-slash-o" class="btn-default" label="user.desktop_notifications.disable" action="turnoff"}}
|
||||
{{i18n "user.desktop_notifications.currently_enabled"}}
|
||||
{{else}}
|
||||
{{d-button icon="bell-o" label="user.desktop_notifications.enable" action="turnon"}}
|
||||
{{d-button icon="bell-o" class="btn-default" label="user.desktop_notifications.enable" action="turnon"}}
|
||||
{{i18n "user.desktop_notifications.currently_disabled"}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{#unless category.is_special}}
|
||||
<button {{action "editPermissions"}} class="btn btn-small edit-permission">{{i18n 'category.edit_permissions'}}</button>
|
||||
<button {{action "editPermissions"}} class="btn btn-default btn-small edit-permission">{{i18n 'category.edit_permissions'}}</button>
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
</section>
|
||||
|
||||
@ -2,5 +2,5 @@
|
||||
<label class="btn btn-primary {{if addDisabled 'disabled'}}">
|
||||
{{d-icon "plus"}}
|
||||
{{i18n 'admin.emoji.add'}}
|
||||
<input disabled={{addDisabled}} type="file" accept=".png,.gif" style="visibility: hidden; position: absolute;" />
|
||||
<input class="hidden-upload-field" disabled={{addDisabled}} type="file" accept=".png,.gif" />
|
||||
</label>
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
input=input
|
||||
includeWeekend=includeWeekend
|
||||
includeFarFuture=includeFarFuture
|
||||
clearable=clearable
|
||||
none="topic.auto_update_input.none"}}
|
||||
</div>
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
<div class="uploaded-image-preview input-xxlarge" style={{backgroundStyle}}>
|
||||
<div class="image-upload-controls">
|
||||
<label class="btn pad-left no-text {{if uploading 'disabled'}}">
|
||||
<label class="btn btn-default pad-left no-text {{if uploading 'disabled'}}">
|
||||
{{d-icon "picture-o"}}
|
||||
<input disabled={{uploading}} type="file" accept="image/*" style="visibility: hidden; position: absolute;" />
|
||||
<input class="hidden-upload-field" disabled={{uploading}} type="file" accept="image/*" />
|
||||
</label>
|
||||
{{#if backgroundStyle}}
|
||||
<button {{action "trash"}} class="btn btn-danger pad-left no-text">{{d-icon "trash-o"}}</button>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user