Version bump
This commit is contained in:
commit
aa6d9e74d3
@ -1,11 +1,9 @@
|
||||
app/assets/javascripts/env.js
|
||||
app/assets/javascripts/main_include.js
|
||||
app/assets/javascripts/main_include_admin.js
|
||||
app/assets/javascripts/preload_store.js
|
||||
app/assets/javascripts/pagedown_custom.js
|
||||
app/assets/javascripts/vendor.js
|
||||
app/assets/javascripts/locales/i18n.js
|
||||
app/assets/javascripts/defer/html-sanitizer-bundle.js
|
||||
app/assets/javascripts/ember-addons/
|
||||
app/assets/javascripts/discourse/lib/autosize.js.es6
|
||||
lib/javascripts/locale/
|
||||
|
||||
@ -14,7 +14,6 @@
|
||||
"RSVP":true,
|
||||
"Discourse":true,
|
||||
"Em":true,
|
||||
"PreloadStore":true,
|
||||
"Handlebars":true,
|
||||
"I18n":true,
|
||||
"bootbox":true,
|
||||
@ -77,6 +76,7 @@
|
||||
"no-eval": 2,
|
||||
"no-extend-native": 2,
|
||||
"no-extra-parens": 0,
|
||||
"no-inner-declarations": 2,
|
||||
"no-irregular-whitespace": 2,
|
||||
"no-iterator": 2,
|
||||
"no-loop-func": 2,
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -46,6 +46,7 @@ log/
|
||||
!/plugins/lazyYT/
|
||||
!/plugins/poll/
|
||||
!/plugins/discourse-details/
|
||||
!/plugins/discourse-nginx-performance-report
|
||||
/plugins/*/auto_generated/
|
||||
|
||||
/spec/fixtures/plugins/my_plugin/auto_generated
|
||||
|
||||
82
Gemfile.lock
82
Gemfile.lock
@ -1,38 +1,38 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actionmailer (4.2.6)
|
||||
actionpack (= 4.2.6)
|
||||
actionview (= 4.2.6)
|
||||
activejob (= 4.2.6)
|
||||
actionmailer (4.2.7)
|
||||
actionpack (= 4.2.7)
|
||||
actionview (= 4.2.7)
|
||||
activejob (= 4.2.7)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
actionpack (4.2.6)
|
||||
actionview (= 4.2.6)
|
||||
activesupport (= 4.2.6)
|
||||
actionpack (4.2.7)
|
||||
actionview (= 4.2.7)
|
||||
activesupport (= 4.2.7)
|
||||
rack (~> 1.6)
|
||||
rack-test (~> 0.6.2)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
actionview (4.2.6)
|
||||
activesupport (= 4.2.6)
|
||||
actionview (4.2.7)
|
||||
activesupport (= 4.2.7)
|
||||
builder (~> 3.1)
|
||||
erubis (~> 2.7.0)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
active_model_serializers (0.8.3)
|
||||
activemodel (>= 3.0)
|
||||
activejob (4.2.6)
|
||||
activesupport (= 4.2.6)
|
||||
activejob (4.2.7)
|
||||
activesupport (= 4.2.7)
|
||||
globalid (>= 0.3.0)
|
||||
activemodel (4.2.6)
|
||||
activesupport (= 4.2.6)
|
||||
activemodel (4.2.7)
|
||||
activesupport (= 4.2.7)
|
||||
builder (~> 3.1)
|
||||
activerecord (4.2.6)
|
||||
activemodel (= 4.2.6)
|
||||
activesupport (= 4.2.6)
|
||||
activerecord (4.2.7)
|
||||
activemodel (= 4.2.7)
|
||||
activesupport (= 4.2.7)
|
||||
arel (~> 6.0)
|
||||
activesupport (4.2.6)
|
||||
activesupport (4.2.7)
|
||||
i18n (~> 0.7)
|
||||
json (~> 1.7, >= 1.7.7)
|
||||
minitest (~> 5.1)
|
||||
@ -42,12 +42,12 @@ GEM
|
||||
activerecord (>= 3.2, < 6.0)
|
||||
rake (>= 10.4, < 12.0)
|
||||
arel (6.0.3)
|
||||
aws-sdk (2.3.7)
|
||||
aws-sdk-resources (= 2.3.7)
|
||||
aws-sdk-core (2.3.7)
|
||||
aws-sdk (2.3.22)
|
||||
aws-sdk-resources (= 2.3.22)
|
||||
aws-sdk-core (2.3.22)
|
||||
jmespath (~> 1.0)
|
||||
aws-sdk-resources (2.3.7)
|
||||
aws-sdk-core (= 2.3.7)
|
||||
aws-sdk-resources (2.3.22)
|
||||
aws-sdk-core (= 2.3.22)
|
||||
babel-source (5.8.34)
|
||||
babel-transpiler (0.7.0)
|
||||
babel-source (>= 4.0, < 6)
|
||||
@ -136,14 +136,12 @@ GEM
|
||||
progress (~> 3.0, >= 3.0.1)
|
||||
image_size (1.4.1)
|
||||
in_threads (1.3.1)
|
||||
jmespath (1.2.4)
|
||||
json_pure (>= 1.8.1)
|
||||
jmespath (1.3.0)
|
||||
jquery-rails (4.0.5)
|
||||
rails-dom-testing (~> 1.0)
|
||||
railties (>= 4.2.0)
|
||||
thor (>= 0.14, < 2.0)
|
||||
json (1.8.3)
|
||||
json_pure (1.8.3)
|
||||
jwt (1.5.2)
|
||||
kgio (2.10.0)
|
||||
librarian (0.1.2)
|
||||
@ -162,7 +160,7 @@ GEM
|
||||
rack (>= 1.1.3)
|
||||
metaclass (0.0.4)
|
||||
method_source (0.8.2)
|
||||
mime-types (2.99.1)
|
||||
mime-types (2.99.2)
|
||||
mini_portile2 (2.1.0)
|
||||
mini_racer (0.1.3)
|
||||
libv8 (~> 5.0)
|
||||
@ -218,7 +216,7 @@ GEM
|
||||
omniauth-twitter (1.2.1)
|
||||
json (~> 1.3)
|
||||
omniauth-oauth (~> 1.1)
|
||||
onebox (1.5.42)
|
||||
onebox (1.5.43)
|
||||
htmlentities (~> 4.3.4)
|
||||
moneta (~> 0.8)
|
||||
multi_json (~> 1.11)
|
||||
@ -250,16 +248,16 @@ GEM
|
||||
rack
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rails (4.2.6)
|
||||
actionmailer (= 4.2.6)
|
||||
actionpack (= 4.2.6)
|
||||
actionview (= 4.2.6)
|
||||
activejob (= 4.2.6)
|
||||
activemodel (= 4.2.6)
|
||||
activerecord (= 4.2.6)
|
||||
activesupport (= 4.2.6)
|
||||
rails (4.2.7)
|
||||
actionmailer (= 4.2.7)
|
||||
actionpack (= 4.2.7)
|
||||
actionview (= 4.2.7)
|
||||
activejob (= 4.2.7)
|
||||
activemodel (= 4.2.7)
|
||||
activerecord (= 4.2.7)
|
||||
activesupport (= 4.2.7)
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 4.2.6)
|
||||
railties (= 4.2.7)
|
||||
sprockets-rails
|
||||
rails-deprecated_sanitizer (1.0.3)
|
||||
activesupport (>= 4.2.0.alpha)
|
||||
@ -272,13 +270,13 @@ GEM
|
||||
rails-observers (0.1.2)
|
||||
activemodel (~> 4.0)
|
||||
rails_multisite (1.0.4)
|
||||
railties (4.2.6)
|
||||
actionpack (= 4.2.6)
|
||||
activesupport (= 4.2.6)
|
||||
railties (4.2.7)
|
||||
actionpack (= 4.2.7)
|
||||
activesupport (= 4.2.7)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
raindrops (0.16.0)
|
||||
rake (11.1.2)
|
||||
rake (11.2.2)
|
||||
rake-compiler (0.9.9)
|
||||
rake
|
||||
rb-fsevent (0.9.7)
|
||||
@ -371,10 +369,10 @@ GEM
|
||||
spork-rails (4.0.0)
|
||||
rails (>= 3.0.0, < 5)
|
||||
spork (>= 1.0rc0)
|
||||
sprockets (3.6.0)
|
||||
sprockets (3.6.3)
|
||||
concurrent-ruby (~> 1.0)
|
||||
rack (> 1, < 3)
|
||||
sprockets-rails (3.0.4)
|
||||
sprockets-rails (3.1.1)
|
||||
actionpack (>= 4.0)
|
||||
activesupport (>= 4.0)
|
||||
sprockets (>= 3.0.0)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/* global ace:true */
|
||||
import loadScript from 'discourse/lib/load-script';
|
||||
import { escapeExpression } from 'discourse/lib/utilities';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
mode: 'css',
|
||||
@ -16,7 +17,7 @@ export default Ember.Component.extend({
|
||||
render(buffer) {
|
||||
buffer.push("<div class='ace'>");
|
||||
if (this.get('content')) {
|
||||
buffer.push(Discourse.Utilities.escapeExpression(this.get('content')));
|
||||
buffer.push(escapeExpression(this.get('content')));
|
||||
}
|
||||
buffer.push("</div>");
|
||||
},
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
classNames: ["ip-lookup"],
|
||||
@ -23,7 +24,7 @@ export default Ember.Component.extend({
|
||||
this.set("show", true);
|
||||
|
||||
if (!this.get("location")) {
|
||||
Discourse.ajax("/admin/users/ip-info", {
|
||||
ajax("/admin/users/ip-info", {
|
||||
data: { ip: this.get("ip") }
|
||||
}).then(function (location) {
|
||||
self.set("location", Em.Object.create(location));
|
||||
@ -39,7 +40,7 @@ export default Ember.Component.extend({
|
||||
"order": "trust_level DESC"
|
||||
};
|
||||
|
||||
Discourse.ajax("/admin/users/total-others-with-same-ip", { data }).then(function (result) {
|
||||
ajax("/admin/users/total-others-with-same-ip", { data }).then(function (result) {
|
||||
self.set("totalOthersWithSameIP", result.total);
|
||||
});
|
||||
|
||||
@ -67,7 +68,7 @@ export default Ember.Component.extend({
|
||||
totalOthersWithSameIP: null
|
||||
});
|
||||
|
||||
Discourse.ajax("/admin/users/delete-others-with-same-ip.json", {
|
||||
ajax("/admin/users/delete-others-with-same-ip.json", {
|
||||
type: "DELETE",
|
||||
data: {
|
||||
"ip": self.get("ip"),
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
export default Ember.ArrayController.extend({
|
||||
needs: ["adminBackups"],
|
||||
status: Ember.computed.alias("controllers.adminBackups"),
|
||||
@ -39,7 +40,7 @@ export default Ember.ArrayController.extend({
|
||||
|
||||
_toggleReadOnlyMode(enable) {
|
||||
var site = this.site;
|
||||
Discourse.ajax("/admin/backups/readonly", {
|
||||
ajax("/admin/backups/readonly", {
|
||||
type: "PUT",
|
||||
data: { enable: enable }
|
||||
}).then(function() {
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
export default Ember.Controller.extend({
|
||||
|
||||
/**
|
||||
@ -29,7 +30,7 @@ export default Ember.Controller.extend({
|
||||
});
|
||||
|
||||
var self = this;
|
||||
Discourse.ajax("/admin/email/test", {
|
||||
ajax("/admin/email/test", {
|
||||
type: 'POST',
|
||||
data: { email_address: this.get('testEmailAddress') }
|
||||
}).then(function () {
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
export default Ember.ArrayController.extend({
|
||||
sortProperties: ["name"],
|
||||
|
||||
@ -15,7 +16,7 @@ export default Ember.ArrayController.extend({
|
||||
I18n.t("yes_value"),
|
||||
function(destroy) {
|
||||
if (destroy) {
|
||||
return Discourse.ajax("/admin/customize/emojis/" + emoji.get("name"), { type: "DELETE" }).then(function() {
|
||||
return ajax("/admin/customize/emojis/" + emoji.get("name"), { type: "DELETE" }).then(function() {
|
||||
self.removeObject(emoji);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
||||
|
||||
@ -20,7 +21,7 @@ export default Ember.Controller.extend({
|
||||
.reject(x => x.length === 0);
|
||||
|
||||
this.set('saving', true);
|
||||
Discourse.ajax('/admin/groups/bulk', {
|
||||
ajax('/admin/groups/bulk', {
|
||||
data: { users, group_id: this.get('groupId') },
|
||||
method: 'PUT'
|
||||
}).then(() => {
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
export default Ember.ArrayController.extend({
|
||||
sortProperties: ['name'],
|
||||
refreshingAutoGroups: false,
|
||||
@ -9,7 +10,7 @@ export default Ember.ArrayController.extend({
|
||||
refreshAutoGroups: function(){
|
||||
var self = this;
|
||||
this.set('refreshingAutoGroups', true);
|
||||
Discourse.ajax('/admin/groups/refresh_automatic_groups', {type: 'POST'}).then(function() {
|
||||
ajax('/admin/groups/refresh_automatic_groups', {type: 'POST'}).then(function() {
|
||||
self.transitionToRoute("adminGroupsType", "automatic").then(function() {
|
||||
self.set('refreshingAutoGroups', false);
|
||||
});
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import CanCheckEmails from 'discourse/mixins/can-check-emails';
|
||||
import { propertyNotEqual, setting } from 'discourse/lib/computed';
|
||||
|
||||
@ -38,7 +39,7 @@ export default Ember.Controller.extend(CanCheckEmails, {
|
||||
saveTitle() {
|
||||
const self = this;
|
||||
|
||||
return Discourse.ajax("/users/" + this.get('model.username').toLowerCase(), {
|
||||
return ajax("/users/" + this.get('model.username').toLowerCase(), {
|
||||
data: {title: this.get('userTitleValue')},
|
||||
type: 'PUT'
|
||||
}).catch(function(e) {
|
||||
@ -68,7 +69,7 @@ export default Ember.Controller.extend(CanCheckEmails, {
|
||||
savePrimaryGroup() {
|
||||
const self = this;
|
||||
|
||||
return Discourse.ajax("/admin/users/" + this.get('model.id') + "/primary_group", {
|
||||
return ajax("/admin/users/" + this.get('model.id') + "/primary_group", {
|
||||
type: 'PUT',
|
||||
data: {primary_group_id: this.get('model.primary_group_id')}
|
||||
}).then(function () {
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { escapeExpression } from 'discourse/lib/utilities';
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
needs: ['modal'],
|
||||
|
||||
@ -22,7 +24,7 @@ export default Ember.Controller.extend({
|
||||
returned = "<pre class='badge-query-plan'>";
|
||||
|
||||
_.each(raw, function(linehash) {
|
||||
returned += Discourse.Utilities.escapeExpression(linehash["QUERY PLAN"]);
|
||||
returned += escapeExpression(linehash["QUERY PLAN"]);
|
||||
returned += "<br>";
|
||||
});
|
||||
|
||||
@ -32,7 +34,7 @@ export default Ember.Controller.extend({
|
||||
|
||||
processed_sample: Ember.computed.map('model.sample', function(grant) {
|
||||
var i18nKey = 'admin.badges.preview.grant.with',
|
||||
i18nParams = { username: Discourse.Utilities.escapeExpression(grant.username) };
|
||||
i18nParams = { username: escapeExpression(grant.username) };
|
||||
|
||||
if (grant.post_id) {
|
||||
i18nKey += "_post";
|
||||
@ -41,7 +43,7 @@ export default Ember.Controller.extend({
|
||||
|
||||
if (grant.granted_at) {
|
||||
i18nKey += "_time";
|
||||
i18nParams.time = Discourse.Utilities.escapeExpression(moment(grant.granted_at).format(I18n.t('dates.long_with_year')));
|
||||
i18nParams.time = escapeExpression(moment(grant.granted_at).format(I18n.t('dates.long_with_year')));
|
||||
}
|
||||
|
||||
return I18n.t(i18nKey, i18nParams);
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
export default Ember.Controller.extend({
|
||||
needs: ['modal'],
|
||||
|
||||
@ -57,7 +58,7 @@ export default Ember.Controller.extend({
|
||||
const groupIds = items.map(function(i){return i.get("id") || -1;});
|
||||
const names = items.map(function(i){return i.get("name");});
|
||||
|
||||
Discourse.ajax('/admin/badges/badge_groupings',{
|
||||
ajax('/admin/badges/badge_groupings',{
|
||||
data: {ids: groupIds, names: names},
|
||||
method: 'POST'
|
||||
}).then(function(data){
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { htmlHelper } from 'discourse/lib/helpers';
|
||||
import { escapeExpression } from 'discourse/lib/utilities';
|
||||
|
||||
export default htmlHelper(str => Discourse.Utilities.escapeExpression(str).replace(/\n/g, "<br>"));
|
||||
export default htmlHelper(str => escapeExpression(str).replace(/\n/g, "<br>"));
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
|
||||
const AdminDashboard = Discourse.Model.extend({});
|
||||
|
||||
@ -11,7 +12,7 @@ AdminDashboard.reopenClass({
|
||||
@return {jqXHR} a jQuery Promise object
|
||||
**/
|
||||
find: function() {
|
||||
return Discourse.ajax("/admin/dashboard.json").then(function(json) {
|
||||
return ajax("/admin/dashboard.json").then(function(json) {
|
||||
var model = AdminDashboard.create(json);
|
||||
model.set('loaded', true);
|
||||
return model;
|
||||
@ -26,7 +27,7 @@ AdminDashboard.reopenClass({
|
||||
@return {jqXHR} a jQuery Promise object
|
||||
**/
|
||||
fetchProblems: function() {
|
||||
return Discourse.ajax("/admin/dashboard/problems.json", {
|
||||
return ajax("/admin/dashboard/problems.json", {
|
||||
type: 'GET',
|
||||
dataType: 'json'
|
||||
}).then(function(json) {
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
import { propertyNotEqual } from 'discourse/lib/computed';
|
||||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
||||
@ -40,7 +41,7 @@ const AdminUser = Discourse.User.extend({
|
||||
canResetBounceScore: Ember.computed.gt("bounce_score", 0),
|
||||
|
||||
resetBounceScore() {
|
||||
return Discourse.ajax(`/admin/users/${this.get("id")}/reset_bounce_score`, {
|
||||
return ajax(`/admin/users/${this.get("id")}/reset_bounce_score`, {
|
||||
type: 'POST'
|
||||
}).then(() => this.setProperties({
|
||||
"bounce_score": 0,
|
||||
@ -50,7 +51,7 @@ const AdminUser = Discourse.User.extend({
|
||||
|
||||
generateApiKey() {
|
||||
const self = this;
|
||||
return Discourse.ajax("/admin/users/" + this.get('id') + "/generate_api_key", {
|
||||
return ajax("/admin/users/" + this.get('id') + "/generate_api_key", {
|
||||
type: 'POST'
|
||||
}).then(function (result) {
|
||||
const apiKey = ApiKey.create(result.api_key);
|
||||
@ -60,20 +61,20 @@ const AdminUser = Discourse.User.extend({
|
||||
},
|
||||
|
||||
groupAdded(added) {
|
||||
return Discourse.ajax("/admin/users/" + this.get('id') + "/groups", {
|
||||
return ajax("/admin/users/" + this.get('id') + "/groups", {
|
||||
type: 'POST',
|
||||
data: { group_id: added.id }
|
||||
}).then(() => this.get('groups').pushObject(added));
|
||||
},
|
||||
|
||||
groupRemoved(groupId) {
|
||||
return Discourse.ajax("/admin/users/" + this.get('id') + "/groups/" + groupId, {
|
||||
return ajax("/admin/users/" + this.get('id') + "/groups/" + groupId, {
|
||||
type: 'DELETE'
|
||||
}).then(() => this.set('groups.[]', this.get('groups').rejectBy("id", groupId)));
|
||||
},
|
||||
|
||||
revokeApiKey() {
|
||||
return Discourse.ajax("/admin/users/" + this.get('id') + "/revoke_api_key", {
|
||||
return ajax("/admin/users/" + this.get('id') + "/revoke_api_key", {
|
||||
type: 'DELETE'
|
||||
}).then(() => this.set('api_key', null));
|
||||
},
|
||||
@ -104,7 +105,7 @@ const AdminUser = Discourse.User.extend({
|
||||
"label": '<i class="fa fa-exclamation-triangle"></i> ' + I18n.t("admin.user.delete_all_posts"),
|
||||
"class": "btn btn-danger",
|
||||
"callback": function() {
|
||||
Discourse.ajax("/admin/users/" + user.get('id') + "/delete_all_posts", {
|
||||
ajax("/admin/users/" + user.get('id') + "/delete_all_posts", {
|
||||
type: 'PUT'
|
||||
}).then(() => user.set('post_count', 0));
|
||||
}
|
||||
@ -114,7 +115,7 @@ const AdminUser = Discourse.User.extend({
|
||||
|
||||
revokeAdmin() {
|
||||
const self = this;
|
||||
return Discourse.ajax("/admin/users/" + this.get('id') + "/revoke_admin", {
|
||||
return ajax("/admin/users/" + this.get('id') + "/revoke_admin", {
|
||||
type: 'PUT'
|
||||
}).then(function() {
|
||||
self.setProperties({
|
||||
@ -127,7 +128,7 @@ const AdminUser = Discourse.User.extend({
|
||||
|
||||
grantAdmin() {
|
||||
const self = this;
|
||||
return Discourse.ajax("/admin/users/" + this.get('id') + "/grant_admin", {
|
||||
return ajax("/admin/users/" + this.get('id') + "/grant_admin", {
|
||||
type: 'PUT'
|
||||
}).then(function() {
|
||||
self.setProperties({
|
||||
@ -140,7 +141,7 @@ const AdminUser = Discourse.User.extend({
|
||||
|
||||
revokeModeration() {
|
||||
const self = this;
|
||||
return Discourse.ajax("/admin/users/" + this.get('id') + "/revoke_moderation", {
|
||||
return ajax("/admin/users/" + this.get('id') + "/revoke_moderation", {
|
||||
type: 'PUT'
|
||||
}).then(function() {
|
||||
self.setProperties({
|
||||
@ -153,7 +154,7 @@ const AdminUser = Discourse.User.extend({
|
||||
|
||||
grantModeration() {
|
||||
const self = this;
|
||||
return Discourse.ajax("/admin/users/" + this.get('id') + "/grant_moderation", {
|
||||
return ajax("/admin/users/" + this.get('id') + "/grant_moderation", {
|
||||
type: 'PUT'
|
||||
}).then(function() {
|
||||
self.setProperties({
|
||||
@ -165,14 +166,14 @@ const AdminUser = Discourse.User.extend({
|
||||
},
|
||||
|
||||
refreshBrowsers() {
|
||||
return Discourse.ajax("/admin/users/" + this.get('id') + "/refresh_browsers", {
|
||||
return ajax("/admin/users/" + this.get('id') + "/refresh_browsers", {
|
||||
type: 'POST'
|
||||
}).finally(() => bootbox.alert(I18n.t("admin.user.refresh_browsers_message")));
|
||||
},
|
||||
|
||||
approve() {
|
||||
const self = this;
|
||||
return Discourse.ajax("/admin/users/" + this.get('id') + "/approve", {
|
||||
return ajax("/admin/users/" + this.get('id') + "/approve", {
|
||||
type: 'PUT'
|
||||
}).then(function() {
|
||||
self.setProperties({
|
||||
@ -190,7 +191,7 @@ const AdminUser = Discourse.User.extend({
|
||||
dirty: propertyNotEqual('originalTrustLevel', 'trustLevel.id'),
|
||||
|
||||
saveTrustLevel() {
|
||||
return Discourse.ajax("/admin/users/" + this.id + "/trust_level", {
|
||||
return ajax("/admin/users/" + this.id + "/trust_level", {
|
||||
type: 'PUT',
|
||||
data: { level: this.get('trustLevel.id') }
|
||||
}).then(function() {
|
||||
@ -210,7 +211,7 @@ const AdminUser = Discourse.User.extend({
|
||||
},
|
||||
|
||||
lockTrustLevel(locked) {
|
||||
return Discourse.ajax("/admin/users/" + this.id + "/trust_level_lock", {
|
||||
return ajax("/admin/users/" + this.id + "/trust_level_lock", {
|
||||
type: 'PUT',
|
||||
data: { locked: !!locked }
|
||||
}).then(function() {
|
||||
@ -239,14 +240,14 @@ const AdminUser = Discourse.User.extend({
|
||||
}.property('suspended_till', 'suspended_at'),
|
||||
|
||||
suspend(duration, reason) {
|
||||
return Discourse.ajax("/admin/users/" + this.id + "/suspend", {
|
||||
return ajax("/admin/users/" + this.id + "/suspend", {
|
||||
type: 'PUT',
|
||||
data: { duration: duration, reason: reason }
|
||||
});
|
||||
},
|
||||
|
||||
unsuspend() {
|
||||
return Discourse.ajax("/admin/users/" + this.id + "/unsuspend", {
|
||||
return ajax("/admin/users/" + this.id + "/unsuspend", {
|
||||
type: 'PUT'
|
||||
}).then(function() {
|
||||
window.location.reload();
|
||||
@ -257,7 +258,7 @@ const AdminUser = Discourse.User.extend({
|
||||
},
|
||||
|
||||
log_out() {
|
||||
return Discourse.ajax("/admin/users/" + this.id + "/log_out", {
|
||||
return ajax("/admin/users/" + this.id + "/log_out", {
|
||||
type: 'POST',
|
||||
data: { username_or_email: this.get('username') }
|
||||
}).then(function() {
|
||||
@ -266,7 +267,7 @@ const AdminUser = Discourse.User.extend({
|
||||
},
|
||||
|
||||
impersonate() {
|
||||
return Discourse.ajax("/admin/impersonate", {
|
||||
return ajax("/admin/impersonate", {
|
||||
type: 'POST',
|
||||
data: { username_or_email: this.get('username') }
|
||||
}).then(function() {
|
||||
@ -281,7 +282,7 @@ const AdminUser = Discourse.User.extend({
|
||||
},
|
||||
|
||||
activate() {
|
||||
return Discourse.ajax('/admin/users/' + this.id + '/activate', {
|
||||
return ajax('/admin/users/' + this.id + '/activate', {
|
||||
type: 'PUT'
|
||||
}).then(function() {
|
||||
window.location.reload();
|
||||
@ -292,7 +293,7 @@ const AdminUser = Discourse.User.extend({
|
||||
},
|
||||
|
||||
deactivate() {
|
||||
return Discourse.ajax('/admin/users/' + this.id + '/deactivate', {
|
||||
return ajax('/admin/users/' + this.id + '/deactivate', {
|
||||
type: 'PUT'
|
||||
}).then(function() {
|
||||
window.location.reload();
|
||||
@ -304,7 +305,7 @@ const AdminUser = Discourse.User.extend({
|
||||
|
||||
unblock() {
|
||||
this.set('blockingUser', true);
|
||||
return Discourse.ajax('/admin/users/' + this.id + '/unblock', {
|
||||
return ajax('/admin/users/' + this.id + '/unblock', {
|
||||
type: 'PUT'
|
||||
}).then(function() {
|
||||
window.location.reload();
|
||||
@ -320,7 +321,7 @@ const AdminUser = Discourse.User.extend({
|
||||
|
||||
const performBlock = function() {
|
||||
user.set('blockingUser', true);
|
||||
return Discourse.ajax('/admin/users/' + user.id + '/block', {
|
||||
return ajax('/admin/users/' + user.id + '/block', {
|
||||
type: 'PUT'
|
||||
}).then(function() {
|
||||
window.location.reload();
|
||||
@ -345,7 +346,7 @@ const AdminUser = Discourse.User.extend({
|
||||
},
|
||||
|
||||
sendActivationEmail() {
|
||||
return Discourse.ajax('/users/action/send_activation_email', {
|
||||
return ajax('/users/action/send_activation_email', {
|
||||
type: 'POST',
|
||||
data: { username: this.get('username') }
|
||||
}).then(function() {
|
||||
@ -360,7 +361,7 @@ const AdminUser = Discourse.User.extend({
|
||||
message = I18n.t("admin.user.anonymize_confirm");
|
||||
|
||||
const performAnonymize = function() {
|
||||
return Discourse.ajax("/admin/users/" + user.get('id') + '/anonymize.json', {
|
||||
return ajax("/admin/users/" + user.get('id') + '/anonymize.json', {
|
||||
type: 'PUT'
|
||||
}).then(function(data) {
|
||||
if (data.success) {
|
||||
@ -422,7 +423,7 @@ const AdminUser = Discourse.User.extend({
|
||||
if (opts && opts.deletePosts) {
|
||||
formData["delete_posts"] = true;
|
||||
}
|
||||
return Discourse.ajax("/admin/users/" + user.get('id') + '.json', {
|
||||
return ajax("/admin/users/" + user.get('id') + '.json', {
|
||||
type: 'DELETE',
|
||||
data: formData
|
||||
}).then(function(data) {
|
||||
@ -481,7 +482,7 @@ const AdminUser = Discourse.User.extend({
|
||||
"label": '<i class="fa fa-exclamation-triangle"></i> ' + I18n.t("flagging.yes_delete_spammer"),
|
||||
"class": "btn btn-danger",
|
||||
"callback": function() {
|
||||
return Discourse.ajax("/admin/users/" + user.get('id') + '.json', {
|
||||
return ajax("/admin/users/" + user.get('id') + '.json', {
|
||||
type: 'DELETE',
|
||||
data: {
|
||||
delete_posts: true,
|
||||
@ -549,7 +550,7 @@ AdminUser.reopenClass({
|
||||
});
|
||||
});
|
||||
|
||||
return Discourse.ajax("/admin/users/approve-bulk", {
|
||||
return ajax("/admin/users/approve-bulk", {
|
||||
type: 'PUT',
|
||||
data: { users: users.map((u) => u.id) }
|
||||
}).finally(() => bootbox.alert(I18n.t("admin.user.approve_bulk_success")));
|
||||
@ -561,7 +562,7 @@ AdminUser.reopenClass({
|
||||
user.set('selected', false);
|
||||
});
|
||||
|
||||
return Discourse.ajax("/admin/users/reject-bulk", {
|
||||
return ajax("/admin/users/reject-bulk", {
|
||||
type: 'DELETE',
|
||||
data: {
|
||||
users: users.map((u) => u.id),
|
||||
@ -571,14 +572,14 @@ AdminUser.reopenClass({
|
||||
},
|
||||
|
||||
find(user_id) {
|
||||
return Discourse.ajax("/admin/users/" + user_id + ".json").then(result => {
|
||||
return ajax("/admin/users/" + user_id + ".json").then(result => {
|
||||
result.loadedDetails = true;
|
||||
return AdminUser.create(result);
|
||||
});
|
||||
},
|
||||
|
||||
findAll(query, filter) {
|
||||
return Discourse.ajax("/admin/users/list/" + query + ".json", {
|
||||
return ajax("/admin/users/list/" + query + ".json", {
|
||||
data: filter
|
||||
}).then(function(users) {
|
||||
return users.map((u) => AdminUser.create(u));
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
const ApiKey = Discourse.Model.extend({
|
||||
|
||||
/**
|
||||
@ -8,7 +9,7 @@ const ApiKey = Discourse.Model.extend({
|
||||
**/
|
||||
regenerate: function() {
|
||||
var self = this;
|
||||
return Discourse.ajax('/admin/api/key', {type: 'PUT', data: {id: this.get('id')}}).then(function (result) {
|
||||
return ajax('/admin/api/key', {type: 'PUT', data: {id: this.get('id')}}).then(function (result) {
|
||||
self.set('key', result.api_key.key);
|
||||
return self;
|
||||
});
|
||||
@ -21,7 +22,7 @@ const ApiKey = Discourse.Model.extend({
|
||||
@returns {Promise} a promise that resolves when the key has been revoked
|
||||
**/
|
||||
revoke: function() {
|
||||
return Discourse.ajax('/admin/api/key', {type: 'DELETE', data: {id: this.get('id')}});
|
||||
return ajax('/admin/api/key', {type: 'DELETE', data: {id: this.get('id')}});
|
||||
}
|
||||
|
||||
});
|
||||
@ -51,7 +52,7 @@ ApiKey.reopenClass({
|
||||
@returns {Promise} a promise that resolves to the array of `ApiKey` instances
|
||||
**/
|
||||
find: function() {
|
||||
return Discourse.ajax("/admin/api").then(function(keys) {
|
||||
return ajax("/admin/api").then(function(keys) {
|
||||
return keys.map(function (key) {
|
||||
return ApiKey.create(key);
|
||||
});
|
||||
@ -65,7 +66,7 @@ ApiKey.reopenClass({
|
||||
@returns {Promise} a promise that resolves to a master `ApiKey`
|
||||
**/
|
||||
generateMasterKey: function() {
|
||||
return Discourse.ajax("/admin/api/key", {type: 'POST'}).then(function (result) {
|
||||
return ajax("/admin/api/key", {type: 'POST'}).then(function (result) {
|
||||
return ApiKey.create(result.api_key);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import PreloadStore from 'preload-store';
|
||||
|
||||
const Backup = Discourse.Model.extend({
|
||||
|
||||
destroy() {
|
||||
return Discourse.ajax("/admin/backups/" + this.get("filename"), { type: "DELETE" });
|
||||
return ajax("/admin/backups/" + this.get("filename"), { type: "DELETE" });
|
||||
},
|
||||
|
||||
restore() {
|
||||
return Discourse.ajax("/admin/backups/" + this.get("filename") + "/restore", {
|
||||
return ajax("/admin/backups/" + this.get("filename") + "/restore", {
|
||||
type: "POST",
|
||||
data: { client_id: window.MessageBus.clientId }
|
||||
});
|
||||
@ -16,13 +19,13 @@ const Backup = Discourse.Model.extend({
|
||||
Backup.reopenClass({
|
||||
|
||||
find() {
|
||||
return PreloadStore.getAndRemove("backups", () => Discourse.ajax("/admin/backups.json"))
|
||||
return PreloadStore.getAndRemove("backups", () => ajax("/admin/backups.json"))
|
||||
.then(backups => backups.map(backup => Backup.create(backup)));
|
||||
},
|
||||
|
||||
start(withUploads) {
|
||||
if (withUploads === undefined) { withUploads = true; }
|
||||
return Discourse.ajax("/admin/backups", {
|
||||
return ajax("/admin/backups", {
|
||||
type: "POST",
|
||||
data: {
|
||||
with_uploads: withUploads,
|
||||
@ -34,14 +37,14 @@ Backup.reopenClass({
|
||||
},
|
||||
|
||||
cancel() {
|
||||
return Discourse.ajax("/admin/backups/cancel.json")
|
||||
return ajax("/admin/backups/cancel.json")
|
||||
.then(result => {
|
||||
if (!result.success) { bootbox.alert(result.message); }
|
||||
});
|
||||
},
|
||||
|
||||
rollback() {
|
||||
return Discourse.ajax("/admin/backups/rollback.json")
|
||||
return ajax("/admin/backups/rollback.json")
|
||||
.then(result => {
|
||||
if (!result.success) {
|
||||
bootbox.alert(result.message);
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import ColorSchemeColor from 'admin/models/color-scheme-color';
|
||||
|
||||
const ColorScheme = Discourse.Model.extend(Ember.Copyable, {
|
||||
@ -65,7 +66,7 @@ const ColorScheme = Discourse.Model.extend(Ember.Copyable, {
|
||||
});
|
||||
}
|
||||
|
||||
return Discourse.ajax("/admin/color_schemes" + (this.id ? '/' + this.id : '') + '.json', {
|
||||
return ajax("/admin/color_schemes" + (this.id ? '/' + this.id : '') + '.json', {
|
||||
data: JSON.stringify({"color_scheme": data}),
|
||||
type: this.id ? 'PUT' : 'POST',
|
||||
dataType: 'json',
|
||||
@ -88,7 +89,7 @@ const ColorScheme = Discourse.Model.extend(Ember.Copyable, {
|
||||
|
||||
destroy: function() {
|
||||
if (this.id) {
|
||||
return Discourse.ajax("/admin/color_schemes/" + this.id, { type: 'DELETE' });
|
||||
return ajax("/admin/color_schemes/" + this.id, { type: 'DELETE' });
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,7 +107,7 @@ var ColorSchemes = Ember.ArrayProxy.extend({
|
||||
ColorScheme.reopenClass({
|
||||
findAll: function() {
|
||||
var colorSchemes = ColorSchemes.create({ content: [], loading: true });
|
||||
Discourse.ajax('/admin/color_schemes').then(function(all) {
|
||||
ajax('/admin/color_schemes').then(function(all) {
|
||||
_.each(all, function(colorScheme){
|
||||
colorSchemes.pushObject(ColorScheme.create({
|
||||
id: colorScheme.id,
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import AdminUser from 'admin/models/admin-user';
|
||||
|
||||
const EmailLog = Discourse.Model.extend({});
|
||||
@ -21,7 +22,7 @@ EmailLog.reopenClass({
|
||||
const status = filter.status || "sent";
|
||||
filter = _.omit(filter, "status");
|
||||
|
||||
return Discourse.ajax(`/admin/email/${status}.json?offset=${offset}`, { data: filter })
|
||||
return ajax(`/admin/email/${status}.json?offset=${offset}`, { data: filter })
|
||||
.then(logs => _.map(logs, log => EmailLog.create(log)));
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
const EmailPreview = Discourse.Model.extend({});
|
||||
|
||||
EmailPreview.reopenClass({
|
||||
@ -11,7 +12,7 @@ EmailPreview.reopenClass({
|
||||
username = Discourse.User.current().username;
|
||||
}
|
||||
|
||||
return Discourse.ajax("/admin/email/preview-digest.json", {
|
||||
return ajax("/admin/email/preview-digest.json", {
|
||||
data: { last_seen_at: lastSeenAt, username: username }
|
||||
}).then(function (result) {
|
||||
return EmailPreview.create(result);
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
const EmailSettings = Discourse.Model.extend({});
|
||||
|
||||
EmailSettings.reopenClass({
|
||||
find: function() {
|
||||
return Discourse.ajax("/admin/email.json").then(function (settings) {
|
||||
return ajax("/admin/email.json").then(function (settings) {
|
||||
return EmailSettings.create(settings);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import RestModel from 'discourse/models/rest';
|
||||
const { getProperties } = Ember;
|
||||
|
||||
export default RestModel.extend({
|
||||
revert() {
|
||||
return Discourse.ajax(`/admin/customize/email_templates/${this.get('id')}`, {
|
||||
return ajax(`/admin/customize/email_templates/${this.get('id')}`, {
|
||||
method: 'DELETE'
|
||||
}).then(result => getProperties(result.email_template, 'subject', 'body', 'can_revert'));
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import AdminUser from 'admin/models/admin-user';
|
||||
import Topic from 'discourse/models/topic';
|
||||
import Post from 'discourse/models/post';
|
||||
@ -106,22 +107,22 @@ const FlaggedPost = Post.extend({
|
||||
|
||||
deletePost: function() {
|
||||
if (this.get('post_number') === 1) {
|
||||
return Discourse.ajax('/t/' + this.topic_id, { type: 'DELETE', cache: false });
|
||||
return ajax('/t/' + this.topic_id, { type: 'DELETE', cache: false });
|
||||
} else {
|
||||
return Discourse.ajax('/posts/' + this.id, { type: 'DELETE', cache: false });
|
||||
return ajax('/posts/' + this.id, { type: 'DELETE', cache: false });
|
||||
}
|
||||
},
|
||||
|
||||
disagreeFlags: function () {
|
||||
return Discourse.ajax('/admin/flags/disagree/' + this.id, { type: 'POST', cache: false });
|
||||
return ajax('/admin/flags/disagree/' + this.id, { type: 'POST', cache: false });
|
||||
},
|
||||
|
||||
deferFlags: function (deletePost) {
|
||||
return Discourse.ajax('/admin/flags/defer/' + this.id, { type: 'POST', cache: false, data: { delete_post: deletePost } });
|
||||
return ajax('/admin/flags/defer/' + this.id, { type: 'POST', cache: false, data: { delete_post: deletePost } });
|
||||
},
|
||||
|
||||
agreeFlags: function (actionOnPost) {
|
||||
return Discourse.ajax('/admin/flags/agree/' + this.id, { type: 'POST', cache: false, data: { action_on_post: actionOnPost } });
|
||||
return ajax('/admin/flags/agree/' + this.id, { type: 'POST', cache: false, data: { action_on_post: actionOnPost } });
|
||||
},
|
||||
|
||||
postHidden: Em.computed.alias('hidden'),
|
||||
@ -144,7 +145,7 @@ FlaggedPost.reopenClass({
|
||||
var result = Em.A();
|
||||
result.set('loading', true);
|
||||
|
||||
return Discourse.ajax('/admin/flags/' + filter + '.json?offset=' + offset).then(function (data) {
|
||||
return ajax('/admin/flags/' + filter + '.json?offset=' + offset).then(function (data) {
|
||||
// users
|
||||
var userLookup = {};
|
||||
_.each(data.users, function (user) {
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import AdminUser from 'admin/models/admin-user';
|
||||
|
||||
const IncomingEmail = Discourse.Model.extend({});
|
||||
@ -15,7 +16,7 @@ IncomingEmail.reopenClass({
|
||||
},
|
||||
|
||||
find(id) {
|
||||
return Discourse.ajax(`/admin/email/incoming/${id}.json`);
|
||||
return ajax(`/admin/email/incoming/${id}.json`);
|
||||
},
|
||||
|
||||
findAll(filter, offset) {
|
||||
@ -25,12 +26,12 @@ IncomingEmail.reopenClass({
|
||||
const status = filter.status || "received";
|
||||
filter = _.omit(filter, "status");
|
||||
|
||||
return Discourse.ajax(`/admin/email/${status}.json?offset=${offset}`, { data: filter })
|
||||
return ajax(`/admin/email/${status}.json?offset=${offset}`, { data: filter })
|
||||
.then(incomings => _.map(incomings, incoming => IncomingEmail.create(incoming)));
|
||||
},
|
||||
|
||||
loadRawEmail(id) {
|
||||
return Discourse.ajax(`/admin/email/incoming/${id}/raw.json`);
|
||||
return ajax(`/admin/email/incoming/${id}/raw.json`);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -1,19 +1,20 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
const Permalink = Discourse.Model.extend({
|
||||
save: function() {
|
||||
return Discourse.ajax("/admin/permalinks.json", {
|
||||
return ajax("/admin/permalinks.json", {
|
||||
type: 'POST',
|
||||
data: {url: this.get('url'), permalink_type: this.get('permalink_type'), permalink_type_value: this.get('permalink_type_value')}
|
||||
});
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
return Discourse.ajax("/admin/permalinks/" + this.get('id') + ".json", {type: 'DELETE'});
|
||||
return ajax("/admin/permalinks/" + this.get('id') + ".json", {type: 'DELETE'});
|
||||
}
|
||||
});
|
||||
|
||||
Permalink.reopenClass({
|
||||
findAll: function(filter) {
|
||||
return Discourse.ajax("/admin/permalinks.json", { data: { filter: filter } }).then(function(permalinks) {
|
||||
return ajax("/admin/permalinks.json", { data: { filter: filter } }).then(function(permalinks) {
|
||||
return permalinks.map(p => Permalink.create(p));
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import round from "discourse/lib/round";
|
||||
import { fmt } from 'discourse/lib/computed';
|
||||
|
||||
@ -132,7 +133,7 @@ const Report = Discourse.Model.extend({
|
||||
Report.reopenClass({
|
||||
|
||||
find(type, startDate, endDate, categoryId, groupId) {
|
||||
return Discourse.ajax("/admin/reports/" + type, {
|
||||
return ajax("/admin/reports/" + type, {
|
||||
data: {
|
||||
start_date: startDate,
|
||||
end_date: endDate,
|
||||
|
||||
@ -1,16 +1,17 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
const ScreenedEmail = Discourse.Model.extend({
|
||||
actionName: function() {
|
||||
return I18n.t("admin.logs.screened_actions." + this.get('action'));
|
||||
}.property('action'),
|
||||
|
||||
clearBlock: function() {
|
||||
return Discourse.ajax('/admin/logs/screened_emails/' + this.get('id'), {method: 'DELETE'});
|
||||
return ajax('/admin/logs/screened_emails/' + this.get('id'), {method: 'DELETE'});
|
||||
}
|
||||
});
|
||||
|
||||
ScreenedEmail.reopenClass({
|
||||
findAll: function() {
|
||||
return Discourse.ajax("/admin/logs/screened_emails.json").then(function(screened_emails) {
|
||||
return ajax("/admin/logs/screened_emails.json").then(function(screened_emails) {
|
||||
return screened_emails.map(function(b) {
|
||||
return ScreenedEmail.create(b);
|
||||
});
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
const ScreenedIpAddress = Discourse.Model.extend({
|
||||
@ -14,25 +15,25 @@ const ScreenedIpAddress = Discourse.Model.extend({
|
||||
},
|
||||
|
||||
save() {
|
||||
return Discourse.ajax("/admin/logs/screened_ip_addresses" + (this.id ? '/' + this.id : '') + ".json", {
|
||||
return ajax("/admin/logs/screened_ip_addresses" + (this.id ? '/' + this.id : '') + ".json", {
|
||||
type: this.id ? 'PUT' : 'POST',
|
||||
data: {ip_address: this.get('ip_address'), action_name: this.get('action_name')}
|
||||
});
|
||||
},
|
||||
|
||||
destroy() {
|
||||
return Discourse.ajax("/admin/logs/screened_ip_addresses/" + this.get('id') + ".json", {type: 'DELETE'});
|
||||
return ajax("/admin/logs/screened_ip_addresses/" + this.get('id') + ".json", {type: 'DELETE'});
|
||||
}
|
||||
});
|
||||
|
||||
ScreenedIpAddress.reopenClass({
|
||||
findAll(filter) {
|
||||
return Discourse.ajax("/admin/logs/screened_ip_addresses.json", { data: { filter: filter } })
|
||||
return ajax("/admin/logs/screened_ip_addresses.json", { data: { filter: filter } })
|
||||
.then(screened_ips => screened_ips.map(b => ScreenedIpAddress.create(b)));
|
||||
},
|
||||
|
||||
rollUp() {
|
||||
return Discourse.ajax("/admin/logs/screened_ip_addresses/roll_up", { type: "POST" });
|
||||
return ajax("/admin/logs/screened_ip_addresses/roll_up", { type: "POST" });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
const ScreenedUrl = Discourse.Model.extend({
|
||||
actionName: function() {
|
||||
return I18n.t("admin.logs.screened_actions." + this.get('action'));
|
||||
@ -6,7 +7,7 @@ const ScreenedUrl = Discourse.Model.extend({
|
||||
|
||||
ScreenedUrl.reopenClass({
|
||||
findAll: function() {
|
||||
return Discourse.ajax("/admin/logs/screened_urls.json").then(function(screened_urls) {
|
||||
return ajax("/admin/logs/screened_urls.json").then(function(screened_urls) {
|
||||
return screened_urls.map(function(b) {
|
||||
return ScreenedUrl.create(b);
|
||||
});
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
const SiteSetting = Discourse.Model.extend({
|
||||
overridden: function() {
|
||||
let val = this.get('value'),
|
||||
@ -28,7 +29,7 @@ const SiteSetting = Discourse.Model.extend({
|
||||
|
||||
SiteSetting.reopenClass({
|
||||
findAll() {
|
||||
return Discourse.ajax("/admin/site_settings").then(function (settings) {
|
||||
return ajax("/admin/site_settings").then(function (settings) {
|
||||
// Group the results by category
|
||||
const categories = {};
|
||||
settings.site_settings.forEach(function(s) {
|
||||
@ -47,7 +48,7 @@ SiteSetting.reopenClass({
|
||||
update(key, value) {
|
||||
const data = {};
|
||||
data[key] = value;
|
||||
return Discourse.ajax("/admin/site_settings/" + key, { type: 'PUT', data });
|
||||
return ajax("/admin/site_settings/" + key, { type: 'PUT', data });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import RestModel from 'discourse/models/rest';
|
||||
const { getProperties } = Ember;
|
||||
|
||||
export default RestModel.extend({
|
||||
revert() {
|
||||
return Discourse.ajax(`/admin/customize/site_texts/${this.get('id')}`, {
|
||||
return ajax(`/admin/customize/site_texts/${this.get('id')}`, {
|
||||
method: 'DELETE'
|
||||
}).then(result => getProperties(result.site_text, 'value', 'can_revert'));
|
||||
}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import AdminUser from 'admin/models/admin-user';
|
||||
import { escapeExpression } from 'discourse/lib/utilities';
|
||||
|
||||
const StaffActionLog = Discourse.Model.extend({
|
||||
showFullDetails: false,
|
||||
@ -19,14 +21,14 @@ const StaffActionLog = Discourse.Model.extend({
|
||||
formatted += this.format('admin.logs.staff_actions.previous_value', 'previous_value');
|
||||
}
|
||||
if (!this.get('useModalForDetails')) {
|
||||
if (this.get('details')) formatted += Discourse.Utilities.escapeExpression(this.get('details')) + '<br/>';
|
||||
if (this.get('details')) formatted += escapeExpression(this.get('details')) + '<br/>';
|
||||
}
|
||||
return formatted;
|
||||
}.property('ip_address', 'email', 'topic_id', 'post_id', 'category_id'),
|
||||
|
||||
format: function(label, propertyName) {
|
||||
if (this.get(propertyName)) {
|
||||
return ('<b>' + I18n.t(label) + ':</b> ' + Discourse.Utilities.escapeExpression(this.get(propertyName)) + '<br/>');
|
||||
return ('<b>' + I18n.t(label) + ':</b> ' + escapeExpression(this.get(propertyName)) + '<br/>');
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
@ -55,7 +57,7 @@ StaffActionLog.reopenClass({
|
||||
},
|
||||
|
||||
findAll: function(filters) {
|
||||
return Discourse.ajax("/admin/logs/staff_action_logs.json", { data: filters }).then(function(staff_actions) {
|
||||
return ajax("/admin/logs/staff_action_logs.json", { data: filters }).then(function(staff_actions) {
|
||||
return staff_actions.map(function(s) {
|
||||
return StaffActionLog.create(s);
|
||||
});
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
const VersionCheck = Discourse.Model.extend({
|
||||
|
||||
noCheckPerformed: function() {
|
||||
@ -33,7 +34,7 @@ const VersionCheck = Discourse.Model.extend({
|
||||
|
||||
VersionCheck.reopenClass({
|
||||
find: function() {
|
||||
return Discourse.ajax('/admin/version_check').then(function(json) {
|
||||
return ajax('/admin/version_check').then(function(json) {
|
||||
return VersionCheck.create(json);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import PreloadStore from 'preload-store';
|
||||
|
||||
export default Ember.Route.extend({
|
||||
|
||||
// since the logs are pushed via the message bus
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import showModal from 'discourse/lib/show-modal';
|
||||
import BackupStatus from 'admin/models/backup-status';
|
||||
import Backup from 'admin/models/backup';
|
||||
import PreloadStore from 'preload-store';
|
||||
|
||||
const LOG_CHANNEL = "/admin/backups/logs";
|
||||
|
||||
@ -31,7 +33,7 @@ export default Discourse.Route.extend({
|
||||
|
||||
model() {
|
||||
return PreloadStore.getAndRemove("operations_status", function() {
|
||||
return Discourse.ajax("/admin/backups/status.json");
|
||||
return ajax("/admin/backups/status.json");
|
||||
}).then(status => {
|
||||
return BackupStatus.create({
|
||||
isOperationRunning: status.is_operation_running,
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import Badge from 'discourse/models/badge';
|
||||
import showModal from 'discourse/lib/show-modal';
|
||||
|
||||
@ -31,7 +32,7 @@ export default Ember.Route.extend({
|
||||
|
||||
preview(badge, explain) {
|
||||
badge.set('preview_loading', true);
|
||||
Discourse.ajax('/admin/badges/preview.json', {
|
||||
ajax('/admin/badges/preview.json', {
|
||||
method: 'post',
|
||||
data: {
|
||||
sql: badge.get('query'),
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import Badge from 'discourse/models/badge';
|
||||
import BadgeGrouping from 'discourse/models/badge-grouping';
|
||||
|
||||
@ -6,7 +7,7 @@ export default Discourse.Route.extend({
|
||||
|
||||
model: function() {
|
||||
var self = this;
|
||||
return Discourse.ajax('/admin/badges.json').then(function(json) {
|
||||
return ajax('/admin/badges.json').then(function(json) {
|
||||
self._json = json;
|
||||
return Badge.createFromJson(json);
|
||||
});
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
export default Discourse.Route.extend({
|
||||
model: function() {
|
||||
return Discourse.ajax("/admin/customize/emojis.json").then(function(emojis) {
|
||||
return ajax("/admin/customize/emojis.json").then(function(emojis) {
|
||||
return emojis.map(function (emoji) { return Ember.Object.create(emoji); });
|
||||
});
|
||||
}
|
||||
|
||||
@ -2,26 +2,23 @@ import Group from 'discourse/models/group';
|
||||
|
||||
export default Discourse.Route.extend({
|
||||
|
||||
model: function(params) {
|
||||
var groups = this.modelFor('adminGroupsType');
|
||||
model(params) {
|
||||
if (params.name === 'new') {
|
||||
return Group.create({
|
||||
automatic: false,
|
||||
visible: true
|
||||
});
|
||||
return Group.create({ automatic: false, visible: true });
|
||||
}
|
||||
|
||||
var group = groups.findProperty('name', params.name);
|
||||
const group = this.modelFor('adminGroupsType')
|
||||
.findProperty('name', params.name);
|
||||
|
||||
if (!group) { return this.transitionTo('adminGroups.index'); }
|
||||
|
||||
return group;
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
setupController(controller, model) {
|
||||
controller.set("model", model);
|
||||
controller.set("model.usernames", null);
|
||||
controller.set("savingStatus", '');
|
||||
controller.set("savingStatus", "");
|
||||
model.findMembers();
|
||||
}
|
||||
|
||||
|
||||
@ -94,10 +94,10 @@
|
||||
</div>
|
||||
|
||||
{{#if siteSettings.email_in}}
|
||||
<div>
|
||||
{{#plugin-outlet "group-email-in"}}
|
||||
<label for="incoming_email">{{i18n 'admin.groups.incoming_email'}}</label>
|
||||
{{text-field name="incoming_email" value=model.incoming_email placeholderKey="admin.groups.incoming_email_placeholder"}}
|
||||
</div>
|
||||
{{/plugin-outlet}}
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import debounce from 'discourse/lib/debounce';
|
||||
import { renderSpinner } from 'discourse/helpers/loading-spinner';
|
||||
import { escapeExpression } from 'discourse/lib/utilities';
|
||||
|
||||
export default Ember.View.extend({
|
||||
classNames: ["admin-backups-logs"],
|
||||
@ -19,7 +20,7 @@ export default Ember.View.extend({
|
||||
let formattedLogs = this.get("formattedLogs");
|
||||
for (let i = this.get("index"), length = logs.length; i < length; i++) {
|
||||
const date = logs[i].get("timestamp"),
|
||||
message = Discourse.Utilities.escapeExpression(logs[i].get("message"));
|
||||
message = escapeExpression(logs[i].get("message"));
|
||||
formattedLogs += "[" + date + "] " + message + "\n";
|
||||
}
|
||||
// update the formatted logs & cache index
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
31
app/assets/javascripts/deprecated.js
Normal file
31
app/assets/javascripts/deprecated.js
Normal file
@ -0,0 +1,31 @@
|
||||
(function() {
|
||||
var Discourse = require('discourse').default;
|
||||
|
||||
function deprecate(module, methods) {
|
||||
const result = {};
|
||||
|
||||
methods.forEach(function(m) {
|
||||
result[m] = function() {
|
||||
Ember.warn("Discourse." + module + "." + m + " is deprecated. Export a setup() function instead");
|
||||
};
|
||||
});
|
||||
|
||||
Discourse[module] = result;
|
||||
}
|
||||
|
||||
deprecate('Markdown', ['whiteListTag', 'whiteListIframe']);
|
||||
deprecate('Dialect', ['inlineRegexp', 'inlineBetween', 'addPreProcessor', 'replaceBlock',
|
||||
'inlineReplace', 'registerInline', 'registerEmoji']);
|
||||
|
||||
deprecate('BBCode', ['replaceBBCode', 'register', 'rawBBCode', 'replaceBBCodeParamsRaw']);
|
||||
|
||||
Discourse.dialect_deprecated = true;
|
||||
|
||||
Discourse.ajax = function() {
|
||||
var ajax = require('discourse/lib/ajax').ajax;
|
||||
Ember.warn("Discourse.ajax is deprecated. Import the module and use it instead");
|
||||
return ajax.apply(this, arguments);
|
||||
};
|
||||
|
||||
window.Discourse = Discourse;
|
||||
})();
|
||||
@ -1,19 +1,14 @@
|
||||
/*global Favcount:true*/
|
||||
var DiscourseResolver = require('discourse/ember/resolver').default;
|
||||
import DiscourseResolver from 'discourse/ember/resolver';
|
||||
import { default as computed, observes } from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
// Allow us to import Ember
|
||||
define('ember', ['exports'], function(__exports__) {
|
||||
__exports__.default = Ember;
|
||||
});
|
||||
const _pluginCallbacks = [];
|
||||
|
||||
var _pluginCallbacks = [];
|
||||
|
||||
window.Discourse = Ember.Application.extend(Discourse.Ajax, {
|
||||
const Discourse = Ember.Application.extend({
|
||||
rootElement: '#main',
|
||||
_docTitle: document.title,
|
||||
__TAGS_INCLUDED__: true,
|
||||
|
||||
getURL: function(url) {
|
||||
getURL(url) {
|
||||
if (!url) return url;
|
||||
|
||||
// if it's a non relative URL, return it.
|
||||
@ -25,8 +20,8 @@ window.Discourse = Ember.Application.extend(Discourse.Ajax, {
|
||||
return Discourse.BaseUri + url;
|
||||
},
|
||||
|
||||
getURLWithCDN: function(url) {
|
||||
url = this.getURL(url);
|
||||
getURLWithCDN(url) {
|
||||
url = Discourse.getURL(url);
|
||||
// only relative urls
|
||||
if (Discourse.CDN && /^\/[^\/]/.test(url)) {
|
||||
url = Discourse.CDN + url;
|
||||
@ -38,78 +33,76 @@ window.Discourse = Ember.Application.extend(Discourse.Ajax, {
|
||||
|
||||
Resolver: DiscourseResolver,
|
||||
|
||||
_titleChanged: function() {
|
||||
var title = this.get('_docTitle') || Discourse.SiteSettings.title;
|
||||
@observes('_docTitle', 'hasFocus', 'notifyCount')
|
||||
_titleChanged() {
|
||||
let title = this.get('_docTitle') || Discourse.SiteSettings.title;
|
||||
|
||||
// if we change this we can trigger changes on document.title
|
||||
// only set if changed.
|
||||
if($('title').text() !== title) {
|
||||
if ($('title').text() !== title) {
|
||||
$('title').text(title);
|
||||
}
|
||||
|
||||
var notifyCount = this.get('notifyCount');
|
||||
const notifyCount = this.get('notifyCount');
|
||||
if (notifyCount > 0 && !Discourse.User.currentProp('dynamic_favicon')) {
|
||||
title = "(" + notifyCount + ") " + title;
|
||||
title = `(${notifyCount}) ${title}`;
|
||||
}
|
||||
|
||||
document.title = title;
|
||||
}.observes('_docTitle', 'hasFocus', 'notifyCount'),
|
||||
},
|
||||
|
||||
faviconChanged: function() {
|
||||
if(Discourse.User.currentProp('dynamic_favicon')) {
|
||||
var url = Discourse.SiteSettings.favicon_url;
|
||||
@observes('notifyCount')
|
||||
faviconChanged() {
|
||||
if (Discourse.User.currentProp('dynamic_favicon')) {
|
||||
let url = Discourse.SiteSettings.favicon_url;
|
||||
if (/^http/.test(url)) {
|
||||
url = Discourse.getURL("/favicon/proxied?" + encodeURIComponent(url));
|
||||
}
|
||||
new Favcount(url).set(
|
||||
this.get('notifyCount')
|
||||
);
|
||||
new window.Favcount(url).set(this.get('notifyCount'));
|
||||
}
|
||||
}.observes('notifyCount'),
|
||||
},
|
||||
|
||||
// The classes of buttons to show on a post
|
||||
postButtons: function() {
|
||||
@computed
|
||||
postButtons() {
|
||||
return Discourse.SiteSettings.post_menu.split("|").map(function(i) {
|
||||
return i.replace(/\+/, '').capitalize();
|
||||
});
|
||||
}.property(),
|
||||
},
|
||||
|
||||
notifyTitle: function(count) {
|
||||
notifyTitle(count) {
|
||||
this.set('notifyCount', count);
|
||||
},
|
||||
|
||||
notifyBackgroundCountIncrement: function() {
|
||||
notifyBackgroundCountIncrement() {
|
||||
if (!this.get('hasFocus')) {
|
||||
this.set('backgroundNotify', true);
|
||||
this.set('notifyCount', (this.get('notifyCount') || 0) + 1);
|
||||
}
|
||||
},
|
||||
|
||||
resetBackgroundNotifyCount: function() {
|
||||
@observes('hasFocus')
|
||||
resetBackgroundNotifyCount() {
|
||||
if (this.get('hasFocus') && this.get('backgroundNotify')) {
|
||||
this.set('notifyCount', 0);
|
||||
}
|
||||
this.set('backgroundNotify', false);
|
||||
}.observes('hasFocus'),
|
||||
},
|
||||
|
||||
authenticationComplete: function(options) {
|
||||
authenticationComplete(options) {
|
||||
// TODO, how to dispatch this to the controller without the container?
|
||||
var loginController = Discourse.__container__.lookup('controller:login');
|
||||
const loginController = Discourse.__container__.lookup('controller:login');
|
||||
return loginController.authenticationComplete(options);
|
||||
},
|
||||
|
||||
/**
|
||||
Start up the Discourse application by running all the initializers we've defined.
|
||||
|
||||
@method start
|
||||
**/
|
||||
start: function() {
|
||||
// Start up the Discourse application by running all the initializers we've defined.
|
||||
start() {
|
||||
|
||||
$('noscript').remove();
|
||||
|
||||
Object.keys(requirejs._eak_seen).forEach(function(key) {
|
||||
if (/\/pre\-initializers\//.test(key)) {
|
||||
var module = require(key, null, null, true);
|
||||
const module = require(key, null, null, true);
|
||||
if (!module) { throw new Error(key + ' must export an initializer.'); }
|
||||
Discourse.initializer(module.default);
|
||||
}
|
||||
@ -117,11 +110,11 @@ window.Discourse = Ember.Application.extend(Discourse.Ajax, {
|
||||
|
||||
Object.keys(requirejs._eak_seen).forEach(function(key) {
|
||||
if (/\/initializers\//.test(key)) {
|
||||
var module = require(key, null, null, true);
|
||||
const module = require(key, null, null, true);
|
||||
if (!module) { throw new Error(key + ' must export an initializer.'); }
|
||||
|
||||
var init = module.default;
|
||||
var oldInitialize = init.initialize;
|
||||
const init = module.default;
|
||||
const oldInitialize = init.initialize;
|
||||
init.initialize = function(app) {
|
||||
oldInitialize.call(this, app.container, Discourse);
|
||||
};
|
||||
@ -131,8 +124,8 @@ window.Discourse = Ember.Application.extend(Discourse.Ajax, {
|
||||
});
|
||||
|
||||
// Plugins that are registered via `<script>` tags.
|
||||
var withPluginApi = require('discourse/lib/plugin-api').withPluginApi;
|
||||
var initCount = 0;
|
||||
const withPluginApi = require('discourse/lib/plugin-api').withPluginApi;
|
||||
let initCount = 0;
|
||||
_pluginCallbacks.forEach(function(cb) {
|
||||
Discourse.instanceInitializer({
|
||||
name: "_discourse_plugin_" + (++initCount),
|
||||
@ -142,22 +135,31 @@ window.Discourse = Ember.Application.extend(Discourse.Ajax, {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const utils = require('discourse/lib/utilities');
|
||||
Discourse.Utilities = {};
|
||||
Object.keys(utils).forEach(function(k) {
|
||||
Discourse.Utilities[k] = function() {
|
||||
Ember.warn('Discourse.Utilities is deprecated. Import it as a module');
|
||||
return utils[k].apply(utils, arguments);
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
requiresRefresh: function(){
|
||||
var desired = Discourse.get("desiredAssetVersion");
|
||||
return desired && Discourse.get("currentAssetVersion") !== desired;
|
||||
}.property("currentAssetVersion", "desiredAssetVersion"),
|
||||
@computed('currentAssetVersion', 'desiredAssetVersion')
|
||||
requiresRefresh(currentAssetVersion, desiredAssetVersion) {
|
||||
return desiredAssetVersion && currentAssetVersion !== desiredAssetVersion;
|
||||
},
|
||||
|
||||
_registerPluginCode: function(version, code) {
|
||||
_pluginCallbacks.push({ version: version, code: code });
|
||||
_registerPluginCode(version, code) {
|
||||
_pluginCallbacks.push({ version, code });
|
||||
},
|
||||
|
||||
assetVersion: Ember.computed({
|
||||
get: function() {
|
||||
get() {
|
||||
return this.get("currentAssetVersion");
|
||||
},
|
||||
set: function(key, val) {
|
||||
set(key, val) {
|
||||
if(val) {
|
||||
if (this.get("currentAssetVersion")) {
|
||||
this.set("desiredAssetVersion", val);
|
||||
@ -170,20 +172,4 @@ window.Discourse = Ember.Application.extend(Discourse.Ajax, {
|
||||
})
|
||||
}).create();
|
||||
|
||||
function RemovedObject(name) {
|
||||
this._removedName = name;
|
||||
}
|
||||
|
||||
function methodMissing() {
|
||||
console.warn("The " + this._removedName + " object has been removed from Discourse " +
|
||||
"and your plugin needs to be updated.");
|
||||
};
|
||||
|
||||
Discourse.RemovedObject = RemovedObject;
|
||||
|
||||
['reopen', 'registerButton', 'on', 'off'].forEach(function(m) { RemovedObject.prototype[m] = methodMissing; });
|
||||
|
||||
['discourse/views/post', 'discourse/components/post-menu'].forEach(function(moduleName) {
|
||||
define(moduleName, [], function() { return new RemovedObject(moduleName); });
|
||||
});
|
||||
|
||||
export default Discourse;
|
||||
@ -1,9 +1,10 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import RestAdapter from 'discourse/adapters/rest';
|
||||
|
||||
export default RestAdapter.extend({
|
||||
find(store, type, findArgs) {
|
||||
const maxReplies = Discourse.SiteSettings.max_reply_history;
|
||||
return Discourse.ajax(`/posts/${findArgs.postId}/reply-history?max_replies=${maxReplies}`).then(replies => {
|
||||
return ajax(`/posts/${findArgs.postId}/reply-history?max_replies=${maxReplies}`).then(replies => {
|
||||
return { post_reply_histories: replies };
|
||||
});
|
||||
},
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import RestAdapter from 'discourse/adapters/rest';
|
||||
|
||||
export default RestAdapter.extend({
|
||||
find(store, type, findArgs) {
|
||||
return Discourse.ajax(`/posts/${findArgs.postId}/replies`).then(replies => {
|
||||
return ajax(`/posts/${findArgs.postId}/replies`).then(replies => {
|
||||
return { post_replies: replies };
|
||||
});
|
||||
},
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import RestAdapter from 'discourse/adapters/rest';
|
||||
import { Result } from 'discourse/adapters/rest';
|
||||
|
||||
@ -12,7 +13,7 @@ export default RestAdapter.extend({
|
||||
createRecord(store, type, args) {
|
||||
const typeField = Ember.String.underscore(type);
|
||||
args.nested_post = true;
|
||||
return Discourse.ajax(this.pathFor(store, type), { method: 'POST', data: args }).then(function (json) {
|
||||
return ajax(this.pathFor(store, type), { method: 'POST', data: args }).then(function (json) {
|
||||
return new Result(json[typeField], json);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import { hashString } from 'discourse/lib/hash';
|
||||
|
||||
const ADMIN_MODELS = ['plugin', 'site-customization', 'embeddable-host'];
|
||||
@ -9,8 +10,6 @@ export function Result(payload, responseJson) {
|
||||
this.target = null;
|
||||
}
|
||||
|
||||
const ajax = Discourse.ajax;
|
||||
|
||||
// We use this to make sure 404s are caught
|
||||
function rethrow(error) {
|
||||
if (error.status === 404) {
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import RestAdapter from 'discourse/adapters/rest';
|
||||
import PreloadStore from 'preload-store';
|
||||
|
||||
export function finderFor(filter, params) {
|
||||
return function() {
|
||||
@ -19,7 +21,7 @@ export function finderFor(filter, params) {
|
||||
url += "?" + encoded.join('&');
|
||||
}
|
||||
}
|
||||
return Discourse.ajax(url);
|
||||
return ajax(url);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import RestAdapter from 'discourse/adapters/rest';
|
||||
|
||||
export default RestAdapter.extend({
|
||||
find(store, type, findArgs) {
|
||||
if (findArgs.similar) {
|
||||
return Discourse.ajax("/topics/similar_to", { data: findArgs.similar });
|
||||
return ajax("/topics/similar_to", { data: findArgs.similar });
|
||||
} else {
|
||||
return this._super(store, type, findArgs);
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
import DiscourseURL from 'discourse/lib/url';
|
||||
import { emojiUnescape } from 'discourse/lib/text';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
size: 'medium',
|
||||
@ -38,7 +39,7 @@ export default Ember.Component.extend({
|
||||
if (size === 'large') {
|
||||
const longDescription = this.get('badge.long_description');
|
||||
if (!_.isEmpty(longDescription)) {
|
||||
return Discourse.Emoji.unescape(longDescription);
|
||||
return emojiUnescape(longDescription);
|
||||
}
|
||||
}
|
||||
return this.get('badge.description');
|
||||
|
||||
@ -3,6 +3,14 @@ import { default as computed, on } from 'ember-addons/ember-computed-decorators'
|
||||
import { linkSeenMentions, fetchUnseenMentions } from 'discourse/lib/link-mentions';
|
||||
import { linkSeenCategoryHashtags, fetchUnseenCategoryHashtags } from 'discourse/lib/link-category-hashtags';
|
||||
import { fetchUnseenTagHashtags, linkSeenTagHashtags } from 'discourse/lib/link-tag-hashtag';
|
||||
import { load } from 'pretty-text/oneboxer';
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import InputValidation from 'discourse/models/input-validation';
|
||||
|
||||
import { tinyAvatar,
|
||||
displayErrorForUpload,
|
||||
getUploadMarkdown,
|
||||
validateUploadedFiles } from 'discourse/lib/utilities';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
classNames: ['wmd-controls'],
|
||||
@ -60,7 +68,7 @@ export default Ember.Component.extend({
|
||||
if (posts && topicId === topic.get('id')) {
|
||||
const quotedPost = posts.findProperty("post_number", postNumber);
|
||||
if (quotedPost) {
|
||||
return Discourse.Utilities.tinyAvatar(quotedPost.get('avatar_template'));
|
||||
return tinyAvatar(quotedPost.get('avatar_template'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -115,7 +123,7 @@ export default Ember.Component.extend({
|
||||
}
|
||||
|
||||
if (reason) {
|
||||
return Discourse.InputValidation.create({ failed: true, reason, lastShownAt: lastValidatedAt });
|
||||
return InputValidation.create({ failed: true, reason, lastShownAt: lastValidatedAt });
|
||||
}
|
||||
},
|
||||
|
||||
@ -181,7 +189,7 @@ export default Ember.Component.extend({
|
||||
this.setProperties({ uploadProgress: 0, isUploading: false, isCancellable: false });
|
||||
}
|
||||
if (removePlaceholder) {
|
||||
this.set('composer.reply', this.get('composer.reply').replace(this.get('uploadPlaceholder'), ""));
|
||||
this.appEvents.trigger('composer:replace-text', this.get('uploadPlaceholder'), "");
|
||||
}
|
||||
},
|
||||
|
||||
@ -199,7 +207,7 @@ export default Ember.Component.extend({
|
||||
});
|
||||
|
||||
$element.on('fileuploadsubmit', (e, data) => {
|
||||
const isUploading = Discourse.Utilities.validateUploadedFiles(data.files);
|
||||
const isUploading = validateUploadedFiles(data.files);
|
||||
data.formData = { type: "composer" };
|
||||
this.setProperties({ uploadProgress: 0, isUploading });
|
||||
return isUploading;
|
||||
@ -211,7 +219,6 @@ export default Ember.Component.extend({
|
||||
|
||||
$element.on("fileuploadsend", (e, data) => {
|
||||
this._validUploads++;
|
||||
// add upload placeholders
|
||||
this.appEvents.trigger('composer:insert-text', uploadPlaceholder);
|
||||
|
||||
if (data.xhr && data.originalFiles.length === 1) {
|
||||
@ -227,7 +234,7 @@ export default Ember.Component.extend({
|
||||
this._xhr = null;
|
||||
|
||||
if (!userCancelled) {
|
||||
Discourse.Utilities.displayErrorForUpload(data);
|
||||
displayErrorForUpload(data);
|
||||
}
|
||||
});
|
||||
|
||||
@ -235,15 +242,15 @@ export default Ember.Component.extend({
|
||||
// replace upload placeholder
|
||||
if (upload && upload.url) {
|
||||
if (!this._xhr || !this._xhr._userCancelled) {
|
||||
const markdown = Discourse.Utilities.getUploadMarkdown(upload);
|
||||
this.set('composer.reply', this.get('composer.reply').replace(uploadPlaceholder, markdown));
|
||||
const markdown = getUploadMarkdown(upload);
|
||||
this.appEvents.trigger('composer:replace-text', uploadPlaceholder, markdown);
|
||||
this._resetUpload(false);
|
||||
} else {
|
||||
this._resetUpload(true);
|
||||
}
|
||||
} else {
|
||||
this._resetUpload(true);
|
||||
Discourse.Utilities.displayErrorForUpload(upload);
|
||||
displayErrorForUpload(upload);
|
||||
}
|
||||
});
|
||||
|
||||
@ -492,7 +499,7 @@ export default Ember.Component.extend({
|
||||
}
|
||||
|
||||
// Paint oneboxes
|
||||
$('a.onebox', $preview).each((i, e) => Discourse.Onebox.load(e, refresh));
|
||||
$('a.onebox', $preview).each((i, e) => load(e, refresh, ajax));
|
||||
this.trigger('previewRefreshed', $preview);
|
||||
this.sendAction('afterRefresh', $preview);
|
||||
},
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import { default as computed, on } from 'ember-addons/ember-computed-decorators';
|
||||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
import InputValidation from 'discourse/models/input-validation';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
classNames: ['title-input'],
|
||||
|
||||
@on('didInsertElement')
|
||||
_focusOnTitle() {
|
||||
if (!this.capabilities.isIOS) {
|
||||
didInsertElement() {
|
||||
this._super();
|
||||
if (this.get('focusTarget') === 'title') {
|
||||
this.$('input').putCursorAtEnd();
|
||||
}
|
||||
},
|
||||
@ -23,7 +24,7 @@ export default Ember.Component.extend({
|
||||
}
|
||||
|
||||
if (reason) {
|
||||
return Discourse.InputValidation.create({ failed: true, reason, lastShownAt: lastValidatedAt });
|
||||
return InputValidation.create({ failed: true, reason, lastShownAt: lastValidatedAt });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -5,6 +5,14 @@ export default Ember.Component.extend({
|
||||
shouldHide: false,
|
||||
defaultUsernameCount: 0,
|
||||
|
||||
didInsertElement() {
|
||||
this._super();
|
||||
|
||||
if (this.get('focusTarget') === 'usernames') {
|
||||
this.$('input').putCursorAtEnd();
|
||||
}
|
||||
},
|
||||
|
||||
@observes('usernames')
|
||||
_checkWidth() {
|
||||
let width = 0;
|
||||
|
||||
@ -1,12 +1,15 @@
|
||||
/*global Mousetrap:true */
|
||||
import loadScript from 'discourse/lib/load-script';
|
||||
import { default as computed, on, observes } from 'ember-addons/ember-computed-decorators';
|
||||
import { showSelector } from "discourse/lib/emoji/emoji-toolbar";
|
||||
import { showSelector } from "discourse/lib/emoji/toolbar";
|
||||
import Category from 'discourse/models/category';
|
||||
import { categoryHashtagTriggerRule } from 'discourse/lib/category-hashtags';
|
||||
import { TAG_HASHTAG_POSTFIX } from 'discourse/lib/tag-hashtags';
|
||||
import { search as searchCategoryTag } from 'discourse/lib/category-tag-search';
|
||||
import { SEPARATOR } from 'discourse/lib/category-hashtags';
|
||||
import { cook } from 'discourse/lib/text';
|
||||
import { translations } from 'pretty-text/emoji/data';
|
||||
import { emojiSearch } from 'pretty-text/emoji';
|
||||
import { emojiUrlFor } from 'discourse/lib/text';
|
||||
|
||||
// Our head can be a static string or a function that returns a string
|
||||
// based on input (like for numbered lists).
|
||||
@ -193,7 +196,7 @@ export default Ember.Component.extend({
|
||||
this._applyEmojiAutocomplete(container, $editorInput);
|
||||
this._applyCategoryHashtagAutocomplete(container, $editorInput);
|
||||
|
||||
loadScript('defer/html-sanitizer-bundle').then(() => this.set('ready', true));
|
||||
this.set('ready', true);
|
||||
|
||||
const mouseTrap = Mousetrap(this.$('.d-editor-input')[0]);
|
||||
|
||||
@ -212,9 +215,8 @@ export default Ember.Component.extend({
|
||||
return false;
|
||||
});
|
||||
|
||||
this.appEvents.on('composer:insert-text', text => {
|
||||
this._addText(this._getSelected(), text);
|
||||
});
|
||||
this.appEvents.on('composer:insert-text', text => this._addText(this._getSelected(), text));
|
||||
this.appEvents.on('composer:replace-text', (oldVal, newVal) => this._replaceText(oldVal, newVal));
|
||||
|
||||
this._mouseTrap = mouseTrap;
|
||||
},
|
||||
@ -222,6 +224,7 @@ export default Ember.Component.extend({
|
||||
@on('willDestroyElement')
|
||||
_shutDown() {
|
||||
this.appEvents.off('composer:insert-text');
|
||||
this.appEvents.off('composer:replace-text');
|
||||
|
||||
const mouseTrap = this._mouseTrap;
|
||||
Object.keys(this.get('toolbar.shortcuts')).forEach(sc => mouseTrap.unbind(sc));
|
||||
@ -241,9 +244,10 @@ export default Ember.Component.extend({
|
||||
|
||||
const value = this.get('value');
|
||||
const markdownOptions = this.get('markdownOptions') || {};
|
||||
markdownOptions.sanitize = true;
|
||||
|
||||
this.set('preview', Discourse.Dialect.cook(value || "", markdownOptions));
|
||||
markdownOptions.siteSettings = this.siteSettings;
|
||||
|
||||
this.set('preview', cook(value));
|
||||
Ember.run.scheduleOnce('afterRender', () => {
|
||||
if (this._state !== "inDOM") { return; }
|
||||
const $preview = this.$('.d-editor-preview');
|
||||
@ -326,15 +330,15 @@ export default Ember.Component.extend({
|
||||
return resolve(["slight_smile", "smile", "wink", "sunny", "blush"]);
|
||||
}
|
||||
|
||||
if (Discourse.Emoji.translations[full]) {
|
||||
return resolve([Discourse.Emoji.translations[full]]);
|
||||
if (translations[full]) {
|
||||
return resolve([translations[full]]);
|
||||
}
|
||||
|
||||
const options = Discourse.Emoji.search(term, {maxResults: 5});
|
||||
const options = emojiSearch(term, {maxResults: 5});
|
||||
|
||||
return resolve(options);
|
||||
}).then(list => list.map(code => {
|
||||
return {code, src: Discourse.Emoji.urlFor(code)};
|
||||
return {code, src: emojiUrlFor(code)};
|
||||
})).then(list => {
|
||||
if (list.length) {
|
||||
list.push({ label: I18n.t("composer.more_emoji") });
|
||||
@ -471,6 +475,15 @@ export default Ember.Component.extend({
|
||||
}
|
||||
},
|
||||
|
||||
_replaceText(oldVal, newVal) {
|
||||
const val = this.get('value');
|
||||
const loc = val.indexOf(oldVal);
|
||||
if (loc !== -1) {
|
||||
this.set('value', val.replace(oldVal, newVal));
|
||||
this._selectText(loc + newVal.length, 0);
|
||||
}
|
||||
},
|
||||
|
||||
_addText(sel, text) {
|
||||
const $textarea = this.$('textarea.d-editor-input');
|
||||
const insert = `${sel.pre}${text}`;
|
||||
@ -524,7 +537,6 @@ export default Ember.Component.extend({
|
||||
const linkUrl = (origLink.indexOf('://') === -1) ? `http://${origLink}` : origLink;
|
||||
const sel = this._lastSel;
|
||||
|
||||
|
||||
if (Ember.isEmpty(linkUrl)) { return; }
|
||||
|
||||
const linkText = this.get('linkText') || '';
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
import { findAll } from 'discourse/models/login-method';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
elementId: 'login-buttons',
|
||||
classNameBindings: ['hidden'],
|
||||
|
||||
hidden: Em.computed.equal('buttons.length', 0),
|
||||
hidden: Ember.computed.equal('buttons.length', 0),
|
||||
|
||||
buttons: function() {
|
||||
return Em.get('Discourse.LoginMethod.all');
|
||||
return findAll(this.siteSettings);
|
||||
}.property(),
|
||||
|
||||
actions: {
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
import { showEntrance } from 'discourse/components/topic-list-item';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
tagName: 'tr',
|
||||
classNameBindings: [':category-topic-link', 'topic.archived'],
|
||||
click: showEntrance
|
||||
});
|
||||
@ -1,2 +0,0 @@
|
||||
const removed = new Discourse.RemovedObject('discourse/components/poster-name');
|
||||
export default removed;
|
||||
@ -20,42 +20,67 @@ export default Ember.Component.extend({
|
||||
}
|
||||
},
|
||||
|
||||
iconClass: function() {
|
||||
@computed('expanded')
|
||||
iconClass() {
|
||||
if (this.get('expanded')) { return "fa fa-caret-down"; }
|
||||
return "fa fa-caret-right";
|
||||
}.property('expanded'),
|
||||
},
|
||||
|
||||
tagClass: function() {
|
||||
@computed('tagId')
|
||||
tagClass() {
|
||||
if (this.get('tagId')) {
|
||||
return "tag-" + this.get('tagId');
|
||||
} else {
|
||||
return "tag_all";
|
||||
}
|
||||
}.property('tagId'),
|
||||
},
|
||||
|
||||
allTagsUrl: function() {
|
||||
@computed('firstCategory', 'secondCategory')
|
||||
allTagsUrl() {
|
||||
if (this.get('currentCategory')) {
|
||||
return this.get('currentCategory.url') + "?allTags=1";
|
||||
} else {
|
||||
return "/";
|
||||
}
|
||||
}.property('firstCategory', 'secondCategory'),
|
||||
},
|
||||
|
||||
allTagsLabel: function() {
|
||||
@computed('tag')
|
||||
allTagsLabel() {
|
||||
return I18n.t("tagging.selector_all_tags");
|
||||
}.property('tag'),
|
||||
},
|
||||
|
||||
dropdownButtonClass: function() {
|
||||
@computed('tagId')
|
||||
noTagsSelected() {
|
||||
return this.get('tagId') === 'none';
|
||||
},
|
||||
|
||||
@computed('firstCategory', 'secondCategory')
|
||||
noTagsUrl() {
|
||||
var url = '/tags';
|
||||
if (this.get('currentCategory')) {
|
||||
url += this.get('currentCategory.url');
|
||||
}
|
||||
return url + '/none';
|
||||
},
|
||||
|
||||
@computed('tag')
|
||||
noTagsLabel() {
|
||||
return I18n.t("tagging.selector_no_tags");
|
||||
},
|
||||
|
||||
@computed('tag')
|
||||
dropdownButtonClass() {
|
||||
var result = 'badge-category category-dropdown-button';
|
||||
if (Em.isNone(this.get('tag'))) {
|
||||
result += ' home';
|
||||
}
|
||||
return result;
|
||||
}.property('tag'),
|
||||
},
|
||||
|
||||
clickEventName: function() {
|
||||
@computed('tag')
|
||||
clickEventName() {
|
||||
return "click.tag-drop-" + (this.get('tag') || "all");
|
||||
}.property('tag'),
|
||||
},
|
||||
|
||||
actions: {
|
||||
expand: function() {
|
||||
|
||||
@ -1,5 +1,20 @@
|
||||
import StringBuffer from 'discourse/mixins/string-buffer';
|
||||
|
||||
export function showEntrance(e) {
|
||||
let target = $(e.target);
|
||||
|
||||
if (target.hasClass('posts-map') || target.parents('.posts-map').length > 0) {
|
||||
if (target.prop('tagName') !== 'A') {
|
||||
target = target.find('a');
|
||||
if (target.length===0) {
|
||||
target = target.end();
|
||||
}
|
||||
}
|
||||
this.container.lookup('controller:application').send("showTopicEntrance", {topic: this.get('topic'), position: target.offset()});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export default Ember.Component.extend(StringBuffer, {
|
||||
rerenderTriggers: ['bulkSelectEnabled', 'topic.pinned'],
|
||||
tagName: 'tr',
|
||||
@ -55,6 +70,16 @@ export default Ember.Component.extend(StringBuffer, {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.site.mobileView) {
|
||||
if (!this.siteSettings.show_pinned_excerpt_mobile) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!this.siteSettings.show_pinned_excerpt_desktop) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.get('expandGloballyPinned') && this.get('topic.pinned_globally')) {
|
||||
return true;
|
||||
}
|
||||
@ -67,19 +92,10 @@ export default Ember.Component.extend(StringBuffer, {
|
||||
}.property(),
|
||||
|
||||
click(e) {
|
||||
let target = $(e.target);
|
||||
|
||||
if (target.hasClass('posts-map') || target.parents('.posts-map').length > 0) {
|
||||
if (target.prop('tagName') !== 'A') {
|
||||
target = target.find('a');
|
||||
if (target.length===0) {
|
||||
target = target.end();
|
||||
}
|
||||
}
|
||||
this.container.lookup('controller:application').send("showTopicEntrance", {topic: this.get('topic'), position: target.offset()});
|
||||
return false;
|
||||
}
|
||||
const result = showEntrance.call(this, e);
|
||||
if (result === false) { return result; }
|
||||
|
||||
const target = $(e.target);
|
||||
if (target.hasClass('bulk-select')) {
|
||||
const selected = this.get('selected');
|
||||
const topic = this.get('topic');
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { iconHTML } from 'discourse/helpers/fa-icon';
|
||||
import StringBuffer from 'discourse/mixins/string-buffer';
|
||||
import { escapeExpression } from 'discourse/lib/utilities';
|
||||
|
||||
export default Ember.Component.extend(StringBuffer, {
|
||||
classNames: ['topic-statuses'],
|
||||
@ -29,7 +30,7 @@ export default Ember.Component.extend(StringBuffer, {
|
||||
const self = this;
|
||||
|
||||
const renderIcon = function(name, key, actionable) {
|
||||
const title = Discourse.Utilities.escapeExpression(I18n.t(`topic_statuses.${key}.help`)),
|
||||
const title = escapeExpression(I18n.t(`topic_statuses.${key}.help`)),
|
||||
startTag = actionable ? "a href" : "span",
|
||||
endTag = actionable ? "a" : "span",
|
||||
iconArgs = key === 'unpinned' ? { 'class': 'unpinned' } : null,
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import LoadMore from "discourse/mixins/load-more";
|
||||
import ClickTrack from 'discourse/lib/click-track';
|
||||
import { selectedText } from 'discourse/lib/utilities';
|
||||
|
||||
export default Ember.Component.extend(LoadMore, {
|
||||
loading: false,
|
||||
@ -19,7 +20,7 @@ export default Ember.Component.extend(LoadMore, {
|
||||
// bypass if we are selecting stuff
|
||||
const selection = window.getSelection && window.getSelection();
|
||||
if (selection.type === "Range" || selection.rangeCount > 0) {
|
||||
if (Discourse.Utilities.selectedText() !== "") {
|
||||
if (selectedText() !== "") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
|
||||
import { allowsImages } from 'discourse/lib/utilities';
|
||||
|
||||
export default Ember.Controller.extend(ModalFunctionality, {
|
||||
@computed("selected", "system_avatar_upload_id", "gravatar_avatar_upload_id", "custom_avatar_upload_id")
|
||||
selectedUploadId(selected, system, gravatar, custom) {
|
||||
@ -22,7 +24,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
|
||||
@computed()
|
||||
allowAvatarUpload() {
|
||||
return this.siteSettings.allow_uploaded_avatars && Discourse.Utilities.allowsImages();
|
||||
return this.siteSettings.allow_uploaded_avatars && allowsImages();
|
||||
},
|
||||
|
||||
actions: {
|
||||
|
||||
@ -4,6 +4,8 @@ import Draft from 'discourse/models/draft';
|
||||
import Composer from 'discourse/models/composer';
|
||||
import { default as computed, observes } from 'ember-addons/ember-computed-decorators';
|
||||
import { relativeAge } from 'discourse/lib/formatter';
|
||||
import { escapeExpression } from 'discourse/lib/utilities';
|
||||
import InputValidation from 'discourse/models/input-validation';
|
||||
|
||||
function loadDraft(store, opts) {
|
||||
opts = opts || {};
|
||||
@ -62,6 +64,21 @@ export default Ember.Controller.extend({
|
||||
topic: null,
|
||||
linkLookup: null,
|
||||
|
||||
@computed('model.replyingToTopic', 'model.creatingPrivateMessage', 'model.targetUsernames')
|
||||
focusTarget(replyingToTopic, creatingPM, usernames) {
|
||||
if (this.capabilities.isIOS) { return "none"; }
|
||||
|
||||
if (creatingPM && usernames === this.currentUser.get('username')) {
|
||||
return 'usernames';
|
||||
}
|
||||
|
||||
if (replyingToTopic) {
|
||||
return 'reply';
|
||||
}
|
||||
|
||||
return 'title';
|
||||
},
|
||||
|
||||
showToolbar: Em.computed({
|
||||
get(){
|
||||
const keyValueStore = this.container.lookup('key-value-store:main');
|
||||
@ -355,7 +372,7 @@ export default Ember.Controller.extend({
|
||||
|
||||
if (currentTopic) {
|
||||
buttons.push({
|
||||
"label": I18n.t("composer.reply_here") + "<br/><div class='topic-title overflow-ellipsis'>" + Discourse.Utilities.escapeExpression(currentTopic.get('title')) + "</div>",
|
||||
"label": I18n.t("composer.reply_here") + "<br/><div class='topic-title overflow-ellipsis'>" + escapeExpression(currentTopic.get('title')) + "</div>",
|
||||
"class": "btn btn-reply-here",
|
||||
"callback": function() {
|
||||
composer.set('topic', currentTopic);
|
||||
@ -366,7 +383,7 @@ export default Ember.Controller.extend({
|
||||
}
|
||||
|
||||
buttons.push({
|
||||
"label": I18n.t("composer.reply_original") + "<br/><div class='topic-title overflow-ellipsis'>" + Discourse.Utilities.escapeExpression(this.get('model.topic.title')) + "</div>",
|
||||
"label": I18n.t("composer.reply_original") + "<br/><div class='topic-title overflow-ellipsis'>" + escapeExpression(this.get('model.topic.title')) + "</div>",
|
||||
"class": "btn-primary btn-reply-on-original",
|
||||
"callback": function() {
|
||||
self.save(true);
|
||||
@ -644,7 +661,7 @@ export default Ember.Controller.extend({
|
||||
@computed('model.categoryId', 'lastValidatedAt')
|
||||
categoryValidation(categoryId, lastValidatedAt) {
|
||||
if( !this.siteSettings.allow_uncategorized_topics && !categoryId) {
|
||||
return Discourse.InputValidation.create({ failed: true, reason: I18n.t('composer.error.category_missing'), lastShownAt: lastValidatedAt });
|
||||
return InputValidation.create({ failed: true, reason: I18n.t('composer.error.category_missing'), lastShownAt: lastValidatedAt });
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import debounce from 'discourse/lib/debounce';
|
||||
import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
||||
import { setting } from 'discourse/lib/computed';
|
||||
import { on } from 'ember-addons/ember-computed-decorators';
|
||||
import { emailValid } from 'discourse/lib/utilities';
|
||||
import InputValidation from 'discourse/models/input-validation';
|
||||
|
||||
export default Ember.Controller.extend(ModalFunctionality, {
|
||||
needs: ['login'],
|
||||
@ -86,10 +89,10 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
// Validate the name.
|
||||
nameValidation: function() {
|
||||
if (Discourse.SiteSettings.full_name_required && Ember.isEmpty(this.get('accountName'))) {
|
||||
return Discourse.InputValidation.create({ failed: true });
|
||||
return InputValidation.create({ failed: true });
|
||||
}
|
||||
|
||||
return Discourse.InputValidation.create({ok: true});
|
||||
return InputValidation.create({ok: true});
|
||||
}.property('accountName'),
|
||||
|
||||
// Check the email address
|
||||
@ -97,7 +100,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
// If blank, fail without a reason
|
||||
let email;
|
||||
if (Ember.isEmpty(this.get('accountEmail'))) {
|
||||
return Discourse.InputValidation.create({
|
||||
return InputValidation.create({
|
||||
failed: true
|
||||
});
|
||||
}
|
||||
@ -105,14 +108,14 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
email = this.get("accountEmail");
|
||||
|
||||
if (this.get('rejectedEmails').contains(email)) {
|
||||
return Discourse.InputValidation.create({
|
||||
return InputValidation.create({
|
||||
failed: true,
|
||||
reason: I18n.t('user.email.invalid')
|
||||
});
|
||||
}
|
||||
|
||||
if ((this.get('authOptions.email') === email) && this.get('authOptions.email_valid')) {
|
||||
return Discourse.InputValidation.create({
|
||||
return InputValidation.create({
|
||||
ok: true,
|
||||
reason: I18n.t('user.email.authenticated', {
|
||||
provider: this.authProviderDisplayName(this.get('authOptions.auth_provider'))
|
||||
@ -120,14 +123,14 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
});
|
||||
}
|
||||
|
||||
if (Discourse.Utilities.emailValid(email)) {
|
||||
return Discourse.InputValidation.create({
|
||||
if (emailValid(email)) {
|
||||
return InputValidation.create({
|
||||
ok: true,
|
||||
reason: I18n.t('user.email.ok')
|
||||
});
|
||||
}
|
||||
|
||||
return Discourse.InputValidation.create({
|
||||
return InputValidation.create({
|
||||
failed: true,
|
||||
reason: I18n.t('user.email.invalid')
|
||||
});
|
||||
@ -175,15 +178,15 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
if (this.usernameNeedsToBeValidatedWithEmail()) {
|
||||
if (this.get('emailValidation.failed')) {
|
||||
if (this.shouldCheckUsernameMatch()) {
|
||||
return this.set('uniqueUsernameValidation', Discourse.InputValidation.create({
|
||||
return this.set('uniqueUsernameValidation', InputValidation.create({
|
||||
failed: true,
|
||||
reason: I18n.t('user.username.enter_email')
|
||||
}));
|
||||
} else {
|
||||
return this.set('uniqueUsernameValidation', Discourse.InputValidation.create({ failed: true }));
|
||||
return this.set('uniqueUsernameValidation', InputValidation.create({ failed: true }));
|
||||
}
|
||||
} else if (this.shouldCheckUsernameMatch()) {
|
||||
this.set('uniqueUsernameValidation', Discourse.InputValidation.create({
|
||||
this.set('uniqueUsernameValidation', InputValidation.create({
|
||||
failed: true,
|
||||
reason: I18n.t('user.username.checking')
|
||||
}));
|
||||
@ -196,7 +199,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
this.set('uniqueUsernameValidation', null);
|
||||
|
||||
if (this.get('accountUsername') === this.get('prefilledUsername')) {
|
||||
return Discourse.InputValidation.create({
|
||||
return InputValidation.create({
|
||||
ok: true,
|
||||
reason: I18n.t('user.username.prefilled')
|
||||
});
|
||||
@ -204,14 +207,14 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
|
||||
// If blank, fail without a reason
|
||||
if (Ember.isEmpty(this.get('accountUsername'))) {
|
||||
return Discourse.InputValidation.create({
|
||||
return InputValidation.create({
|
||||
failed: true
|
||||
});
|
||||
}
|
||||
|
||||
// If too short
|
||||
if (this.get('accountUsername').length < Discourse.SiteSettings.min_username_length) {
|
||||
return Discourse.InputValidation.create({
|
||||
return InputValidation.create({
|
||||
failed: true,
|
||||
reason: I18n.t('user.username.too_short')
|
||||
});
|
||||
@ -219,7 +222,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
|
||||
// If too long
|
||||
if (this.get('accountUsername').length > this.get('maxUsernameLength')) {
|
||||
return Discourse.InputValidation.create({
|
||||
return InputValidation.create({
|
||||
failed: true,
|
||||
reason: I18n.t('user.username.too_long')
|
||||
});
|
||||
@ -227,7 +230,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
|
||||
this.checkUsernameAvailability();
|
||||
// Let's check it out asynchronously
|
||||
return Discourse.InputValidation.create({
|
||||
return InputValidation.create({
|
||||
failed: true,
|
||||
reason: I18n.t('user.username.checking')
|
||||
});
|
||||
@ -246,23 +249,23 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
if (result.is_developer) {
|
||||
_this.set('isDeveloper', true);
|
||||
}
|
||||
return _this.set('uniqueUsernameValidation', Discourse.InputValidation.create({
|
||||
return _this.set('uniqueUsernameValidation', InputValidation.create({
|
||||
ok: true,
|
||||
reason: I18n.t('user.username.available')
|
||||
}));
|
||||
} else {
|
||||
if (result.suggestion) {
|
||||
return _this.set('uniqueUsernameValidation', Discourse.InputValidation.create({
|
||||
return _this.set('uniqueUsernameValidation', InputValidation.create({
|
||||
failed: true,
|
||||
reason: I18n.t('user.username.not_available', result)
|
||||
}));
|
||||
} else if (result.errors) {
|
||||
return _this.set('uniqueUsernameValidation', Discourse.InputValidation.create({
|
||||
return _this.set('uniqueUsernameValidation', InputValidation.create({
|
||||
failed: true,
|
||||
reason: result.errors.join(' ')
|
||||
}));
|
||||
} else {
|
||||
return _this.set('uniqueUsernameValidation', Discourse.InputValidation.create({
|
||||
return _this.set('uniqueUsernameValidation', InputValidation.create({
|
||||
failed: true,
|
||||
reason: I18n.t('user.username.enter_email')
|
||||
}));
|
||||
@ -286,47 +289,47 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
// Validate the password
|
||||
passwordValidation: function() {
|
||||
if (!this.get('passwordRequired')) {
|
||||
return Discourse.InputValidation.create({ ok: true });
|
||||
return InputValidation.create({ ok: true });
|
||||
}
|
||||
|
||||
// If blank, fail without a reason
|
||||
const password = this.get("accountPassword");
|
||||
if (Ember.isEmpty(this.get('accountPassword'))) {
|
||||
return Discourse.InputValidation.create({ failed: true });
|
||||
return InputValidation.create({ failed: true });
|
||||
}
|
||||
|
||||
// If too short
|
||||
const passwordLength = this.get('isDeveloper') ? Discourse.SiteSettings.min_admin_password_length : Discourse.SiteSettings.min_password_length;
|
||||
if (password.length < passwordLength) {
|
||||
return Discourse.InputValidation.create({
|
||||
return InputValidation.create({
|
||||
failed: true,
|
||||
reason: I18n.t('user.password.too_short')
|
||||
});
|
||||
}
|
||||
|
||||
if (this.get('rejectedPasswords').contains(password)) {
|
||||
return Discourse.InputValidation.create({
|
||||
return InputValidation.create({
|
||||
failed: true,
|
||||
reason: I18n.t('user.password.common')
|
||||
});
|
||||
}
|
||||
|
||||
if (!Ember.isEmpty(this.get('accountUsername')) && this.get('accountPassword') === this.get('accountUsername')) {
|
||||
return Discourse.InputValidation.create({
|
||||
return InputValidation.create({
|
||||
failed: true,
|
||||
reason: I18n.t('user.password.same_as_username')
|
||||
});
|
||||
}
|
||||
|
||||
if (!Ember.isEmpty(this.get('accountEmail')) && this.get('accountPassword') === this.get('accountEmail')) {
|
||||
return Discourse.InputValidation.create({
|
||||
return InputValidation.create({
|
||||
failed: true,
|
||||
reason: I18n.t('user.password.same_as_email')
|
||||
});
|
||||
}
|
||||
|
||||
// Looks good!
|
||||
return Discourse.InputValidation.create({
|
||||
return InputValidation.create({
|
||||
ok: true,
|
||||
reason: I18n.t('user.password.ok')
|
||||
});
|
||||
@ -334,7 +337,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
|
||||
@on('init')
|
||||
fetchConfirmationValue() {
|
||||
return Discourse.ajax('/users/hp.json').then(json => {
|
||||
return ajax('/users/hp.json').then(json => {
|
||||
this.set('accountPasswordConfirm', json.value);
|
||||
this.set('accountChallenge', json.challenge.split("").reverse().join(""));
|
||||
});
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import { observes } from "ember-addons/ember-computed-decorators";
|
||||
import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
||||
|
||||
@ -32,7 +33,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
setAutoClose(time) {
|
||||
const self = this;
|
||||
this.set('loading', true);
|
||||
Discourse.ajax({
|
||||
ajax({
|
||||
url: `/t/${this.get('model.id')}/autoclose`,
|
||||
type: 'PUT',
|
||||
dataType: 'json',
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
||||
import { categoryLinkHTML } from 'discourse/helpers/category-link';
|
||||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
import InputValidation from 'discourse/models/input-validation';
|
||||
|
||||
export default Ember.Controller.extend(ModalFunctionality, {
|
||||
needs: ["topic"],
|
||||
@ -68,14 +70,14 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
@computed("pinDisabled")
|
||||
pinInCategoryValidation(pinDisabled) {
|
||||
if (pinDisabled) {
|
||||
return Discourse.InputValidation.create({ failed: true, reason: I18n.t("topic.feature_topic.pin_validation") });
|
||||
return InputValidation.create({ failed: true, reason: I18n.t("topic.feature_topic.pin_validation") });
|
||||
}
|
||||
},
|
||||
|
||||
@computed("pinGloballyDisabled")
|
||||
pinGloballyValidation(pinGloballyDisabled) {
|
||||
if (pinGloballyDisabled) {
|
||||
return Discourse.InputValidation.create({ failed: true, reason: I18n.t("topic.feature_topic.pin_validation") });
|
||||
return InputValidation.create({ failed: true, reason: I18n.t("topic.feature_topic.pin_validation") });
|
||||
}
|
||||
},
|
||||
|
||||
@ -90,7 +92,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
onShow() {
|
||||
this.set("loading", true);
|
||||
|
||||
return Discourse.ajax("/topics/feature_stats.json", {
|
||||
return ajax("/topics/feature_stats.json", {
|
||||
data: { category_id: this.get("model.category.id") }
|
||||
}).then(result => {
|
||||
if (result) {
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
||||
import { escapeExpression } from 'discourse/lib/utilities';
|
||||
|
||||
export default Ember.Controller.extend(ModalFunctionality, {
|
||||
|
||||
@ -23,7 +25,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
|
||||
var success = function(data) {
|
||||
// don't tell people what happened, this keeps it more secure (ensure same on server)
|
||||
var escaped = Discourse.Utilities.escapeExpression(self.get('accountEmailOrUsername'));
|
||||
var escaped = escapeExpression(self.get('accountEmailOrUsername'));
|
||||
var isEmail = self.get('accountEmailOrUsername').match(/@/);
|
||||
|
||||
var key = 'forgot_password.complete_' + (isEmail ? 'email' : 'username');
|
||||
@ -48,7 +50,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
self.flash(e.responseJSON.errors[0], 'error');
|
||||
};
|
||||
|
||||
Discourse.ajax('/session/forgot_password', {
|
||||
ajax('/session/forgot_password', {
|
||||
data: { login: this.get('accountEmailOrUsername').trim() },
|
||||
type: 'POST'
|
||||
}).then(success, fail).finally(function(){
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import { translateResults, searchContextDescription, getSearchKey, isValidSearchTerm } from "discourse/lib/search";
|
||||
import showModal from 'discourse/lib/show-modal';
|
||||
import { default as computed, observes } from 'ember-addons/ember-computed-decorators';
|
||||
import Category from 'discourse/models/category';
|
||||
import { escapeExpression } from 'discourse/lib/utilities';
|
||||
|
||||
const SortOrders = [
|
||||
{name: I18n.t('search.relevance'), id: 0},
|
||||
@ -75,7 +77,7 @@ export default Ember.Controller.extend({
|
||||
}
|
||||
});
|
||||
}
|
||||
return Discourse.Utilities.escapeExpression(q);
|
||||
return escapeExpression(q);
|
||||
},
|
||||
|
||||
_searchOnSortChange: true,
|
||||
@ -156,7 +158,7 @@ export default Ember.Controller.extend({
|
||||
|
||||
const searchKey = getSearchKey(args);
|
||||
|
||||
Discourse.ajax("/search", { data: args }).then(results => {
|
||||
ajax("/search", { data: args }).then(results => {
|
||||
const model = translateResults(results) || {};
|
||||
router.transientCache('lastSearch', { searchKey, model }, 5);
|
||||
this.set("model", model);
|
||||
@ -193,7 +195,7 @@ export default Ember.Controller.extend({
|
||||
|
||||
showSearchHelp() {
|
||||
// TODO: dupe code should be centralized
|
||||
Discourse.ajax("/static/search_help.html", { dataType: 'html' }).then((model) => {
|
||||
ajax("/static/search_help.html", { dataType: 'html' }).then((model) => {
|
||||
showModal('searchHelp', { model });
|
||||
});
|
||||
},
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
||||
import { emailValid } from 'discourse/lib/utilities';
|
||||
|
||||
export default Ember.Controller.extend(ModalFunctionality, {
|
||||
needs: ['user-invited-show'],
|
||||
@ -19,11 +20,11 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
if (Ember.isEmpty(this.get('emailOrUsername'))) return true;
|
||||
const emailOrUsername = this.get('emailOrUsername').trim();
|
||||
// when inviting to forum, email must be valid
|
||||
if (!this.get('invitingToTopic') && !Discourse.Utilities.emailValid(emailOrUsername)) return true;
|
||||
if (!this.get('invitingToTopic') && !emailValid(emailOrUsername)) return true;
|
||||
// normal users (not admin) can't invite users to private topic via email
|
||||
if (!this.get('isAdmin') && this.get('isPrivateTopic') && Discourse.Utilities.emailValid(emailOrUsername)) return true;
|
||||
if (!this.get('isAdmin') && this.get('isPrivateTopic') && emailValid(emailOrUsername)) return true;
|
||||
// when inviting to private topic via email, group name must be specified
|
||||
if (this.get('isPrivateTopic') && Ember.isEmpty(this.get('model.groupNames')) && Discourse.Utilities.emailValid(emailOrUsername)) return true;
|
||||
if (this.get('isPrivateTopic') && Ember.isEmpty(this.get('model.groupNames')) && emailValid(emailOrUsername)) return true;
|
||||
if (this.get('model.details.can_invite_to')) return false;
|
||||
return false;
|
||||
}.property('isAdmin', 'emailOrUsername', 'invitingToTopic', 'isPrivateTopic', 'model.groupNames', 'model.saving'),
|
||||
@ -34,11 +35,11 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
if (Ember.isEmpty(this.get('emailOrUsername'))) return true;
|
||||
const emailOrUsername = this.get('emailOrUsername').trim();
|
||||
// email must be valid
|
||||
if (!Discourse.Utilities.emailValid(emailOrUsername)) return true;
|
||||
if (!emailValid(emailOrUsername)) return true;
|
||||
// normal users (not admin) can't invite users to private topic via email
|
||||
if (!this.get('isAdmin') && this.get('isPrivateTopic') && Discourse.Utilities.emailValid(emailOrUsername)) return true;
|
||||
if (!this.get('isAdmin') && this.get('isPrivateTopic') && emailValid(emailOrUsername)) return true;
|
||||
// when inviting to private topic via email, group name must be specified
|
||||
if (this.get('isPrivateTopic') && Ember.isEmpty(this.get('model.groupNames')) && Discourse.Utilities.emailValid(emailOrUsername)) return true;
|
||||
if (this.get('isPrivateTopic') && Ember.isEmpty(this.get('model.groupNames')) && emailValid(emailOrUsername)) return true;
|
||||
return false;
|
||||
}.property('emailOrUsername', 'model.saving', 'isPrivateTopic', 'model.groupNames', 'hasCustomMessage'),
|
||||
|
||||
@ -71,11 +72,11 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
|
||||
// Show Groups? (add invited user to private group)
|
||||
showGroups: function() {
|
||||
return this.get('isAdmin') && (Discourse.Utilities.emailValid(this.get('emailOrUsername')) || this.get('isPrivateTopic') || !this.get('invitingToTopic')) && !Discourse.SiteSettings.enable_sso && Discourse.SiteSettings.enable_local_logins && !this.get('isMessage');
|
||||
return this.get('isAdmin') && (emailValid(this.get('emailOrUsername')) || this.get('isPrivateTopic') || !this.get('invitingToTopic')) && !Discourse.SiteSettings.enable_sso && Discourse.SiteSettings.enable_local_logins && !this.get('isMessage');
|
||||
}.property('isAdmin', 'emailOrUsername', 'isPrivateTopic', 'isMessage', 'invitingToTopic'),
|
||||
|
||||
showCustomMessage: function() {
|
||||
return (this.get('model') === this.currentUser || Discourse.Utilities.emailValid(this.get('emailOrUsername')));
|
||||
return (this.get('model') === this.currentUser || emailValid(this.get('emailOrUsername')));
|
||||
}.property('emailOrUsername'),
|
||||
|
||||
// Instructional text for the modal.
|
||||
@ -95,7 +96,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
// when inviting to a topic, display instructions based on provided entity
|
||||
if (Ember.isEmpty(this.get('emailOrUsername'))) {
|
||||
return I18n.t('topic.invite_reply.to_topic_blank');
|
||||
} else if (Discourse.Utilities.emailValid(this.get('emailOrUsername'))) {
|
||||
} else if (emailValid(this.get('emailOrUsername'))) {
|
||||
this.set("inviteIcon", "envelope");
|
||||
return I18n.t('topic.invite_reply.to_topic_email');
|
||||
} else {
|
||||
@ -125,7 +126,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
return I18n.t('topic.invite_private.success_group');
|
||||
} else if (this.get('isMessage')) {
|
||||
return I18n.t('topic.invite_private.success');
|
||||
} else if ( Discourse.Utilities.emailValid(this.get('emailOrUsername')) ) {
|
||||
} else if ( emailValid(this.get('emailOrUsername')) ) {
|
||||
return I18n.t('topic.invite_reply.success_email', { emailOrUsername: this.get('emailOrUsername') });
|
||||
} else {
|
||||
return I18n.t('topic.invite_reply.success_username');
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
||||
import showModal from 'discourse/lib/show-modal';
|
||||
import { setting } from 'discourse/lib/computed';
|
||||
import { findAll } from 'discourse/models/login-method';
|
||||
|
||||
// This is happening outside of the app via popup
|
||||
const AuthErrors =
|
||||
@ -22,12 +24,10 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
this.set('loggedIn', false);
|
||||
},
|
||||
|
||||
/**
|
||||
Determines whether at least one login button is enabled
|
||||
**/
|
||||
// Determines whether at least one login button is enabled
|
||||
hasAtLeastOneLoginButton: function() {
|
||||
return Em.get("Discourse.LoginMethod.all").length > 0;
|
||||
}.property("Discourse.LoginMethod.all.[]"),
|
||||
return findAll(this.siteSettings).length > 0;
|
||||
}.property(),
|
||||
|
||||
loginButtonText: function() {
|
||||
return this.get('loggingIn') ? I18n.t('login.logging_in') : I18n.t('login.title');
|
||||
@ -56,7 +56,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
|
||||
this.set('loggingIn', true);
|
||||
|
||||
Discourse.ajax("/session", {
|
||||
ajax("/session", {
|
||||
data: { login: this.get('loginName'), password: this.get('loginPassword') },
|
||||
type: 'POST'
|
||||
}).then(function (result) {
|
||||
@ -175,7 +175,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
|
||||
authMessage: (function() {
|
||||
if (Ember.isEmpty(this.get('authenticate'))) return "";
|
||||
const method = Discourse.get('LoginMethod.all').findProperty("name", this.get("authenticate"));
|
||||
const method = findAll(this.siteSettings).findProperty("name", this.get("authenticate"));
|
||||
if(method){
|
||||
return method.get('message');
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
||||
|
||||
export default Ember.Controller.extend(ModalFunctionality, {
|
||||
@ -9,7 +10,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
|
||||
actions: {
|
||||
sendActivationEmail: function() {
|
||||
Discourse.ajax('/users/action/send_activation_email', {data: {username: this.get('username')}, type: 'POST'});
|
||||
ajax('/users/action/send_activation_email', {data: {username: this.get('username')}, type: 'POST'});
|
||||
this.set('emailSent', true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ import { setting } from 'discourse/lib/computed';
|
||||
import CanCheckEmails from 'discourse/mixins/can-check-emails';
|
||||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
import { cook } from 'discourse/lib/text';
|
||||
|
||||
export default Ember.Controller.extend(CanCheckEmails, {
|
||||
|
||||
@ -155,7 +156,7 @@ export default Ember.Controller.extend(CanCheckEmails, {
|
||||
if (Discourse.User.currentProp('id') === model.get('id')) {
|
||||
Discourse.User.currentProp('name', model.get('name'));
|
||||
}
|
||||
model.set('bio_cooked', Discourse.Markdown.cook(Discourse.Markdown.sanitize(model.get('bio_raw'))));
|
||||
model.set('bio_cooked', cook(model.get('bio_raw')));
|
||||
this.set('saved', true);
|
||||
}).catch(popupAjaxError);
|
||||
},
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import BadgeSelectController from "discourse/mixins/badge-select-controller";
|
||||
|
||||
export default Ember.ArrayController.extend(BadgeSelectController, {
|
||||
@ -11,7 +12,7 @@ export default Ember.ArrayController.extend(BadgeSelectController, {
|
||||
this.setProperties({ saved: false, saving: true });
|
||||
|
||||
var self = this;
|
||||
Discourse.ajax(this.get('user.path') + "/preferences/badge_title", {
|
||||
ajax(this.get('user.path') + "/preferences/badge_title", {
|
||||
type: "PUT",
|
||||
data: { user_badge_id: self.get('selectedUserBadgeId') }
|
||||
}).then(function() {
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import BadgeSelectController from "discourse/mixins/badge-select-controller";
|
||||
|
||||
export default Ember.ArrayController.extend(BadgeSelectController, {
|
||||
@ -12,7 +13,7 @@ export default Ember.ArrayController.extend(BadgeSelectController, {
|
||||
this.setProperties({ saved: false, saving: true });
|
||||
|
||||
var self = this;
|
||||
Discourse.ajax(this.get('user.path') + "/preferences/card-badge", {
|
||||
ajax(this.get('user.path') + "/preferences/card-badge", {
|
||||
type: "PUT",
|
||||
data: { user_badge_id: self.get('selectedUserBadgeId') }
|
||||
}).then(function() {
|
||||
|
||||
@ -1,14 +1,10 @@
|
||||
import loadScript from 'discourse/lib/load-script';
|
||||
import Quote from 'discourse/lib/quote';
|
||||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
import { selectedText } from 'discourse/lib/utilities';
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
needs: ['topic', 'composer'],
|
||||
|
||||
_loadSanitizer: function() {
|
||||
loadScript('defer/html-sanitizer-bundle');
|
||||
}.on('init'),
|
||||
|
||||
@computed('buffer', 'postId')
|
||||
post(buffer, postId) {
|
||||
if (!postId || Ember.isEmpty(buffer)) { return null; }
|
||||
@ -49,12 +45,12 @@ export default Ember.Controller.extend({
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedText = Discourse.Utilities.selectedText();
|
||||
if (this.get('buffer') === selectedText) return;
|
||||
const selVal = selectedText();
|
||||
if (this.get('buffer') === selVal) return;
|
||||
|
||||
// we need to retrieve the post data from the posts collection in the topic controller
|
||||
this.set('postId', postId);
|
||||
this.set('buffer', selectedText);
|
||||
this.set('buffer', selVal);
|
||||
|
||||
// create a marker element
|
||||
const markerElement = document.createElement("span");
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
||||
const BufferedProxy = window.BufferedProxy; // import BufferedProxy from 'ember-buffered-proxy/proxy';
|
||||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
||||
@ -90,7 +91,7 @@ export default Ember.Controller.extend(ModalFunctionality, Ember.Evented, {
|
||||
this.get('categoriesBuffered').forEach((cat) => {
|
||||
data[cat.get('id')] = cat.get('position');
|
||||
});
|
||||
Discourse.ajax('/categories/reorder',
|
||||
ajax('/categories/reorder',
|
||||
{type: 'POST', data: {mapping: JSON.stringify(data)}}).
|
||||
then(() => this.send("closeModal")).
|
||||
catch(popupAjaxError);
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
@ -15,7 +16,7 @@ export default Ember.Controller.extend({
|
||||
markFaqRead() {
|
||||
const currentUser = this.currentUser;
|
||||
if (currentUser) {
|
||||
Discourse.ajax("/users/read-faq", { method: "POST" }).then(() => {
|
||||
ajax("/users/read-faq", { method: "POST" }).then(() => {
|
||||
currentUser.set('read_faq', true);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
||||
import { default as computed } from 'ember-addons/ember-computed-decorators';
|
||||
import { allowsAttachments, authorizesAllExtensions, authorizedExtensions } from 'discourse/lib/utilities';
|
||||
|
||||
export function uploadTranslate(key, options) {
|
||||
options = options || {};
|
||||
if (Discourse.Utilities.allowsAttachments()) { key += "_with_attachments"; }
|
||||
if (allowsAttachments()) { key += "_with_attachments"; }
|
||||
return I18n.t(`upload_selector.${key}`, options);
|
||||
}
|
||||
|
||||
@ -16,13 +17,13 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
|
||||
@computed
|
||||
uploadIcon() {
|
||||
return Discourse.Utilities.allowsAttachments() ? "upload" : "picture-o";
|
||||
return allowsAttachments() ? "upload" : "picture-o";
|
||||
},
|
||||
|
||||
@computed('controller.local')
|
||||
tip(local) {
|
||||
const source = local ? "local" : "remote";
|
||||
const authorized_extensions = Discourse.Utilities.authorizesAllExtensions() ? "" : `(${Discourse.Utilities.authorizedExtensions()})`;
|
||||
const authorized_extensions = authorizesAllExtensions() ? "" : `(${authorizedExtensions()})`;
|
||||
return uploadTranslate(`${source}_tip`, { authorized_extensions });
|
||||
},
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import { default as computed, observes } from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
export default Ember.ArrayController.extend({
|
||||
@ -17,7 +18,7 @@ export default Ember.ArrayController.extend({
|
||||
|
||||
actions: {
|
||||
resetNew() {
|
||||
Discourse.ajax('/notifications/mark-read', { method: 'PUT' }).then(() => {
|
||||
ajax('/notifications/mark-read', { method: 'PUT' }).then(() => {
|
||||
this.setEach('read', true);
|
||||
});
|
||||
},
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
/**
|
||||
This addition handles auto linking of text. When included, it will parse out links and create
|
||||
a hrefs for them.
|
||||
**/
|
||||
var urlReplacerArgs = {
|
||||
matcher: /^((?:https?:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.])(?:[^\s()<>]+|\([^\s()<>]+\))+(?:\([^\s()<>]+\)|[^`!()\[\]{};:'".,<>?«»“”‘’\s]))/,
|
||||
spaceOrTagBoundary: true,
|
||||
|
||||
emitter: function(matches) {
|
||||
var url = matches[1],
|
||||
displayUrl = url;
|
||||
|
||||
// Don't autolink a markdown link to something
|
||||
if (url.match(/\]\[\d$/)) { return; }
|
||||
|
||||
// If we improperly caught a markdown link abort
|
||||
if (url.match(/\(http/)) { return; }
|
||||
|
||||
if (url.match(/^www/)) { url = "http://" + url; }
|
||||
return ['a', {href: url}, displayUrl];
|
||||
}
|
||||
};
|
||||
|
||||
Discourse.Dialect.inlineRegexp(_.merge({start: 'http'}, urlReplacerArgs));
|
||||
Discourse.Dialect.inlineRegexp(_.merge({start: 'www'}, urlReplacerArgs));
|
||||
@ -1,182 +0,0 @@
|
||||
Discourse.BBCode = {};
|
||||
|
||||
/**
|
||||
Create a simple BBCode tag handler
|
||||
|
||||
@method replaceBBCode
|
||||
@param {tag} tag the tag we want to match
|
||||
@param {function} emitter the function that creates JsonML for the tag
|
||||
@param {Object} opts options to pass to Discourse.Dialect.inlineBetween
|
||||
@param {Function} [opts.emitter] The function that will be called with the contents and returns JsonML.
|
||||
@param {String} [opts.start] The starting token we want to find
|
||||
@param {String} [opts.stop] The ending token we want to find
|
||||
@param {String} [opts.between] A shortcut for when the `start` and `stop` are the same.
|
||||
@param {Boolean} [opts.rawContents] If true, the contents between the tokens will not be parsed.
|
||||
@param {Boolean} [opts.wordBoundary] If true, the match must be on a word boundary
|
||||
@param {Boolean} [opts.spaceBoundary] If true, the match must be on a sppace boundary
|
||||
**/
|
||||
|
||||
Discourse.BBCode.register = function(codeName, args, emitter) {
|
||||
|
||||
// Optional second param for args
|
||||
if (typeof args === "function") {
|
||||
emitter = args;
|
||||
args = {};
|
||||
}
|
||||
|
||||
Discourse.Dialect.replaceBlock({
|
||||
start: new RegExp("\\[" + codeName + "(=[^\\[\\]]+)?\\]([\\s\\S]*)", "igm"),
|
||||
stop: new RegExp("\\[\\/" + codeName + "\\]", "igm"),
|
||||
emitter: function(blockContents, matches, options) {
|
||||
while (blockContents.length && (typeof blockContents[0] === "string" || blockContents[0] instanceof String)) {
|
||||
blockContents[0] = String(blockContents[0]).replace(/^\s+/, '');
|
||||
if (!blockContents[0].length) {
|
||||
blockContents.shift();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var contents = [];
|
||||
if (blockContents.length) {
|
||||
var self = this;
|
||||
|
||||
var nextContents = blockContents.slice(1);
|
||||
blockContents = this.processBlock(blockContents[0], nextContents).concat(nextContents);
|
||||
|
||||
blockContents.forEach(function (bc) {
|
||||
if (typeof bc === "string" || bc instanceof String) {
|
||||
var processed = self.processInline(String(bc));
|
||||
if (processed.length) {
|
||||
contents.push(['p'].concat(processed));
|
||||
}
|
||||
} else {
|
||||
contents.push(bc);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!args.singlePara && contents.length === 1 && contents[0] instanceof Array && contents[0][0] === "para") {
|
||||
contents[0].shift();
|
||||
contents = contents[0];
|
||||
}
|
||||
var result = emitter(contents, matches[1] ? matches[1].replace(/^=|\"/g, '') : null, options);
|
||||
return args.noWrap ? result : ['p', result];
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Discourse.BBCode.replaceBBCode = function (tag, emitter, opts) {
|
||||
opts = opts || {};
|
||||
opts = _.merge(opts, { start: "[" + tag + "]", stop: "[/" + tag + "]", emitter: emitter });
|
||||
Discourse.Dialect.inlineBetween(opts);
|
||||
|
||||
tag = tag.toUpperCase();
|
||||
opts = _.merge(opts, { start: "[" + tag + "]", stop: "[/" + tag + "]", emitter: emitter });
|
||||
Discourse.Dialect.inlineBetween(opts);
|
||||
};
|
||||
|
||||
/**
|
||||
Shortcut to call replaceBBCode with `rawContents` as true.
|
||||
|
||||
@method replaceBBCode
|
||||
@param {tag} tag the tag we want to match
|
||||
@param {function} emitter the function that creates JsonML for the tag
|
||||
**/
|
||||
Discourse.BBCode.rawBBCode = function (tag, emitter) {
|
||||
Discourse.BBCode.replaceBBCode(tag, emitter, { rawContents: true });
|
||||
};
|
||||
|
||||
/**
|
||||
Creates a BBCode handler that accepts parameters. Passes them to the emitter.
|
||||
|
||||
@method replaceBBCodeParamsRaw
|
||||
@param {tag} tag the tag we want to match
|
||||
@param {function} emitter the function that creates JsonML for the tag
|
||||
**/
|
||||
Discourse.BBCode.replaceBBCodeParamsRaw = function (tag, emitter) {
|
||||
var opts = {
|
||||
rawContents: true,
|
||||
emitter: function(contents) {
|
||||
var regexp = /^([^\]]+)\]([\S\s]*)$/,
|
||||
m = regexp.exec(contents);
|
||||
|
||||
if (m) { return emitter.call(this, m[1], m[2]); }
|
||||
}
|
||||
};
|
||||
|
||||
Discourse.Dialect.inlineBetween(_.merge(opts, { start: "[" + tag + "=", stop: "[/" + tag + "]" }));
|
||||
|
||||
tag = tag.toUpperCase();
|
||||
Discourse.Dialect.inlineBetween(_.merge(opts, { start: "[" + tag + "=", stop: "[/" + tag + "]" }));
|
||||
};
|
||||
|
||||
/**
|
||||
Filters an array of JSON-ML nodes, removing nodes that represent empty lines ("\n").
|
||||
|
||||
@method removeEmptyLines
|
||||
@param {Array} [contents] Array of JSON-ML nodes
|
||||
**/
|
||||
Discourse.BBCode.removeEmptyLines = function (contents) {
|
||||
var result = [];
|
||||
for (var i=0; i < contents.length; i++) {
|
||||
if (contents[i] !== "\n") { result.push(contents[i]); }
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
Discourse.BBCode.replaceBBCode('b', function(contents) { return ['span', {'class': 'bbcode-b'}].concat(contents); });
|
||||
Discourse.BBCode.replaceBBCode('i', function(contents) { return ['span', {'class': 'bbcode-i'}].concat(contents); });
|
||||
Discourse.BBCode.replaceBBCode('u', function(contents) { return ['span', {'class': 'bbcode-u'}].concat(contents); });
|
||||
Discourse.BBCode.replaceBBCode('s', function(contents) { return ['span', {'class': 'bbcode-s'}].concat(contents); });
|
||||
Discourse.Markdown.whiteListTag('span', 'class', /^bbcode-[bius]$/);
|
||||
|
||||
Discourse.BBCode.replaceBBCode('ul', function(contents) { return ['ul'].concat(Discourse.BBCode.removeEmptyLines(contents)); });
|
||||
Discourse.BBCode.replaceBBCode('ol', function(contents) { return ['ol'].concat(Discourse.BBCode.removeEmptyLines(contents)); });
|
||||
Discourse.BBCode.replaceBBCode('li', function(contents) { return ['li'].concat(Discourse.BBCode.removeEmptyLines(contents)); });
|
||||
|
||||
Discourse.BBCode.rawBBCode('img', function(contents) { return ['img', {href: contents}]; });
|
||||
Discourse.BBCode.rawBBCode('email', function(contents) { return ['a', {href: "mailto:" + contents, 'data-bbcode': true}, contents]; });
|
||||
|
||||
Discourse.BBCode.replaceBBCode('url', function(contents) {
|
||||
if (!Array.isArray(contents)) { return; }
|
||||
if (contents.length === 1 && contents[0][0] === 'a') {
|
||||
// single-line bbcode links shouldn't be oneboxed, so we mark this as a bbcode link.
|
||||
if (typeof contents[0][1] !== 'object') { contents[0].splice(1, 0, {}); }
|
||||
contents[0][1]['data-bbcode'] = true;
|
||||
}
|
||||
return ['concat'].concat(contents);
|
||||
});
|
||||
Discourse.BBCode.replaceBBCodeParamsRaw('url', function(param, contents) {
|
||||
var url = param.replace(/(^")|("$)/g, '');
|
||||
return ['a', {'href': url}].concat(this.processInline(contents));
|
||||
});
|
||||
Discourse.Dialect.on('parseNode', function(event) {
|
||||
if (!Array.isArray(event.node)) { return; }
|
||||
var result = [ event.node[0] ];
|
||||
var nodes = event.node.slice(1);
|
||||
var i, j;
|
||||
for (i = 0; i < nodes.length; i++) {
|
||||
if (Array.isArray(nodes[i]) && nodes[i][0] === 'concat') {
|
||||
for (j = 1; j < nodes[i].length; j++) { result.push(nodes[i][j]); }
|
||||
} else {
|
||||
result.push(nodes[i]);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < result.length; i++) { event.node[i] = result[i]; }
|
||||
});
|
||||
|
||||
Discourse.BBCode.replaceBBCodeParamsRaw("email", function(param, contents) {
|
||||
return ['a', {href: "mailto:" + param, 'data-bbcode': true}].concat(contents);
|
||||
});
|
||||
|
||||
// Handles `[code] ... [/code]` blocks
|
||||
Discourse.Dialect.replaceBlock({
|
||||
start: /(\[code\])([\s\S]*)/igm,
|
||||
stop: /\[\/code\]/igm,
|
||||
rawContents: true,
|
||||
|
||||
emitter: function(blockContents) {
|
||||
var inner = blockContents.join("\n");
|
||||
return ['p', ['pre', ['code', {'class': Discourse.SiteSettings.default_code_lang}, inner]]];
|
||||
}
|
||||
});
|
||||
@ -1,78 +0,0 @@
|
||||
/**
|
||||
markdown-js doesn't ensure that em/strong codes are present on word boundaries.
|
||||
So we create our own handlers here.
|
||||
**/
|
||||
|
||||
// From PageDown
|
||||
var aLetter = /[a-zA-Z0-9\u00aa\u00b5\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376-\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0523\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0621-\u064a\u0660-\u0669\u066e-\u066f\u0671-\u06d3\u06d5\u06e5-\u06e6\u06ee-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07c0-\u07ea\u07f4-\u07f5\u07fa\u0904-\u0939\u093d\u0950\u0958-\u0961\u0966-\u096f\u0971-\u0972\u097b-\u097f\u0985-\u098c\u098f-\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc-\u09dd\u09df-\u09e1\u09e6-\u09f1\u0a05-\u0a0a\u0a0f-\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32-\u0a33\u0a35-\u0a36\u0a38-\u0a39\u0a59-\u0a5c\u0a5e\u0a66-\u0a6f\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2-\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0-\u0ae1\u0ae6-\u0aef\u0b05-\u0b0c\u0b0f-\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32-\u0b33\u0b35-\u0b39\u0b3d\u0b5c-\u0b5d\u0b5f-\u0b61\u0b66-\u0b6f\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99-\u0b9a\u0b9c\u0b9e-\u0b9f\u0ba3-\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0be6-\u0bef\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58-\u0c59\u0c60-\u0c61\u0c66-\u0c6f\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0-\u0ce1\u0ce6-\u0cef\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d28\u0d2a-\u0d39\u0d3d\u0d60-\u0d61\u0d66-\u0d6f\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32-\u0e33\u0e40-\u0e46\u0e50-\u0e59\u0e81-\u0e82\u0e84\u0e87-\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa-\u0eab\u0ead-\u0eb0\u0eb2-\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0ed0-\u0ed9\u0edc-\u0edd\u0f00\u0f20-\u0f29\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8b\u1000-\u102a\u103f-\u1049\u1050-\u1055\u105a-\u105d\u1061\u1065-\u1066\u106e-\u1070\u1075-\u1081\u108e\u1090-\u1099\u10a0-\u10c5\u10d0-\u10fa\u10fc\u1100-\u1159\u115f-\u11a2\u11a8-\u11f9\u1200-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u1676\u1681-\u169a\u16a0-\u16ea\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u17e0-\u17e9\u1810-\u1819\u1820-\u1877\u1880-\u18a8\u18aa\u1900-\u191c\u1946-\u196d\u1970-\u1974\u1980-\u19a9\u19c1-\u19c7\u19d0-\u19d9\u1a00-\u1a16\u1b05-\u1b33\u1b45-\u1b4b\u1b50-\u1b59\u1b83-\u1ba0\u1bae-\u1bb9\u1c00-\u1c23\u1c40-\u1c49\u1c4d-\u1c7d\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u203f-\u2040\u2054\u2071\u207f\u2090-\u2094\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2183-\u2184\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2c6f\u2c71-\u2c7d\u2c80-\u2ce4\u2d00-\u2d25\u2d30-\u2d65\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3006\u3031-\u3035\u303b-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31b7\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fc3\ua000-\ua48c\ua500-\ua60c\ua610-\ua62b\ua640-\ua65f\ua662-\ua66e\ua67f-\ua697\ua717-\ua71f\ua722-\ua788\ua78b-\ua78c\ua7fb-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8d0-\ua8d9\ua900-\ua925\ua930-\ua946\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa50-\uaa59\uac00-\ud7a3\uf900-\ufa2d\ufa30-\ufa6a\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe33-\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]/;
|
||||
|
||||
|
||||
var unhoist = function(obj,from,to){
|
||||
var unhoisted = 0;
|
||||
var regex = new RegExp(from, "g");
|
||||
|
||||
if(_.isArray(obj)){
|
||||
for(var i=0; i<obj.length; i++){
|
||||
var item = obj[i];
|
||||
|
||||
if(_.isString(item)){
|
||||
// Odd, but we need +1 for the / in front of /*
|
||||
var matches = item.match(regex);
|
||||
unhoisted -= matches ? matches.length : 0;
|
||||
|
||||
obj[i] = item.replace(regex, to);
|
||||
unhoisted += item.length - obj[i].length;
|
||||
}
|
||||
if(_.isArray(item)){
|
||||
unhoisted += unhoist(item, from, to);
|
||||
}
|
||||
}
|
||||
}
|
||||
return unhoisted;
|
||||
};
|
||||
|
||||
var replaceMarkdown = function(match, tag) {
|
||||
var hash = Discourse.Dialect.guid();
|
||||
|
||||
Discourse.Dialect.registerInline(match, function(text, matched, prev){
|
||||
if(!text || text.length < match.length + 1) {
|
||||
return;
|
||||
}
|
||||
var lastText = prev[prev.length-1];
|
||||
lastText = typeof lastText === "string" && lastText;
|
||||
lastText = lastText && lastText[lastText.length-1];
|
||||
if(lastText && (lastText === "/" || lastText.match(aLetter))){
|
||||
return;
|
||||
}
|
||||
|
||||
if(text[match.length].match(/\s/)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// hoist out escaped \*
|
||||
text = text.replace(new RegExp("\\\\\\" + match[0], "g"), hash);
|
||||
|
||||
var endText = new RegExp("[^\\s|" + match[0] + "]" + match.replace(/\*/g,"\\*") + "([^" + match[0] + "]|$)");
|
||||
|
||||
var finish = text.split("\n")[0].search(endText);
|
||||
if(finish && finish >= 0) {
|
||||
var newText = text.substring(match.length, finish+1);
|
||||
newText = this.processInline(newText);
|
||||
|
||||
var unhoisted_length = unhoist(newText,hash,match[0]);
|
||||
|
||||
var array = typeof tag === "string" ? [tag].concat(newText) : [tag[0], [tag[1]].concat(newText)];
|
||||
|
||||
return [(finish + match.length + 1) - unhoisted_length, array];
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
replaceMarkdown('***', ['strong','em']);
|
||||
replaceMarkdown('___', ['strong','em']);
|
||||
replaceMarkdown('**', 'strong');
|
||||
replaceMarkdown('__', 'strong');
|
||||
replaceMarkdown('*', 'em');
|
||||
replaceMarkdown('_', 'em');
|
||||
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
/**
|
||||
Supports Discourse's category hashtags (#category-slug) for automatically
|
||||
generating a link to the category.
|
||||
**/
|
||||
Discourse.Dialect.inlineRegexp({
|
||||
start: '#',
|
||||
matcher: /^#([\w-:]{1,101})/i,
|
||||
spaceOrTagBoundary: true,
|
||||
|
||||
emitter: function(matches) {
|
||||
var slug = matches[1],
|
||||
hashtag = matches[0],
|
||||
attributeClass = 'hashtag',
|
||||
categoryHashtagLookup = this.dialect.options.categoryHashtagLookup,
|
||||
result = categoryHashtagLookup && categoryHashtagLookup(slug);
|
||||
|
||||
if (result) {
|
||||
return ['a', { class: attributeClass, href: result[0] }, '#', ["span", {}, result[1]]];
|
||||
} else {
|
||||
return ['span', { class: attributeClass }, hashtag];
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -1,3 +0,0 @@
|
||||
Discourse.Dialect.addPreProcessor(function(text) {
|
||||
return Discourse.CensoredWords.censor(text);
|
||||
});
|
||||
@ -1,81 +0,0 @@
|
||||
/**
|
||||
Support for various code blocks
|
||||
**/
|
||||
|
||||
var acceptableCodeClasses;
|
||||
|
||||
function init() {
|
||||
acceptableCodeClasses = Discourse.SiteSettings.highlighted_languages.split("|");
|
||||
if (Discourse.SiteSettings.highlighted_languages.length > 0) {
|
||||
var regexpSource = "^lang-(" + "nohighlight|auto|" + Discourse.SiteSettings.highlighted_languages + ")$";
|
||||
Discourse.Markdown.whiteListTag('code', 'class', new RegExp(regexpSource, "i"));
|
||||
}
|
||||
}
|
||||
|
||||
if (Discourse.SiteSettings) {
|
||||
init();
|
||||
} else {
|
||||
Discourse.initializer({initialize: init, name: 'load-acceptable-code-classes'});
|
||||
}
|
||||
|
||||
|
||||
var textCodeClasses = ["text", "pre", "plain"];
|
||||
|
||||
function codeFlattenBlocks(blocks) {
|
||||
var result = "";
|
||||
blocks.forEach(function(b) {
|
||||
result += b;
|
||||
if (b.trailing) { result += b.trailing; }
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
Discourse.Dialect.replaceBlock({
|
||||
start: /^`{3}([^\n\[\]]+)?\n?([\s\S]*)?/gm,
|
||||
stop: /^```$/gm,
|
||||
withoutLeading: /\[quote/gm, //if leading text contains a quote this should not match
|
||||
emitter: function(blockContents, matches) {
|
||||
|
||||
var klass = Discourse.SiteSettings.default_code_lang;
|
||||
|
||||
if (acceptableCodeClasses && matches[1] && acceptableCodeClasses.indexOf(matches[1]) !== -1) {
|
||||
klass = matches[1];
|
||||
}
|
||||
|
||||
if (textCodeClasses.indexOf(matches[1]) !== -1) {
|
||||
return ['p', ['pre', ['code', {'class': 'lang-nohighlight'}, codeFlattenBlocks(blockContents) ]]];
|
||||
} else {
|
||||
return ['p', ['pre', ['code', {'class': 'lang-' + klass}, codeFlattenBlocks(blockContents) ]]];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Discourse.Dialect.replaceBlock({
|
||||
start: /(<pre[^\>]*\>)([\s\S]*)/igm,
|
||||
stop: /<\/pre>/igm,
|
||||
rawContents: true,
|
||||
skipIfTradtionalLinebreaks: true,
|
||||
|
||||
emitter: function(blockContents) {
|
||||
return ['p', ['pre', codeFlattenBlocks(blockContents)]];
|
||||
}
|
||||
});
|
||||
|
||||
// Ensure that content in a code block is fully escaped. This way it's not white listed
|
||||
// and we can use HTML and Javascript examples.
|
||||
Discourse.Dialect.on('parseNode', function (event) {
|
||||
var node = event.node,
|
||||
path = event.path;
|
||||
|
||||
if (node[0] === 'code') {
|
||||
var contents = node[node.length-1],
|
||||
regexp;
|
||||
|
||||
if (path && path[path.length-1] && path[path.length-1][0] && path[path.length-1][0] === "pre") {
|
||||
regexp = / +$/g;
|
||||
} else {
|
||||
regexp = /^ +| +$/g;
|
||||
}
|
||||
node[node.length-1] = Discourse.Utilities.escapeExpression(contents.replace(regexp,''));
|
||||
}
|
||||
});
|
||||
@ -1,51 +0,0 @@
|
||||
/**
|
||||
If a row begins with HTML tags, don't parse it.
|
||||
**/
|
||||
var blockTags = ['address', 'article', 'aside', 'audio', 'blockquote', 'canvas', 'dd', 'div',
|
||||
'dl', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3',
|
||||
'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'iframe', 'noscript', 'ol', 'output',
|
||||
'p', 'pre', 'section', 'table', 'tfoot', 'ul', 'video'],
|
||||
|
||||
splitAtLast = function(tag, block, next, first) {
|
||||
var endTag = "</" + tag + ">",
|
||||
endTagIndex = first ? block.indexOf(endTag) : block.lastIndexOf(endTag);
|
||||
|
||||
if (endTagIndex !== -1) {
|
||||
endTagIndex += endTag.length;
|
||||
|
||||
var leading = block.substr(0, endTagIndex),
|
||||
trailing = block.substr(endTagIndex).replace(/^\s+/, '');
|
||||
|
||||
if (trailing.length) {
|
||||
next.unshift(trailing);
|
||||
}
|
||||
|
||||
return [ leading ];
|
||||
}
|
||||
};
|
||||
|
||||
Discourse.Dialect.registerBlock('html', function(block, next) {
|
||||
var split, pos;
|
||||
|
||||
// Fix manual blockquote paragraphing even though it's not strictly correct
|
||||
// PERF NOTE: /\S+<blockquote/ is a perf hog for search, try on huge string
|
||||
if (pos = block.search(/<blockquote/) >= 0) {
|
||||
if(block.substring(0, pos).search(/\s/) === -1) {
|
||||
split = splitAtLast('blockquote', block, next, true);
|
||||
if (split) { return this.processInline(split[0]); }
|
||||
}
|
||||
}
|
||||
|
||||
var m = /^<([^>]+)\>/.exec(block);
|
||||
if (m && m[1]) {
|
||||
var tag = m[1].split(/\s/);
|
||||
if (tag && tag[0] && blockTags.indexOf(tag[0]) !== -1) {
|
||||
split = splitAtLast(tag[0], block, next);
|
||||
if (split) {
|
||||
if (split.length === 1 && split[0] === block) { return; }
|
||||
return split;
|
||||
}
|
||||
return [ block.toString() ];
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -1,45 +0,0 @@
|
||||
/**
|
||||
Supports Discourse's custom @mention syntax for calling out a user in a post.
|
||||
It will add a special class to them, and create a link if the user is found in a
|
||||
local map.
|
||||
**/
|
||||
Discourse.Dialect.inlineRegexp({
|
||||
start: '@',
|
||||
// NOTE: since we can't use SiteSettings here (they loads later in process)
|
||||
// we are being less strict to account for more cases than allowed
|
||||
matcher: /^@(\w[\w.-]{0,59})\b/i,
|
||||
wordBoundary: true,
|
||||
|
||||
emitter: function(matches) {
|
||||
var mention = matches[0].trim(),
|
||||
name = matches[1],
|
||||
mentionLookup = this.dialect.options.mentionLookup;
|
||||
|
||||
var type = mentionLookup && mentionLookup(name);
|
||||
if (type === "user") {
|
||||
return ['a', {'class': 'mention', href: Discourse.getURL("/users/") + name.toLowerCase()}, mention];
|
||||
} else if (type === "group") {
|
||||
return ['a', {'class': 'mention-group', href: Discourse.getURL("/groups/") + name}, mention];
|
||||
} else {
|
||||
return ['span', {'class': 'mention'}, mention];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// We have to prune @mentions that are within links.
|
||||
Discourse.Dialect.on("parseNode", function(event) {
|
||||
var node = event.node,
|
||||
path = event.path;
|
||||
|
||||
if (node[1] && node[1]["class"] === 'mention') {
|
||||
var parent = path[path.length - 1];
|
||||
// If the parent is an 'a', remove it
|
||||
if (parent && parent[0] === 'a') {
|
||||
var name = node[2];
|
||||
node.length = 0;
|
||||
node[0] = "__RAW";
|
||||
node[1] = name;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
@ -1,21 +0,0 @@
|
||||
Discourse.Dialect.on('parseNode', function (event) {
|
||||
var node = event.node,
|
||||
path = event.path;
|
||||
|
||||
if (node[0] === 'a') {
|
||||
|
||||
// It's invalid HTML to nest a link within another so strip it out.
|
||||
for (var i=0; i<path.length; i++) {
|
||||
if (path[i][0] === 'a') {
|
||||
var parent = path[path.length - 1],
|
||||
pos = parent.indexOf(node);
|
||||
|
||||
// Just leave the link text
|
||||
if (pos !== -1) {
|
||||
parent[pos] = node[2];
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -1,32 +0,0 @@
|
||||
/**
|
||||
Support for the newline behavior in markdown that most expect. Look through all text nodes
|
||||
in the tree, replace any new lines with `br`s.
|
||||
**/
|
||||
Discourse.Dialect.postProcessText(function (text, event) {
|
||||
var opts = event.dialect.options,
|
||||
insideCounts = event.insideCounts,
|
||||
linebreaks = opts.traditional_markdown_linebreaks || Discourse.SiteSettings.traditional_markdown_linebreaks;
|
||||
|
||||
if (linebreaks || (insideCounts.pre > 0)) { return; }
|
||||
|
||||
if (text === "\n") {
|
||||
// If the tag is just a new line, replace it with a `<br>`
|
||||
return [['br']];
|
||||
} else {
|
||||
|
||||
|
||||
// If the text node contains new lines, perhaps with text between them, insert the
|
||||
// `<br>` tags.
|
||||
var split = text.split(/\n+/);
|
||||
if (split.length) {
|
||||
var replacement = [];
|
||||
for (var i=0; i<split.length; i++) {
|
||||
if (split[i].length > 0) { replacement.push(split[i]); }
|
||||
if (i !== split.length-1) { replacement.push(['br']); }
|
||||
}
|
||||
|
||||
return replacement;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
@ -1,79 +0,0 @@
|
||||
/**
|
||||
Given a node in the document and its parent, determine whether it is on its
|
||||
own line or not.
|
||||
|
||||
@method isOnOneLine
|
||||
@namespace Discourse.Dialect
|
||||
**/
|
||||
var isOnOneLine = function(link, parent) {
|
||||
if (!parent) { return false; }
|
||||
|
||||
var siblings = parent.slice(1);
|
||||
if ((!siblings) || (siblings.length < 1)) { return false; }
|
||||
|
||||
var idx = siblings.indexOf(link);
|
||||
if (idx === -1) { return false; }
|
||||
|
||||
if (idx > 0) {
|
||||
var prev = siblings[idx-1];
|
||||
if (prev[0] !== 'br') { return false; }
|
||||
}
|
||||
|
||||
if (idx < siblings.length) {
|
||||
var next = siblings[idx+1];
|
||||
if (next && (!((next[0] === 'br') || (typeof next === 'string' && next.trim() === "")))) { return false; }
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
We only onebox stuff that is on its own line. This navigates the JsonML tree and
|
||||
correctly inserts the oneboxes.
|
||||
|
||||
@event parseNode
|
||||
@namespace Discourse.Dialect
|
||||
**/
|
||||
Discourse.Dialect.on("parseNode", function(event) {
|
||||
var node = event.node,
|
||||
path = event.path;
|
||||
|
||||
// We only care about links
|
||||
if (node[0] !== 'a') { return; }
|
||||
|
||||
var parent = path[path.length - 1];
|
||||
|
||||
// We don't onebox bbcode
|
||||
if (node[1]['data-bbcode']) {
|
||||
delete node[1]['data-bbcode'];
|
||||
return;
|
||||
}
|
||||
|
||||
// We don't onebox mentions
|
||||
if (node[1]['class'] === 'mention') { return; }
|
||||
|
||||
// Don't onebox links within a list
|
||||
for (var i=0; i<path.length; i++) {
|
||||
if (path[i][0] === 'li') { return; }
|
||||
}
|
||||
|
||||
// If the link has a different label text than the link itself, don't onebox it.
|
||||
var label = node[node.length-1];
|
||||
if (label !== node[1]['href']) { return; }
|
||||
|
||||
if (isOnOneLine(node, parent)) {
|
||||
|
||||
node[1]['class'] = 'onebox';
|
||||
node[1].target = '_blank';
|
||||
|
||||
if (Discourse && Discourse.Onebox) {
|
||||
var contents = Discourse.Onebox.lookupCache(node[1].href);
|
||||
if (contents) {
|
||||
node[0] = '__RAW';
|
||||
node[1] = contents;
|
||||
node.length = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,61 +0,0 @@
|
||||
var esc = Handlebars.Utils.escapeExpression;
|
||||
|
||||
Discourse.BBCode.register('quote', {noWrap: true, singlePara: true}, function(contents, bbParams, options) {
|
||||
var params = {'class': 'quote'},
|
||||
username = null;
|
||||
|
||||
if (bbParams) {
|
||||
var paramsSplit = bbParams.split(/\,\s*/);
|
||||
username = paramsSplit[0];
|
||||
|
||||
paramsSplit.forEach(function(p,i) {
|
||||
if (i > 0) {
|
||||
var assignment = p.split(':');
|
||||
if (assignment[0] && assignment[1]) {
|
||||
var escaped = esc(assignment[0]);
|
||||
// don't escape attributes, makes no sense
|
||||
if(escaped === assignment[0]) {
|
||||
params['data-' + assignment[0]] = esc(assignment[1].trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var avatarImg;
|
||||
var postNumber = parseInt(params['data-post'], 10);
|
||||
var topicId = parseInt(params['data-topic'], 10);
|
||||
|
||||
if (options.lookupAvatarByPostNumber) {
|
||||
// client-side, we can retrieve the avatar from the post
|
||||
avatarImg = options.lookupAvatarByPostNumber(postNumber, topicId);
|
||||
} else if (options.lookupAvatar) {
|
||||
// server-side, we need to lookup the avatar from the username
|
||||
avatarImg = options.lookupAvatar(username);
|
||||
}
|
||||
|
||||
// If there's no username just return a simple quote
|
||||
if (!username) {
|
||||
return ['p', ['aside', params, ['blockquote'].concat(contents)]];
|
||||
}
|
||||
|
||||
var header = [ 'div', {'class': 'title'},
|
||||
['div', {'class': 'quote-controls'}],
|
||||
avatarImg ? ['__RAW', avatarImg] : "",
|
||||
username ? I18n.t('user.said', {username: username}) : ""
|
||||
];
|
||||
|
||||
if (options.topicId && postNumber && options.getTopicInfo && topicId !== options.topicId) {
|
||||
var topicInfo = options.getTopicInfo(topicId);
|
||||
if (topicInfo) {
|
||||
var href = topicInfo.href;
|
||||
if (postNumber > 0) { href += "/" + postNumber; }
|
||||
// get rid of username said stuff
|
||||
header.pop();
|
||||
header.push(['a', {'href': href}, topicInfo.title]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ['aside', params, header, ['blockquote'].concat(contents)];
|
||||
});
|
||||
@ -1,51 +0,0 @@
|
||||
var tableFlattenBlocks = function(blocks) {
|
||||
var result = "";
|
||||
blocks.forEach(function(b) {
|
||||
result += b;
|
||||
if (b.trailing) { result += b.trailing; }
|
||||
});
|
||||
|
||||
// bypass newline insertion
|
||||
return result.replace(/[\n\r]/g, " ");
|
||||
};
|
||||
|
||||
var emitter = function(contents) {
|
||||
// TODO event should be fired when sanitizer loads
|
||||
if (window.html4 && window.html4.ELEMENTS.td !== 1) {
|
||||
window.html4.ELEMENTS.table = 0;
|
||||
window.html4.ELEMENTS.tbody = 1;
|
||||
window.html4.ELEMENTS.td = 1;
|
||||
window.html4.ELEMENTS.thead = 1;
|
||||
window.html4.ELEMENTS.th = 1;
|
||||
window.html4.ELEMENTS.tr = 1;
|
||||
}
|
||||
return ['table', {"class": "md-table"}, tableFlattenBlocks.apply(this, [contents])];
|
||||
};
|
||||
|
||||
var tableBlock = {
|
||||
start: /(<table[^>]*>)([\S\s]*)/igm,
|
||||
stop: /<\/table>/igm,
|
||||
rawContents: true,
|
||||
emitter: emitter,
|
||||
priority: 1
|
||||
};
|
||||
|
||||
var init = function(){
|
||||
if (Discourse.SiteSettings.allow_html_tables) {
|
||||
Discourse.Markdown.whiteListTag("table");
|
||||
Discourse.Markdown.whiteListTag("table", "class", "md-table");
|
||||
Discourse.Markdown.whiteListTag("tbody");
|
||||
Discourse.Markdown.whiteListTag("thead");
|
||||
Discourse.Markdown.whiteListTag("tr");
|
||||
Discourse.Markdown.whiteListTag("th");
|
||||
Discourse.Markdown.whiteListTag("td");
|
||||
Discourse.Dialect.replaceBlock(tableBlock);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
if (Discourse.SiteSettings) {
|
||||
init();
|
||||
} else {
|
||||
Discourse.initializer({initialize: init, name: 'enable-html-tables'});
|
||||
}
|
||||
@ -1,5 +1,4 @@
|
||||
import { htmlHelper } from 'discourse/lib/helpers';
|
||||
import { avatarImg } from 'discourse/lib/utilities';
|
||||
|
||||
export default htmlHelper((avatarTemplate, size) => {
|
||||
return Discourse.Utilities.avatarImg({ size, avatarTemplate });
|
||||
});
|
||||
export default htmlHelper((avatarTemplate, size) => avatarImg({ size, avatarTemplate }));
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { htmlHelper } from 'discourse/lib/helpers';
|
||||
import { avatarImg } from 'discourse/lib/utilities';
|
||||
|
||||
export default htmlHelper((user, size) => {
|
||||
if (Ember.isEmpty(user)) {
|
||||
@ -6,5 +7,5 @@ export default htmlHelper((user, size) => {
|
||||
}
|
||||
|
||||
const avatarTemplate = Em.get(user, 'avatar_template');
|
||||
return Discourse.Utilities.avatarImg({ size, avatarTemplate });
|
||||
return avatarImg({ size, avatarTemplate });
|
||||
});
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
import { cook } from 'discourse/lib/text';
|
||||
import { registerUnbound } from 'discourse/lib/helpers';
|
||||
|
||||
registerUnbound('cook-text', function(text) {
|
||||
return new Handlebars.SafeString(Discourse.Markdown.cook(text, {sanitize: true}));
|
||||
});
|
||||
|
||||
registerUnbound('cook-text', cook);
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { registerHelper } from 'discourse/lib/helpers';
|
||||
import PreloadStore from 'preload-store';
|
||||
|
||||
const _customizations = {};
|
||||
|
||||
|
||||
@ -1,9 +1,5 @@
|
||||
import { registerUnbound } from 'discourse/lib/helpers';
|
||||
import { emojiUnescape } from 'discourse/lib/text';
|
||||
|
||||
registerUnbound('i18n', function(key, params) {
|
||||
return I18n.t(key, params);
|
||||
});
|
||||
|
||||
registerUnbound('replace-emoji', function(text) {
|
||||
return new Handlebars.SafeString(Discourse.Emoji.unescape(text));
|
||||
});
|
||||
registerUnbound('i18n', (key, params) => I18n.t(key, params));
|
||||
registerUnbound('replace-emoji', text => new Handlebars.SafeString(emojiUnescape(text)));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user