Version bump
This commit is contained in:
commit
33b93124d6
5
.gitignore
vendored
5
.gitignore
vendored
@ -46,7 +46,7 @@ bootsnap-compile-cache/
|
||||
|
||||
# Ignore plugins except for the bundled ones.
|
||||
/plugins/*
|
||||
!/plugins/lazyYT/
|
||||
!/plugins/lazy-yt/
|
||||
!/plugins/poll/
|
||||
!/plugins/discourse-details/
|
||||
!/plugins/discourse-nginx-performance-report
|
||||
@ -127,3 +127,6 @@ vendor/bundle/*
|
||||
|
||||
# Vagrant
|
||||
.vagrant
|
||||
|
||||
# ignore auto-generated plugin js assets
|
||||
/app/assets/javascripts/plugins/*
|
||||
|
||||
@ -7,7 +7,7 @@ AllCops:
|
||||
- 'vendor/**/*'
|
||||
- 'node_modules/**/*'
|
||||
- 'public/**/*'
|
||||
- 'plugins/**/*'
|
||||
- 'plugins/**/gems/**/*'
|
||||
|
||||
# Prefer &&/|| over and/or.
|
||||
Style/AndOr:
|
||||
|
||||
@ -60,7 +60,7 @@ before_install:
|
||||
- git clone --depth=1 https://github.com/discourse/discourse-chat-integration.git plugins/discourse-chat-integration
|
||||
- git clone --depth=1 https://github.com/discourse/discourse-assign.git plugins/discourse-assign
|
||||
- git clone --depth=1 https://github.com/discourse/discourse-patreon.git plugins/discourse-patreon
|
||||
- git clone --depth=1 https://github.com/discourse/discourse-staff-notes.git plugins/discourse-staff-notes
|
||||
- git clone --depth=1 https://github.com/discourse/discourse-user-notes.git plugins/discourse-user-notes
|
||||
- git clone --depth=1 https://github.com/discourse/discourse-group-tracker
|
||||
- export PATH=$HOME/.yarn/bin:$PATH
|
||||
|
||||
|
||||
9
Gemfile
9
Gemfile
@ -46,12 +46,12 @@ gem 'redis-namespace'
|
||||
|
||||
gem 'active_model_serializers', '~> 0.8.3'
|
||||
|
||||
gem 'onebox', '1.9.2'
|
||||
gem 'onebox', '1.9.12'
|
||||
|
||||
gem 'http_accept_language', '~>2.0.5', require: false
|
||||
|
||||
gem 'ember-rails', '0.18.5'
|
||||
gem 'discourse-ember-source', '~> 3.8.0'
|
||||
gem 'discourse-ember-source', '~> 3.10.0'
|
||||
gem 'ember-handlebars-template', '0.8.0'
|
||||
gem 'barber'
|
||||
|
||||
@ -74,10 +74,12 @@ gem 'unf', require: false
|
||||
gem 'email_reply_trimmer', '~> 0.1'
|
||||
|
||||
# Forked until https://github.com/toy/image_optim/pull/162 is merged
|
||||
# https://github.com/discourse/image_optim
|
||||
gem 'discourse_image_optim', require: 'image_optim'
|
||||
gem 'multi_json'
|
||||
gem 'mustache'
|
||||
gem 'nokogiri'
|
||||
gem 'css_parser', require: false
|
||||
|
||||
gem 'omniauth'
|
||||
gem 'omniauth-openid'
|
||||
@ -203,9 +205,12 @@ gem "sassc-rails"
|
||||
gem 'rotp'
|
||||
gem 'rqrcode'
|
||||
|
||||
gem 'rubyzip', require: false
|
||||
|
||||
gem 'sshkey', require: false
|
||||
|
||||
gem 'rchardet', require: false
|
||||
gem 'lz4-ruby', require: false, platform: :mri
|
||||
|
||||
if ENV["IMPORT"] == "1"
|
||||
gem 'mysql2'
|
||||
|
||||
23
Gemfile.lock
23
Gemfile.lock
@ -88,10 +88,12 @@ GEM
|
||||
crack (0.4.3)
|
||||
safe_yaml (~> 1.0.0)
|
||||
crass (1.0.4)
|
||||
css_parser (1.7.0)
|
||||
addressable
|
||||
debug_inspector (0.0.3)
|
||||
diff-lcs (1.3)
|
||||
diffy (3.3.0)
|
||||
discourse-ember-source (3.8.0.1)
|
||||
discourse-ember-source (3.10.0.1)
|
||||
discourse_image_optim (0.26.2)
|
||||
exifr (~> 1.2, >= 1.2.2)
|
||||
fspath (~> 3.0)
|
||||
@ -172,11 +174,12 @@ GEM
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
lru_redux (1.1.0)
|
||||
lz4-ruby (0.3.3)
|
||||
mail (2.7.1)
|
||||
mini_mime (>= 0.1.1)
|
||||
maxminddb (0.1.22)
|
||||
memory_profiler (0.9.13)
|
||||
message_bus (2.2.0)
|
||||
message_bus (2.2.2)
|
||||
rack (>= 1.1.3)
|
||||
metaclass (0.0.4)
|
||||
method_source (0.9.2)
|
||||
@ -184,7 +187,7 @@ GEM
|
||||
mini_portile2 (2.4.0)
|
||||
mini_racer (0.2.6)
|
||||
libv8 (>= 6.9.411)
|
||||
mini_scheduler (0.11.0)
|
||||
mini_scheduler (0.12.1)
|
||||
sidekiq
|
||||
mini_sql (0.2.2)
|
||||
mini_suffix (0.3.0)
|
||||
@ -199,7 +202,7 @@ GEM
|
||||
multi_xml (0.6.0)
|
||||
multipart-post (2.1.1)
|
||||
mustache (1.1.0)
|
||||
nokogiri (1.10.3)
|
||||
nokogiri (1.10.4)
|
||||
mini_portile2 (~> 2.4.0)
|
||||
nokogumbo (2.0.1)
|
||||
nokogiri (~> 1.8, >= 1.8.4)
|
||||
@ -238,7 +241,7 @@ GEM
|
||||
omniauth-twitter (1.4.0)
|
||||
omniauth-oauth (~> 1.1)
|
||||
rack
|
||||
onebox (1.9.2)
|
||||
onebox (1.9.12)
|
||||
htmlentities (~> 4.3)
|
||||
moneta (~> 1.0)
|
||||
multi_json (~> 1.11)
|
||||
@ -272,7 +275,7 @@ GEM
|
||||
rack-openid (1.3.1)
|
||||
rack (>= 1.1.0)
|
||||
ruby-openid (>= 2.1.8)
|
||||
rack-protection (2.0.5)
|
||||
rack-protection (2.0.7)
|
||||
rack
|
||||
rack-test (1.1.0)
|
||||
rack (>= 1.0, < 3)
|
||||
@ -351,6 +354,7 @@ GEM
|
||||
guess_html_encoding (>= 0.0.4)
|
||||
nokogiri (>= 1.6.0)
|
||||
ruby_dep (1.5.0)
|
||||
rubyzip (1.2.3)
|
||||
safe_yaml (1.0.5)
|
||||
sanitize (5.0.0)
|
||||
crass (~> 1.0.2)
|
||||
@ -437,8 +441,9 @@ DEPENDENCIES
|
||||
certified
|
||||
colored2
|
||||
cppjieba_rb
|
||||
css_parser
|
||||
diffy
|
||||
discourse-ember-source (~> 3.8.0)
|
||||
discourse-ember-source (~> 3.10.0)
|
||||
discourse_image_optim
|
||||
email_reply_trimmer (~> 0.1)
|
||||
ember-handlebars-template (= 0.8.0)
|
||||
@ -463,6 +468,7 @@ DEPENDENCIES
|
||||
logstash-logger
|
||||
logster
|
||||
lru_redux
|
||||
lz4-ruby
|
||||
mail
|
||||
maxminddb
|
||||
memory_profiler
|
||||
@ -487,7 +493,7 @@ DEPENDENCIES
|
||||
omniauth-oauth2
|
||||
omniauth-openid
|
||||
omniauth-twitter
|
||||
onebox (= 1.9.2)
|
||||
onebox (= 1.9.12)
|
||||
openid-redis-store
|
||||
parallel_tests
|
||||
pg
|
||||
@ -516,6 +522,7 @@ DEPENDENCIES
|
||||
rubocop
|
||||
ruby-prof
|
||||
ruby-readability
|
||||
rubyzip
|
||||
sanitize
|
||||
sassc
|
||||
sassc-rails
|
||||
|
||||
7
app/assets/javascripts/admin/adapters/email-style.js.es6
Normal file
7
app/assets/javascripts/admin/adapters/email-style.js.es6
Normal file
@ -0,0 +1,7 @@
|
||||
import RestAdapter from "discourse/adapters/rest";
|
||||
|
||||
export default RestAdapter.extend({
|
||||
pathFor() {
|
||||
return "/admin/customize/email_style";
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,7 @@
|
||||
import RestAdapter from "discourse/adapters/rest";
|
||||
|
||||
export default RestAdapter.extend({
|
||||
basePath() {
|
||||
return "/admin/logs/";
|
||||
}
|
||||
});
|
||||
@ -75,7 +75,7 @@ export default Ember.Component.extend({
|
||||
if (!this.element || this.isDestroying || this.isDestroyed) {
|
||||
return;
|
||||
}
|
||||
const editor = loadedAce.edit(this.$(".ace")[0]);
|
||||
const editor = loadedAce.edit(this.element.querySelector(".ace"));
|
||||
|
||||
editor.setTheme("ace/theme/chrome");
|
||||
editor.setShowPrintMargin(false);
|
||||
@ -89,7 +89,7 @@ export default Ember.Component.extend({
|
||||
editor.$blockScrolling = Infinity;
|
||||
editor.renderer.setScrollMargin(10, 10);
|
||||
|
||||
this.$().data("editor", editor);
|
||||
this.element.setAttribute("data-editor", editor);
|
||||
this._editor = editor;
|
||||
this.changeDisabledState();
|
||||
|
||||
|
||||
@ -18,8 +18,8 @@ export default Ember.Component.extend(
|
||||
},
|
||||
|
||||
_scrollDown() {
|
||||
const $div = this.$()[0];
|
||||
$div.scrollTop = $div.scrollHeight;
|
||||
const div = this.element;
|
||||
div.scrollTop = div.scrollHeight;
|
||||
},
|
||||
|
||||
@on("init")
|
||||
|
||||
@ -5,7 +5,7 @@ export default Ember.Component.extend({
|
||||
type: "line",
|
||||
|
||||
refreshChart() {
|
||||
const ctx = this.$()[0].getContext("2d");
|
||||
const ctx = this.element.getContext("2d");
|
||||
const model = this.model;
|
||||
const rawData = this.get("model.data");
|
||||
|
||||
|
||||
@ -35,14 +35,17 @@ export default Ember.Component.extend({
|
||||
|
||||
_scheduleChartRendering() {
|
||||
Ember.run.schedule("afterRender", () => {
|
||||
this._renderChart(this.model, this.$(".chart-canvas"));
|
||||
this._renderChart(
|
||||
this.model,
|
||||
this.element && this.element.querySelector(".chart-canvas")
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
_renderChart(model, $chartCanvas) {
|
||||
if (!$chartCanvas || !$chartCanvas.length) return;
|
||||
_renderChart(model, chartCanvas) {
|
||||
if (!chartCanvas) return;
|
||||
|
||||
const context = $chartCanvas[0].getContext("2d");
|
||||
const context = chartCanvas.getContext("2d");
|
||||
const chartData = Ember.makeArray(
|
||||
model.get("chartData") || model.get("data")
|
||||
);
|
||||
|
||||
@ -33,14 +33,17 @@ export default Ember.Component.extend({
|
||||
|
||||
_scheduleChartRendering() {
|
||||
Ember.run.schedule("afterRender", () => {
|
||||
this._renderChart(this.model, this.$(".chart-canvas"));
|
||||
this._renderChart(
|
||||
this.model,
|
||||
this.element.querySelector(".chart-canvas")
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
_renderChart(model, $chartCanvas) {
|
||||
if (!$chartCanvas || !$chartCanvas.length) return;
|
||||
_renderChart(model, chartCanvas) {
|
||||
if (!chartCanvas) return;
|
||||
|
||||
const context = $chartCanvas[0].getContext("2d");
|
||||
const context = chartCanvas.getContext("2d");
|
||||
|
||||
const chartData = Ember.makeArray(
|
||||
model.get("chartData") || model.get("data")
|
||||
|
||||
@ -183,6 +183,32 @@ export default Ember.Component.extend({
|
||||
},
|
||||
|
||||
actions: {
|
||||
onChangeEndDate(date) {
|
||||
const startDate = moment(this.startDate);
|
||||
const newEndDate = moment(date).endOf("day");
|
||||
|
||||
if (newEndDate.isSameOrAfter(startDate)) {
|
||||
this.set("endDate", newEndDate.format("YYYY-MM-DD"));
|
||||
} else {
|
||||
this.set("endDate", startDate.endOf("day").format("YYYY-MM-DD"));
|
||||
}
|
||||
|
||||
this.send("refreshReport");
|
||||
},
|
||||
|
||||
onChangeStartDate(date) {
|
||||
const endDate = moment(this.endDate);
|
||||
const newStartDate = moment(date).startOf("day");
|
||||
|
||||
if (newStartDate.isSameOrBefore(endDate)) {
|
||||
this.set("startDate", newStartDate.format("YYYY-MM-DD"));
|
||||
} else {
|
||||
this.set("startDate", endDate.startOf("day").format("YYYY-MM-DD"));
|
||||
}
|
||||
|
||||
this.send("refreshReport");
|
||||
},
|
||||
|
||||
applyFilter(id, value) {
|
||||
let customFilters = this.get("filters.customFilters") || {};
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ import { bufferedRender } from "discourse-common/lib/buffered-render";
|
||||
export default Ember.Component.extend(
|
||||
bufferedRender({
|
||||
classes: ["text-muted", "text-danger", "text-successful", "text-muted"],
|
||||
icons: ["circle-o", "times-circle", "circle", "circle"],
|
||||
icons: ["far-circle", "times-circle", "circle", "circle"],
|
||||
|
||||
@computed("deliveryStatuses", "model.last_delivery_status")
|
||||
status(deliveryStatuses, lastDeliveryStatus) {
|
||||
|
||||
@ -11,10 +11,10 @@ export default Ember.Component.extend({
|
||||
classNames: ["color-picker"],
|
||||
hexValueChanged: function() {
|
||||
var hex = this.hexValue;
|
||||
let $text = this.$("input.hex-input");
|
||||
let text = this.element.querySelector("input.hex-input");
|
||||
|
||||
if (this.valid) {
|
||||
$text.attr(
|
||||
text.setAttribute(
|
||||
"style",
|
||||
"color: " +
|
||||
(this.brightnessValue > 125 ? "black" : "white") +
|
||||
@ -24,10 +24,12 @@ export default Ember.Component.extend({
|
||||
);
|
||||
|
||||
if (this.pickerLoaded) {
|
||||
this.$(".picker").spectrum({ color: "#" + this.hexValue });
|
||||
$(this.element.querySelector(".picker")).spectrum({
|
||||
color: "#" + this.hexValue
|
||||
});
|
||||
}
|
||||
} else {
|
||||
$text.attr("style", "");
|
||||
text.setAttribute("style", "");
|
||||
}
|
||||
}.observes("hexValue", "brightnessValue", "valid"),
|
||||
|
||||
@ -35,7 +37,7 @@ export default Ember.Component.extend({
|
||||
loadScript("/javascripts/spectrum.js").then(() => {
|
||||
loadCSS("/javascripts/spectrum.css").then(() => {
|
||||
Ember.run.schedule("afterRender", () => {
|
||||
this.$(".picker")
|
||||
$(this.element.querySelector(".picker"))
|
||||
.spectrum({ color: "#" + this.hexValue })
|
||||
.on("change.spectrum", (me, color) => {
|
||||
this.set("hexValue", color.toHexString().replace("#", ""));
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
|
||||
export default Ember.Component.extend({
|
||||
editorId: Ember.computed.reads("fieldName"),
|
||||
|
||||
@computed("fieldName", "styles.html", "styles.css")
|
||||
resetDisabled(fieldName) {
|
||||
return (
|
||||
this.get(`styles.${fieldName}`) ===
|
||||
this.get(`styles.default_${fieldName}`)
|
||||
);
|
||||
},
|
||||
|
||||
@computed("styles", "fieldName")
|
||||
editorContents: {
|
||||
get(styles, fieldName) {
|
||||
return styles[fieldName];
|
||||
},
|
||||
set(value, styles, fieldName) {
|
||||
styles.setField(fieldName, value);
|
||||
return value;
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
reset() {
|
||||
bootbox.confirm(
|
||||
I18n.t("admin.customize.email_style.reset_confirm", {
|
||||
fieldName: I18n.t(`admin.customize.email_style.${this.fieldName}`)
|
||||
}),
|
||||
I18n.t("no_value"),
|
||||
I18n.t("yes_value"),
|
||||
result => {
|
||||
if (result) {
|
||||
this.styles.setField(
|
||||
this.fieldName,
|
||||
this.styles.get(`default_${this.fieldName}`)
|
||||
);
|
||||
this.notifyPropertyChange("editorContents");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -14,7 +14,7 @@ export default Ember.Component.extend(bufferedProperty("host"), {
|
||||
@observes("editing")
|
||||
_focusOnInput() {
|
||||
Ember.run.schedule("afterRender", () => {
|
||||
this.$(".host-name").focus();
|
||||
this.element.querySelector(".host-name").focus();
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@ -5,6 +5,6 @@ export default Ember.Component.extend({
|
||||
@on("didInsertElement")
|
||||
@observes("code")
|
||||
_refresh: function() {
|
||||
highlightSyntax(this.$());
|
||||
highlightSyntax($(this.element));
|
||||
}
|
||||
});
|
||||
|
||||
@ -23,10 +23,10 @@ export default Ember.Component.extend({
|
||||
// If we switch to edit mode, jump to the edit textarea
|
||||
if (postAction === "edit") {
|
||||
Ember.run.scheduleOnce("afterRender", () => {
|
||||
let $elem = this.$();
|
||||
let body = $elem.closest(".modal-body");
|
||||
let elem = this.element;
|
||||
let body = elem.closest(".modal-body");
|
||||
body.scrollTop(body.height());
|
||||
$elem.find(".post-editor").focus();
|
||||
elem.querySelector(".post-editor").focus();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,7 +19,9 @@ export default Ember.Component.extend({
|
||||
},
|
||||
|
||||
focusPermalink() {
|
||||
Ember.run.schedule("afterRender", () => this.$(".permalink-url").focus());
|
||||
Ember.run.schedule("afterRender", () =>
|
||||
this.element.querySelector(".permalink-url").focus()
|
||||
);
|
||||
},
|
||||
|
||||
actions: {
|
||||
@ -67,7 +69,7 @@ export default Ember.Component.extend({
|
||||
this._super(...arguments);
|
||||
|
||||
Ember.run.schedule("afterRender", () => {
|
||||
this.$(".external-url").keydown(e => {
|
||||
$(this.element.querySelector(".external-url")).keydown(e => {
|
||||
// enter key
|
||||
if (e.keyCode === 13) {
|
||||
this.send("submit");
|
||||
|
||||
@ -62,7 +62,7 @@ export default Ember.Component.extend({
|
||||
this.setProperties({ ip_address: "", formSubmitted: false });
|
||||
this.action(ScreenedIpAddress.create(result.screened_ip_address));
|
||||
Ember.run.schedule("afterRender", () =>
|
||||
this.$(".ip-address-input").focus()
|
||||
this.element.querySelector(".ip-address-input").focus()
|
||||
);
|
||||
})
|
||||
.catch(e => {
|
||||
@ -73,7 +73,9 @@ export default Ember.Component.extend({
|
||||
error: e.jqXHR.responseJSON.errors.join(". ")
|
||||
})
|
||||
: I18n.t("generic_error");
|
||||
bootbox.alert(msg, () => this.$(".ip-address-input").focus());
|
||||
bootbox.alert(msg, () =>
|
||||
this.element.querySelector(".ip-address-input").focus()
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -82,7 +84,7 @@ export default Ember.Component.extend({
|
||||
@on("didInsertElement")
|
||||
_init() {
|
||||
Ember.run.schedule("afterRender", () => {
|
||||
this.$(".ip-address-input").keydown(e => {
|
||||
$(this.element.querySelector(".ip-address-input")).keydown(e => {
|
||||
if (e.keyCode === 13) {
|
||||
this.send("submit");
|
||||
}
|
||||
|
||||
@ -3,6 +3,8 @@ import computed from "ember-addons/ember-computed-decorators";
|
||||
export default Ember.Component.extend({
|
||||
@computed()
|
||||
groupChoices() {
|
||||
return this.site.get("groups").map(g => g.name);
|
||||
return this.site.get("groups").map(g => {
|
||||
return { name: g.name, id: g.id.toString() };
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@ -9,11 +9,13 @@ export default Ember.Component.extend({
|
||||
const term = this._searchTerm();
|
||||
|
||||
if (term) {
|
||||
this.$(".site-text-id, .site-text-value").highlight(term, {
|
||||
$(
|
||||
this.element.querySelector(".site-text-id, .site-text-value")
|
||||
).highlight(term, {
|
||||
className: "text-highlight"
|
||||
});
|
||||
}
|
||||
this.$(".site-text-value").ellipsis();
|
||||
$(this.element.querySelector(".site-text-value")).ellipsis();
|
||||
},
|
||||
|
||||
click() {
|
||||
|
||||
@ -4,19 +4,23 @@ export default Ember.Component.extend({
|
||||
classNames: ["table", "staff-actions"],
|
||||
|
||||
willDestroyElement() {
|
||||
this.$().off("click.discourse-staff-logs");
|
||||
$(this.element).off("click.discourse-staff-logs");
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
|
||||
this.$().on("click.discourse-staff-logs", "[data-link-post-id]", e => {
|
||||
let postId = $(e.target).attr("data-link-post-id");
|
||||
$(this.element).on(
|
||||
"click.discourse-staff-logs",
|
||||
"[data-link-post-id]",
|
||||
e => {
|
||||
let postId = $(e.target).attr("data-link-post-id");
|
||||
|
||||
this.store.find("post", postId).then(p => {
|
||||
DiscourseURL.routeTo(p.get("url"));
|
||||
});
|
||||
return false;
|
||||
});
|
||||
this.store.find("post", postId).then(p => {
|
||||
DiscourseURL.routeTo(p.get("url"));
|
||||
});
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@ -38,8 +38,8 @@ export default Ember.Component.extend({
|
||||
},
|
||||
|
||||
animate(isInitial) {
|
||||
const $container = this.$();
|
||||
const $list = this.$(".components-list");
|
||||
const $container = $(this.element);
|
||||
const $list = $(this.element.querySelector(".components-list"));
|
||||
if ($list.length === 0 || Ember.testing) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ export default Ember.Component.extend({
|
||||
});
|
||||
this.action(WatchedWord.create(result));
|
||||
Ember.run.schedule("afterRender", () =>
|
||||
this.$(".watched-word-input").focus()
|
||||
this.element.querySelector(".watched-word-input").focus()
|
||||
);
|
||||
})
|
||||
.catch(e => {
|
||||
@ -75,7 +75,9 @@ export default Ember.Component.extend({
|
||||
error: e.jqXHR.responseJSON.errors.join(". ")
|
||||
})
|
||||
: I18n.t("generic_error");
|
||||
bootbox.alert(msg, () => this.$(".watched-word-input").focus());
|
||||
bootbox.alert(msg, () =>
|
||||
this.element.querySelector(".watched-word-input").focus()
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -84,7 +86,7 @@ export default Ember.Component.extend({
|
||||
@on("didInsertElement")
|
||||
_init() {
|
||||
Ember.run.schedule("afterRender", () => {
|
||||
this.$(".watched-word-input").keydown(e => {
|
||||
$(this.element.querySelector(".watched-word-input")).keydown(e => {
|
||||
if (e.keyCode === 13) {
|
||||
this.send("submit");
|
||||
}
|
||||
|
||||
@ -2,13 +2,13 @@ import computed from "ember-addons/ember-computed-decorators";
|
||||
import UploadMixin from "discourse/mixins/upload";
|
||||
|
||||
export default Ember.Component.extend(UploadMixin, {
|
||||
type: "csv",
|
||||
type: "txt",
|
||||
classNames: "watched-words-uploader",
|
||||
uploadUrl: "/admin/logs/watched_words/upload",
|
||||
addDisabled: Ember.computed.alias("uploading"),
|
||||
|
||||
validateUploadedFilesOptions() {
|
||||
return { csvOnly: true };
|
||||
return { skipValidation: true };
|
||||
},
|
||||
|
||||
@computed("actionKey")
|
||||
|
||||
@ -29,7 +29,7 @@ export default Ember.Controller.extend({
|
||||
I18n.t("yes_value"),
|
||||
confirmed => {
|
||||
if (confirmed) {
|
||||
Discourse.User.currentProp("hideReadOnlyAlert", true);
|
||||
this.set("currentUser.hideReadOnlyAlert", true);
|
||||
this._toggleReadOnlyMode(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
@computed("model.isSaving")
|
||||
saveButtonText(isSaving) {
|
||||
return isSaving ? I18n.t("saving") : I18n.t("admin.customize.save");
|
||||
},
|
||||
|
||||
@computed("model.changed", "model.isSaving")
|
||||
saveDisabled(changed, isSaving) {
|
||||
return !changed || isSaving;
|
||||
},
|
||||
|
||||
actions: {
|
||||
save() {
|
||||
if (!this.model.saving) {
|
||||
this.set("saving", true);
|
||||
this.model
|
||||
.update(this.model.getProperties("html", "css"))
|
||||
.catch(e => {
|
||||
const msg =
|
||||
e.jqXHR.responseJSON && e.jqXHR.responseJSON.errors
|
||||
? I18n.t("admin.customize.email_style.save_error_with_reason", {
|
||||
error: e.jqXHR.responseJSON.errors.join(". ")
|
||||
})
|
||||
: I18n.t("generic_error");
|
||||
bootbox.alert(msg);
|
||||
})
|
||||
.finally(() => this.set("model.changed", false));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -6,5 +6,11 @@ export default Ember.Controller.extend({
|
||||
this._super(...arguments);
|
||||
|
||||
this.titleSorting = ["title"];
|
||||
},
|
||||
|
||||
actions: {
|
||||
selectTemplate(template) {
|
||||
this.transitionToRoute("adminCustomizeEmailTemplates.edit", template);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { bufferedProperty } from "discourse/mixins/buffered-content";
|
||||
import { propertyEqual } from "discourse/lib/computed";
|
||||
|
||||
export default Ember.Controller.extend(bufferedProperty("model"), {
|
||||
saved: false,
|
||||
isSaving: false,
|
||||
saveDisabled: propertyEqual("model.robots_txt", "buffered.robots_txt"),
|
||||
resetDisbaled: Ember.computed.not("model.overridden"),
|
||||
|
||||
actions: {
|
||||
save() {
|
||||
this.setProperties({
|
||||
isSaving: true,
|
||||
saved: false
|
||||
});
|
||||
|
||||
ajax("robots.json", {
|
||||
method: "PUT",
|
||||
data: { robots_txt: this.buffered.get("robots_txt") }
|
||||
})
|
||||
.then(data => {
|
||||
this.commitBuffer();
|
||||
this.set("saved", true);
|
||||
this.set("model.overridden", data.overridden);
|
||||
})
|
||||
.finally(() => this.set("isSaving", false));
|
||||
},
|
||||
|
||||
reset() {
|
||||
this.setProperties({
|
||||
isSaving: true,
|
||||
saved: false
|
||||
});
|
||||
ajax("robots.json", { method: "DELETE" })
|
||||
.then(data => {
|
||||
this.buffered.set("robots_txt", data.robots_txt);
|
||||
this.commitBuffer();
|
||||
this.set("saved", true);
|
||||
this.set("model.overridden", false);
|
||||
})
|
||||
.finally(() => this.set("isSaving", false));
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -5,11 +5,11 @@ import Report from "admin/models/report";
|
||||
import PeriodComputationMixin from "admin/mixins/period-computation";
|
||||
|
||||
function staticReport(reportType) {
|
||||
return function() {
|
||||
return Ember.computed("reports.[]", function() {
|
||||
return Ember.makeArray(this.reports).find(
|
||||
report => report.type === reportType
|
||||
);
|
||||
}.property("reports.[]");
|
||||
});
|
||||
}
|
||||
|
||||
export default Ember.Controller.extend(PeriodComputationMixin, {
|
||||
|
||||
@ -1,21 +1,15 @@
|
||||
import { exportEntity } from "discourse/lib/export-csv";
|
||||
import { outputExportResult } from "discourse/lib/export-result";
|
||||
import StaffActionLog from "admin/models/staff-action-log";
|
||||
import {
|
||||
default as computed,
|
||||
on
|
||||
} from "ember-addons/ember-computed-decorators";
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
loading: false,
|
||||
filters: null,
|
||||
userHistoryActions: [],
|
||||
model: null,
|
||||
nextPage: 0,
|
||||
lastPage: null,
|
||||
|
||||
filters: null,
|
||||
filtersExists: Ember.computed.gt("filterCount", 0),
|
||||
showTable: Ember.computed.gt("model.length", 0),
|
||||
userHistoryActions: null,
|
||||
|
||||
@computed("filters.action_name")
|
||||
actionFilter(name) {
|
||||
@ -25,34 +19,21 @@ export default Ember.Controller.extend({
|
||||
@on("init")
|
||||
resetFilters() {
|
||||
this.setProperties({
|
||||
filters: Ember.Object.create(),
|
||||
model: [],
|
||||
nextPage: 0,
|
||||
lastPage: null
|
||||
model: Ember.Object.create({ loadingMore: true }),
|
||||
filters: Ember.Object.create()
|
||||
});
|
||||
this.scheduleRefresh();
|
||||
},
|
||||
|
||||
_changeFilters(props) {
|
||||
this.set("model", Ember.Object.create({ loadingMore: true }));
|
||||
this.filters.setProperties(props);
|
||||
this.setProperties({
|
||||
model: [],
|
||||
nextPage: 0,
|
||||
lastPage: null
|
||||
});
|
||||
this.scheduleRefresh();
|
||||
},
|
||||
|
||||
_refresh() {
|
||||
if (this.lastPage && this.nextPage >= this.lastPage) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.set("loading", true);
|
||||
|
||||
const page = this.nextPage;
|
||||
let filters = this.filters;
|
||||
let params = { page };
|
||||
let params = {};
|
||||
let count = 0;
|
||||
|
||||
// Don't send null values
|
||||
@ -65,32 +46,23 @@ export default Ember.Controller.extend({
|
||||
});
|
||||
this.set("filterCount", count);
|
||||
|
||||
StaffActionLog.findAll(params)
|
||||
.then(result => {
|
||||
this.setProperties({
|
||||
model: this.model.concat(result.staff_action_logs),
|
||||
nextPage: page + 1
|
||||
});
|
||||
this.store.findAll("staff-action-log", params).then(result => {
|
||||
this.set("model", result);
|
||||
|
||||
if (result.staff_action_logs.length === 0) {
|
||||
this.set("lastPage", page);
|
||||
}
|
||||
|
||||
if (this.userHistoryActions.length === 0) {
|
||||
this.set(
|
||||
"userHistoryActions",
|
||||
result.user_history_actions
|
||||
.map(action => ({
|
||||
id: action.id,
|
||||
action_id: action.action_id,
|
||||
name: I18n.t("admin.logs.staff_actions.actions." + action.id),
|
||||
name_raw: action.id
|
||||
}))
|
||||
.sort((a, b) => (a.name > b.name ? 1 : -1))
|
||||
);
|
||||
}
|
||||
})
|
||||
.finally(() => this.set("loading", false));
|
||||
if (!this.userHistoryActions) {
|
||||
this.set(
|
||||
"userHistoryActions",
|
||||
result.extras.user_history_actions
|
||||
.map(action => ({
|
||||
id: action.id,
|
||||
action_id: action.action_id,
|
||||
name: I18n.t("admin.logs.staff_actions.actions." + action.id),
|
||||
name_raw: action.id
|
||||
}))
|
||||
.sort((a, b) => a.name.localeCompare(b.name))
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
scheduleRefresh() {
|
||||
@ -153,7 +125,7 @@ export default Ember.Controller.extend({
|
||||
},
|
||||
|
||||
loadMore() {
|
||||
this._refresh();
|
||||
this.model.loadMore();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -134,7 +134,7 @@ export default Ember.Controller.extend(CanCheckEmails, {
|
||||
return this.model.resetBounceScore();
|
||||
},
|
||||
approve() {
|
||||
return this.model.approve();
|
||||
return this.model.approve(this.currentUser);
|
||||
},
|
||||
deactivate() {
|
||||
return this.model.deactivate();
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
import WatchedWord from "admin/models/watched-word";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { fmt } from "discourse/lib/computed";
|
||||
import showModal from "discourse/lib/show-modal";
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
actionNameKey: null,
|
||||
@ -8,6 +11,10 @@ export default Ember.Controller.extend({
|
||||
"adminWatchedWords.filtered",
|
||||
"adminWatchedWords.showWords"
|
||||
),
|
||||
downloadLink: fmt(
|
||||
"actionNameKey",
|
||||
"/admin/logs/watched_words/action/%@/download"
|
||||
),
|
||||
|
||||
findAction(actionName) {
|
||||
return (this.get("adminWatchedWords.model") || []).findBy(
|
||||
@ -17,13 +24,13 @@ export default Ember.Controller.extend({
|
||||
},
|
||||
|
||||
@computed("actionNameKey", "adminWatchedWords.model")
|
||||
filteredContent(actionNameKey) {
|
||||
if (!actionNameKey) {
|
||||
return [];
|
||||
}
|
||||
currentAction(actionName) {
|
||||
return this.findAction(actionName);
|
||||
},
|
||||
|
||||
const a = this.findAction(actionNameKey);
|
||||
return a ? a.words : [];
|
||||
@computed("currentAction.words.[]", "adminWatchedWords.model")
|
||||
filteredContent(words) {
|
||||
return words || [];
|
||||
},
|
||||
|
||||
@computed("actionNameKey")
|
||||
@ -31,10 +38,9 @@ export default Ember.Controller.extend({
|
||||
return I18n.t("admin.watched_words.action_descriptions." + actionNameKey);
|
||||
},
|
||||
|
||||
@computed("actionNameKey", "adminWatchedWords.model")
|
||||
wordCount(actionNameKey) {
|
||||
const a = this.findAction(actionNameKey);
|
||||
return a ? a.words.length : 0;
|
||||
@computed("currentAction.count")
|
||||
wordCount(count) {
|
||||
return count || 0;
|
||||
},
|
||||
|
||||
actions: {
|
||||
@ -62,10 +68,9 @@ export default Ember.Controller.extend({
|
||||
},
|
||||
|
||||
recordRemoved(arg) {
|
||||
const a = this.findAction(this.actionNameKey);
|
||||
if (a) {
|
||||
a.words.removeObject(arg);
|
||||
a.decrementProperty("count");
|
||||
if (this.currentAction) {
|
||||
this.currentAction.words.removeObject(arg);
|
||||
this.currentAction.decrementProperty("count");
|
||||
}
|
||||
},
|
||||
|
||||
@ -73,6 +78,40 @@ export default Ember.Controller.extend({
|
||||
WatchedWord.findAll().then(data => {
|
||||
this.set("adminWatchedWords.model", data);
|
||||
});
|
||||
},
|
||||
|
||||
clearAll() {
|
||||
const actionKey = this.actionNameKey;
|
||||
bootbox.confirm(
|
||||
I18n.t(`admin.watched_words.clear_all_confirm_${actionKey}`),
|
||||
I18n.t("no_value"),
|
||||
I18n.t("yes_value"),
|
||||
result => {
|
||||
if (result) {
|
||||
ajax(`/admin/logs/watched_words/action/${actionKey}.json`, {
|
||||
method: "DELETE"
|
||||
}).then(() => {
|
||||
const action = this.findAction(actionKey);
|
||||
if (action) {
|
||||
action.setProperties({
|
||||
words: [],
|
||||
count: 0
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
test() {
|
||||
WatchedWord.findAll().then(data => {
|
||||
this.set("adminWatchedWords.model", data);
|
||||
showModal("admin-watched-word-test", {
|
||||
admin: true,
|
||||
model: this.currentAction
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
application: Ember.inject.controller(),
|
||||
router: Ember.inject.service(),
|
||||
|
||||
@computed("siteSettings.enable_group_directory")
|
||||
showGroups(enableGroupDirectory) {
|
||||
@ -13,7 +13,7 @@ export default Ember.Controller.extend({
|
||||
return this.currentUser.get("admin") && enableBadges;
|
||||
},
|
||||
|
||||
@computed("application.currentPath")
|
||||
@computed("router._router.currentPath")
|
||||
adminContentsClassName(currentPath) {
|
||||
let cssClasses = currentPath
|
||||
.split(".")
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
import { default as computed } from "ember-addons/ember-computed-decorators";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
|
||||
export default Ember.Controller.extend(ModalFunctionality, {
|
||||
@computed("value", "model.compiledRegularExpression")
|
||||
matches(value, regexpString) {
|
||||
if (!value || !regexpString) return;
|
||||
let censorRegexp = new RegExp(regexpString, "ig");
|
||||
return value.match(censorRegexp);
|
||||
}
|
||||
});
|
||||
@ -90,7 +90,7 @@ export default Ember.Mixin.create({
|
||||
},
|
||||
|
||||
_watchEnterKey: function() {
|
||||
this.$().on("keydown.setting-enter", ".input-setting-string", e => {
|
||||
$(this.element).on("keydown.setting-enter", ".input-setting-string", e => {
|
||||
if (e.keyCode === 13) {
|
||||
// enter key
|
||||
this.send("save");
|
||||
@ -99,7 +99,7 @@ export default Ember.Mixin.create({
|
||||
}.on("didInsertElement"),
|
||||
|
||||
_removeBindings: function() {
|
||||
this.$().off("keydown.setting-enter");
|
||||
$(this.element).off("keydown.setting-enter");
|
||||
}.on("willDestroyElement"),
|
||||
|
||||
_save() {
|
||||
|
||||
@ -227,14 +227,14 @@ const AdminUser = Discourse.User.extend({
|
||||
.catch(popupAjaxError);
|
||||
},
|
||||
|
||||
approve() {
|
||||
approve(approvedBy) {
|
||||
return ajax(`/admin/users/${this.id}/approve`, {
|
||||
type: "PUT"
|
||||
}).then(() => {
|
||||
this.setProperties({
|
||||
can_approve: false,
|
||||
approved: true,
|
||||
approved_by: Discourse.User.current()
|
||||
approved_by: approvedBy
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
@ -3,7 +3,7 @@ import {
|
||||
observes,
|
||||
on
|
||||
} from "ember-addons/ember-computed-decorators";
|
||||
import { propertyNotEqual, i18n } from "discourse/lib/computed";
|
||||
import { propertyNotEqual } from "discourse/lib/computed";
|
||||
|
||||
const ColorSchemeColor = Discourse.Model.extend({
|
||||
@on("init")
|
||||
@ -42,9 +42,23 @@ const ColorSchemeColor = Discourse.Model.extend({
|
||||
}
|
||||
},
|
||||
|
||||
translatedName: i18n("name", "admin.customize.colors.%@.name"),
|
||||
@computed("name")
|
||||
translatedName(name) {
|
||||
if (!this.is_advanced) {
|
||||
return I18n.t(`admin.customize.colors.${name}.name`);
|
||||
} else {
|
||||
return name;
|
||||
}
|
||||
},
|
||||
|
||||
description: i18n("name", "admin.customize.colors.%@.description"),
|
||||
@computed("name")
|
||||
description(name) {
|
||||
if (!this.is_advanced) {
|
||||
return I18n.t(`admin.customize.colors.${name}.description`);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
brightness returns a number between 0 (darkest) to 255 (brightest).
|
||||
|
||||
@ -128,7 +128,8 @@ ColorScheme.reopenClass({
|
||||
return ColorSchemeColor.create({
|
||||
name: c.name,
|
||||
hex: c.hex,
|
||||
default_hex: c.default_hex
|
||||
default_hex: c.default_hex,
|
||||
is_advanced: c.is_advanced
|
||||
});
|
||||
})
|
||||
})
|
||||
|
||||
10
app/assets/javascripts/admin/models/email-style.js.es6
Normal file
10
app/assets/javascripts/admin/models/email-style.js.es6
Normal file
@ -0,0 +1,10 @@
|
||||
import RestModel from "discourse/models/rest";
|
||||
|
||||
export default RestModel.extend({
|
||||
changed: false,
|
||||
|
||||
setField(fieldName, value) {
|
||||
this.set(`${fieldName}`, value);
|
||||
this.set("changed", true);
|
||||
}
|
||||
});
|
||||
@ -2,6 +2,7 @@ import computed from "ember-addons/ember-computed-decorators";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import AdminUser from "admin/models/admin-user";
|
||||
import { escapeExpression } from "discourse/lib/utilities";
|
||||
import RestModel from "discourse/models/rest";
|
||||
|
||||
function format(label, value, escape = true) {
|
||||
return value
|
||||
@ -9,7 +10,7 @@ function format(label, value, escape = true) {
|
||||
: "";
|
||||
}
|
||||
|
||||
const StaffActionLog = Discourse.Model.extend({
|
||||
const StaffActionLog = RestModel.extend({
|
||||
showFullDetails: false,
|
||||
|
||||
@computed("action_name")
|
||||
@ -80,16 +81,14 @@ const StaffActionLog = Discourse.Model.extend({
|
||||
});
|
||||
|
||||
StaffActionLog.reopenClass({
|
||||
create(attrs) {
|
||||
attrs = attrs || {};
|
||||
|
||||
if (attrs.acting_user) {
|
||||
attrs.acting_user = AdminUser.create(attrs.acting_user);
|
||||
munge(json) {
|
||||
if (json.acting_user) {
|
||||
json.acting_user = AdminUser.create(json.acting_user);
|
||||
}
|
||||
if (attrs.target_user) {
|
||||
attrs.target_user = AdminUser.create(attrs.target_user);
|
||||
if (json.target_user) {
|
||||
json.target_user = AdminUser.create(json.target_user);
|
||||
}
|
||||
return this._super(attrs);
|
||||
return json;
|
||||
},
|
||||
|
||||
findAll(data) {
|
||||
|
||||
@ -42,7 +42,8 @@ WatchedWord.reopenClass({
|
||||
name: I18n.t("admin.watched_words.actions." + n),
|
||||
words: actions[n],
|
||||
count: actions[n].length,
|
||||
regularExpressions: list.regular_expressions
|
||||
regularExpressions: list.regular_expressions,
|
||||
compiledRegularExpression: list.compiled_regular_expressions[n]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
export default Ember.Route.extend({
|
||||
model(params) {
|
||||
return {
|
||||
model: this.modelFor("adminCustomizeEmailStyle"),
|
||||
fieldName: params.field_name
|
||||
};
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
controller.setProperties({
|
||||
fieldName: model.fieldName,
|
||||
model: model.model
|
||||
});
|
||||
this._shouldAlertUnsavedChanges = true;
|
||||
},
|
||||
|
||||
actions: {
|
||||
willTransition(transition) {
|
||||
if (
|
||||
this.get("controller.model.changed") &&
|
||||
this._shouldAlertUnsavedChanges &&
|
||||
transition.intent.name !== this.routeName
|
||||
) {
|
||||
transition.abort();
|
||||
bootbox.confirm(
|
||||
I18n.t("admin.customize.theme.unsaved_changes_alert"),
|
||||
I18n.t("admin.customize.theme.discard"),
|
||||
I18n.t("admin.customize.theme.stay"),
|
||||
result => {
|
||||
if (!result) {
|
||||
this._shouldAlertUnsavedChanges = false;
|
||||
transition.retry();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,9 @@
|
||||
export default Ember.Route.extend({
|
||||
model() {
|
||||
return this.store.find("email-style");
|
||||
},
|
||||
|
||||
redirect() {
|
||||
this.transitionTo("adminCustomizeEmailStyle.edit", "html");
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,7 @@
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
|
||||
export default Ember.Route.extend({
|
||||
model() {
|
||||
return ajax("/admin/customize/robots");
|
||||
}
|
||||
});
|
||||
@ -86,6 +86,17 @@ export default function() {
|
||||
this.route("edit", { path: "/:id" });
|
||||
}
|
||||
);
|
||||
this.route("adminCustomizeRobotsTxt", {
|
||||
path: "/robots",
|
||||
resetNamespace: true
|
||||
});
|
||||
this.route(
|
||||
"adminCustomizeEmailStyle",
|
||||
{ path: "/email_style", resetNamespace: true },
|
||||
function() {
|
||||
this.route("edit", { path: "/:field_name" });
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ export default Discourse.Route.extend({
|
||||
},
|
||||
|
||||
sendInvites() {
|
||||
this.transitionTo("userInvited", Discourse.User.current());
|
||||
this.transitionTo("userInvited", this.currentUser);
|
||||
},
|
||||
|
||||
deleteUser(user) {
|
||||
|
||||
@ -130,9 +130,7 @@
|
||||
</span>
|
||||
|
||||
<div class="input">
|
||||
{{date-picker-past
|
||||
value=startDate
|
||||
defaultDate=startDate}}
|
||||
{{date-input date=startDate onChange=(action "onChangeStartDate")}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -142,9 +140,7 @@
|
||||
</span>
|
||||
|
||||
<div class="input">
|
||||
{{date-picker-past
|
||||
value=endDate
|
||||
defaultDate=endDate}}
|
||||
{{date-input date=endDate onChange=(action "onChangeEndDate")}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
<div class='row'>
|
||||
<div class='admin-controls'>
|
||||
<nav>
|
||||
<ul class='nav nav-pills'>
|
||||
<li>{{#link-to 'adminCustomizeEmailStyle.edit' 'html' replace=true}}{{i18n 'admin.customize.email_style.html'}}{{/link-to}}</li>
|
||||
<li>{{#link-to 'adminCustomizeEmailStyle.edit' 'css' replace=true}}{{i18n 'admin.customize.email_style.css'}}{{/link-to}}</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ace-editor content=editorContents mode=fieldName editorId=editorId}}
|
||||
|
||||
<div class='admin-footer'>
|
||||
<div class='buttons'>
|
||||
{{#d-button action=(action "reset") disabled=resetDisabled class='btn-default'}}
|
||||
{{i18n 'admin.customize.email_style.reset'}}
|
||||
{{/d-button}}
|
||||
</div>
|
||||
</div>
|
||||
@ -1,3 +1,3 @@
|
||||
{{list-setting settingValue=value choices=groupChoices settingName=setting.setting}}
|
||||
{{list-setting settingValue=value choices=groupChoices settingName='name'}}
|
||||
{{setting-validation-message message=validationMessage}}
|
||||
<div class='desc'>{{{unbound setting.description}}}</div>
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
<label class="btn btn-default {{if addDisabled 'disabled'}}">
|
||||
{{d-icon "upload"}}
|
||||
{{i18n 'admin.watched_words.form.upload'}}
|
||||
<input class="hidden-upload-field" disabled={{addDisabled}} type="file" accept="text/plain,text/csv" />
|
||||
<input class="hidden-upload-field" disabled={{addDisabled}} type="file" accept="text/plain" />
|
||||
</label>
|
||||
<br/>
|
||||
<span class="instructions">One word per line</span>
|
||||
<span class="instructions">{{i18n 'admin.watched_words.one_word_per_line'}}</span>
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
<button {{action "save"}} disabled={{model.disableSave}} class='btn btn-primary'>{{i18n 'admin.customize.save'}}</button>
|
||||
{{/unless}}
|
||||
<button {{action "copy" model}} class='btn btn-default'>{{d-icon "copy"}} {{i18n 'admin.customize.copy'}}</button>
|
||||
<button {{action "copyToClipboard" model}} class='btn btn-default'>{{d-icon "clipboard"}} {{i18n 'admin.customize.copy_to_clipboard'}}</button>
|
||||
<button {{action "copyToClipboard" model}} class='btn btn-default'>{{d-icon "far-clipboard"}} {{i18n 'admin.customize.copy_to_clipboard'}}</button>
|
||||
{{#if model.theme_id}}
|
||||
{{i18n "admin.customize.theme_owner"}}
|
||||
{{#link-to "adminCustomizeThemes.show" model.theme_id}}{{model.theme_name}}{{/link-to}}
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
{{email-styles-editor styles=model fieldName=fieldName}}
|
||||
|
||||
<div class='admin-footer'>
|
||||
<div class='buttons'>
|
||||
{{#d-button action=(action "save") disabled=saveDisabled class='btn-primary'}}
|
||||
{{saveButtonText}}
|
||||
{{/d-button}}
|
||||
</div>
|
||||
</div>
|
||||
@ -0,0 +1,7 @@
|
||||
<div class='row'>
|
||||
<h2>{{i18n 'admin.customize.email_style.heading'}}</h2>
|
||||
|
||||
<p>{{i18n 'admin.customize.email_style.instructions'}}</p>
|
||||
</div>
|
||||
|
||||
{{outlet}}
|
||||
@ -1,15 +1,8 @@
|
||||
<div class='row'>
|
||||
<div class='content-list'>
|
||||
<ul>
|
||||
{{#each sortedTemplates as |et|}}
|
||||
<li>
|
||||
{{#link-to 'adminCustomizeEmailTemplates.edit' et}}{{et.title}}{{/link-to}}
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
{{combo-box
|
||||
content=sortedTemplates
|
||||
valueAttribute="id"
|
||||
nameProperty="title"
|
||||
onSelect=(action "selectTemplate")
|
||||
}}
|
||||
|
||||
<div class='content-editor'>
|
||||
{{outlet}}
|
||||
</div>
|
||||
</div>
|
||||
{{outlet}}
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
<div class="robots-txt-edit">
|
||||
<h3>{{i18n "admin.customize.robots.title"}}</h3>
|
||||
<p>{{i18n "admin.customize.robots.warning"}}</p>
|
||||
{{#if model.overridden}}
|
||||
<div class="overridden">
|
||||
{{i18n "admin.customize.robots.overridden"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{textarea
|
||||
value=buffered.robots_txt
|
||||
class="robots-txt-input"}}
|
||||
{{#save-controls model=this action=(action "save") saved=saved saveDisabled=saveDisabled}}
|
||||
{{d-button
|
||||
class="btn-default"
|
||||
disabled=resetDisbaled
|
||||
icon="undo"
|
||||
action=(action "reset")
|
||||
label="admin.settings.reset"}}
|
||||
{{/save-controls}}
|
||||
</div>
|
||||
@ -3,6 +3,7 @@
|
||||
{{nav-item route='adminCustomize.colors' label='admin.customize.colors.title'}}
|
||||
{{nav-item route='adminSiteText' label='admin.site_text.title'}}
|
||||
{{nav-item route='adminCustomizeEmailTemplates' label='admin.customize.email_templates.title'}}
|
||||
{{nav-item route='adminCustomizeEmailStyle' label='admin.customize.email_style.title'}}
|
||||
{{nav-item route='adminUserFields' label='admin.user_fields.title'}}
|
||||
{{nav-item route='adminEmojis' label='admin.emoji.title'}}
|
||||
{{nav-item route='adminPermalinks' label='admin.permalink.title'}}
|
||||
|
||||
@ -117,13 +117,15 @@
|
||||
<h4>{{i18n "admin.dashboard.last_updated"}} </h4>
|
||||
<p>{{format-date model.attributes.updated_at leaveAgo="true"}}</p>
|
||||
</div>
|
||||
<div>
|
||||
<h4>{{i18n "admin.dashboard.discourse_last_updated"}} </h4>
|
||||
<p>{{format-date model.attributes.discourse_updated_at leaveAgo="true"}}</p>
|
||||
<a rel="noopener" target="_blank" href={{model.attributes.release_notes_link}} class="btn btn-default">
|
||||
{{i18n "admin.dashboard.whats_new_in_discourse"}}
|
||||
</a>
|
||||
</div>
|
||||
{{#if model.attributes.discourse_updated_at}}
|
||||
<div>
|
||||
<h4>{{i18n "admin.dashboard.discourse_last_updated"}} </h4>
|
||||
<p>{{format-date model.attributes.discourse_updated_at leaveAgo="true"}}</p>
|
||||
<a rel="noopener" target="_blank" href={{model.attributes.release_notes_link}} class="btn btn-default">
|
||||
{{i18n "admin.dashboard.whats_new_in_discourse"}}
|
||||
</a>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -6,13 +6,15 @@
|
||||
{{date-picker-past value=lastSeen id="last-seen"}}
|
||||
<label>{{i18n 'admin.email.user'}}:</label>
|
||||
{{user-selector single="true" usernames=username canReceiveUpdates="true"}}
|
||||
<button class='btn' {{action "refresh"}}>{{i18n 'admin.email.refresh'}}</button>
|
||||
<button class='btn btn-primary digest-refresh-button' {{action "refresh"}}>{{i18n 'admin.email.refresh'}}</button>
|
||||
<div class="toggle">
|
||||
<label>{{i18n 'admin.email.format'}}</label>
|
||||
{{#if showHtml}}
|
||||
<span>{{i18n 'admin.email.html'}}</span> | <a href {{action "toggleShowHtml"}}>{{i18n 'admin.email.text'}}</a>
|
||||
<span>{{i18n 'admin.email.html'}}</span> | <a href
|
||||
{{action "toggleShowHtml"}}>{{i18n 'admin.email.text'}}</a>
|
||||
{{else}}
|
||||
<a href {{action "toggleShowHtml"}}>{{i18n 'admin.email.html'}}</a> | <span>{{i18n 'admin.email.text'}}</span>
|
||||
<a href {{action "toggleShowHtml"}}>{{i18n 'admin.email.html'}}</a> |
|
||||
<span>{{i18n 'admin.email.text'}}</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
@ -20,35 +22,33 @@
|
||||
|
||||
{{#conditional-loading-spinner condition=loading}}
|
||||
|
||||
<div class="email-preview-digest">
|
||||
{{#if showSendEmailForm}}
|
||||
<br/>
|
||||
<div class="controls">
|
||||
{{#if sendingEmail}}
|
||||
{{i18n 'admin.email.sending_test'}}
|
||||
{{else}}
|
||||
<label>{{i18n 'admin.email.send_digest_label'}}</label>
|
||||
{{text-field value=email placeholderKey="admin.email.test_email_address"}}
|
||||
<button class='btn btn-default' {{action "sendEmail"}} disabled={{sendEmailDisabled}}>{{i18n 'admin.email.send_digest'}}</button>
|
||||
{{#if sentEmail}}
|
||||
<span class='result-message'>{{i18n 'admin.email.sent_test'}}</span>
|
||||
<div class="email-preview-digest">
|
||||
{{#if showSendEmailForm}}
|
||||
<div class="controls">
|
||||
{{#if sendingEmail}}
|
||||
{{i18n 'admin.email.sending_test'}}
|
||||
{{else}}
|
||||
<label>{{i18n 'admin.email.send_digest_label'}}</label>
|
||||
{{text-field value=email placeholderKey="admin.email.test_email_address"}}
|
||||
<button class='btn btn-default' {{action "sendEmail"}} disabled={{sendEmailDisabled}}>{{i18n 'admin.email.send_digest'}}</button>
|
||||
{{#if sentEmail}}
|
||||
<span class='result-message'>{{i18n 'admin.email.sent_test'}}</span>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="preview-output">
|
||||
{{#if showHtml}}
|
||||
{{#if htmlEmpty}}
|
||||
<p>{{i18n 'admin.email.no_result'}}</p>
|
||||
{{else}}
|
||||
<iframe srcdoc={{model.html_content}} />
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<pre>{{{model.text_content}}}</pre>
|
||||
{{/if}}
|
||||
</div>
|
||||
<br/>
|
||||
{{/if}}
|
||||
|
||||
<div class="preview-output">
|
||||
{{#if showHtml}}
|
||||
{{#if htmlEmpty}}
|
||||
<p>{{i18n 'admin.email.no_result'}}</p>
|
||||
{{else}}
|
||||
<iframe srcdoc={{model.html_content}} />
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<pre>{{{model.text_content}}}</pre>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{/conditional-loading-spinner}}
|
||||
{{/conditional-loading-spinner}}
|
||||
@ -39,70 +39,66 @@
|
||||
|
||||
{{#staff-actions}}
|
||||
|
||||
{{#load-more selector=".staff-logs tr" action=(action "loadMore")}}
|
||||
{{#if showTable}}
|
||||
<table class='table staff-logs grid'>
|
||||
|
||||
<thead>
|
||||
<th>{{i18n 'admin.logs.staff_actions.staff_user'}}</th>
|
||||
<th>{{i18n 'admin.logs.action'}}</th>
|
||||
<th>{{i18n 'admin.logs.staff_actions.subject'}}</th>
|
||||
<th>{{i18n 'admin.logs.staff_actions.when'}}</th>
|
||||
<th>{{i18n 'admin.logs.staff_actions.details'}}</th>
|
||||
<th>{{i18n 'admin.logs.staff_actions.context'}}</th>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{{#each model as |item|}}
|
||||
<tr class='admin-list-item'>
|
||||
<td class="staff-users">
|
||||
<div class="staff-user">
|
||||
{{#if item.acting_user}}
|
||||
{{#link-to 'adminUser' item.acting_user}}{{avatar item.acting_user imageSize="tiny"}}{{/link-to}}
|
||||
<a {{action "filterByStaffUser" item.acting_user}}>{{item.acting_user.username}}</a>
|
||||
{{else}}
|
||||
<span class="deleted-user" title="{{i18n 'admin.user.deleted'}}">
|
||||
{{d-icon "far-trash-alt"}}
|
||||
</span>
|
||||
{{#load-more selector=".staff-logs tr" action=(action "loadMore")}}
|
||||
{{#if model.content}}
|
||||
<table class='table staff-logs grid'>
|
||||
<thead>
|
||||
<th>{{i18n 'admin.logs.staff_actions.staff_user'}}</th>
|
||||
<th>{{i18n 'admin.logs.action'}}</th>
|
||||
<th>{{i18n 'admin.logs.staff_actions.subject'}}</th>
|
||||
<th>{{i18n 'admin.logs.staff_actions.when'}}</th>
|
||||
<th>{{i18n 'admin.logs.staff_actions.details'}}</th>
|
||||
<th>{{i18n 'admin.logs.staff_actions.context'}}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each model.content as |item|}}
|
||||
<tr class='admin-list-item'>
|
||||
<td class="staff-users">
|
||||
<div class="staff-user">
|
||||
{{#if item.acting_user}}
|
||||
{{#link-to 'adminUser' item.acting_user}}{{avatar item.acting_user imageSize="tiny"}}{{/link-to}}
|
||||
<a {{action "filterByStaffUser" item.acting_user}}>{{item.acting_user.username}}</a>
|
||||
{{else}}
|
||||
<span class="deleted-user" title="{{i18n 'admin.user.deleted'}}">
|
||||
{{d-icon "far-trash-alt"}}
|
||||
</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
</td>
|
||||
<td class="col value action">
|
||||
<a {{action "filterByAction" item}}>{{item.actionName}}</a>
|
||||
</td>
|
||||
<td class="col value subject">
|
||||
<div class="subject">
|
||||
{{#if item.target_user}}
|
||||
{{#link-to 'adminUser' item.target_user}}{{avatar item.target_user imageSize="tiny"}}{{/link-to}}
|
||||
<a {{action "filterByTargetUser" item.target_user}}>{{item.target_user.username}}</a>
|
||||
{{/if}}
|
||||
{{#if item.subject}}
|
||||
<a {{action "filterBySubject" item.subject}} title={{item.subject}}>{{item.subject}}</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</td>
|
||||
<td class="col value created-at">{{age-with-tooltip item.created_at}}</td>
|
||||
<td class="col value details">
|
||||
{{{item.formattedDetails}}}
|
||||
{{#if item.useCustomModalForDetails}}
|
||||
<a {{action "showCustomDetailsModal" item}}>{{d-icon "info-circle"}} {{i18n 'admin.logs.staff_actions.show'}}</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</td>
|
||||
<td class="col value action">
|
||||
<a {{action "filterByAction" item}}>{{item.actionName}}</a>
|
||||
</td>
|
||||
<td class="col value subject">
|
||||
<div class="subject">
|
||||
|
||||
{{#if item.target_user}}
|
||||
{{#link-to 'adminUser' item.target_user}}{{avatar item.target_user imageSize="tiny"}}{{/link-to}}
|
||||
<a {{action "filterByTargetUser" item.target_user}}>{{item.target_user.username}}</a>
|
||||
{{/if}}
|
||||
{{#if item.subject}}
|
||||
<a {{action "filterBySubject" item.subject}} title={{item.subject}}>{{item.subject}}</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</td>
|
||||
<td class="col value created-at">{{age-with-tooltip item.created_at}}</td>
|
||||
<td class="col value details">
|
||||
{{{item.formattedDetails}}}
|
||||
{{#if item.useCustomModalForDetails}}
|
||||
<a {{action "showCustomDetailsModal" item}}>{{d-icon "info-circle"}} {{i18n 'admin.logs.staff_actions.show'}}</a>
|
||||
{{/if}}
|
||||
{{#if item.useModalForDetails}}
|
||||
<a {{action "showDetailsModal" item}}>{{d-icon "info-circle"}} {{i18n 'admin.logs.staff_actions.show'}}</a>
|
||||
{{/if}}
|
||||
</td>
|
||||
<td class="col value context">{{item.context}}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
{{else}}
|
||||
{{i18n 'search.no_results'}}
|
||||
{{/if}}
|
||||
|
||||
{{conditional-loading-spinner condition=loading}}
|
||||
{{/load-more}}
|
||||
{{#if item.useModalForDetails}}
|
||||
<a {{action "showDetailsModal" item}}>{{d-icon "info-circle"}} {{i18n 'admin.logs.staff_actions.show'}}</a>
|
||||
{{/if}}
|
||||
</td>
|
||||
<td class="col value context">{{item.context}}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{else if model.loadingMore}}
|
||||
{{conditional-loading-spinner condition=model.loadingMore}}
|
||||
{{else}}
|
||||
{{i18n 'search.no_results'}}
|
||||
{{/if}}
|
||||
{{/load-more}}
|
||||
|
||||
{{/staff-actions}}
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
|
||||
{{#if local}}
|
||||
<div class="inputs">
|
||||
<input onchange={{action "uploadLocaleFile"}} type="file" id="file-input" accept='.dcstyle.json,application/json,.tar.gz,application/x-gzip'><br>
|
||||
<input onchange={{action "uploadLocaleFile"}} type="file" id="file-input" accept='.dcstyle.json,application/json,.tar.gz,application/x-gzip,.zip,application/zip'><br>
|
||||
<span class="description">{{i18n 'admin.customize.theme.import_file_tip'}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
{{#d-modal-body rawTitle=(i18n "admin.watched_words.test.modal_title" action=model.name) class="watched-words-test-modal"}}
|
||||
<p>{{i18n "admin.watched_words.test.description"}}</p>
|
||||
{{textarea name="test_value" value=value autofocus="autofocus"}}
|
||||
{{#if matches}}
|
||||
<p>
|
||||
{{i18n "admin.watched_words.test.found_matches"}}
|
||||
<ul>
|
||||
{{#each matches as |match|}}
|
||||
<li>{{match}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</p>
|
||||
{{else}}
|
||||
<p>{{i18n "admin.watched_words.test.no_matches"}}</p>
|
||||
{{/if}}
|
||||
{{/d-modal-body}}
|
||||
@ -3,14 +3,24 @@
|
||||
<p class="about">{{actionDescription}}</p>
|
||||
|
||||
<div class="watched-word-controls">
|
||||
{{watched-word-form
|
||||
actionKey=actionNameKey
|
||||
action=(action "recordAdded")
|
||||
filteredContent=filteredContent
|
||||
regularExpressions=adminWatchedWords.regularExpressions}}
|
||||
{{watched-word-form
|
||||
actionKey=actionNameKey
|
||||
action=(action "recordAdded")
|
||||
filteredContent=filteredContent
|
||||
regularExpressions=adminWatchedWords.regularExpressions}}
|
||||
|
||||
{{watched-word-uploader uploading=uploading actionKey=actionNameKey done=(action "uploadComplete")}}
|
||||
<div class="download-upload-controls">
|
||||
<div class="download">
|
||||
{{d-button
|
||||
class="btn-default download-link"
|
||||
href=downloadLink
|
||||
icon="download"
|
||||
label="admin.watched_words.download"}}
|
||||
</div>
|
||||
{{watched-word-uploader uploading=uploading actionKey=actionNameKey done=(action "uploadComplete")}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="show-words-checkbox">
|
||||
{{input type="checkbox" checked=adminWatchedWords.showWords disabled=adminWatchedWords.disableShowWords}}
|
||||
@ -26,3 +36,15 @@
|
||||
{{i18n 'admin.watched_words.word_count' count=wordCount}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<div class="clear-all-row">
|
||||
{{d-button
|
||||
label="admin.watched_words.test.button_label"
|
||||
icon="far-eye"
|
||||
action=(action "test")}}
|
||||
{{d-button
|
||||
class="btn-danger clear-all"
|
||||
label="admin.watched_words.clear_all"
|
||||
icon="trash-alt"
|
||||
action=(action "clearAll")}}
|
||||
</div>
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
<td class='description'>{{webHook.description}}</td>
|
||||
<td class='controls'>
|
||||
{{#link-to 'adminWebHooks.show' webHook tagName='button' classNames='btn btn-default no-text'}}{{d-icon 'far-edit'}}{{/link-to}}
|
||||
{{d-button class="destroy btn-danger" action=(action "destroy") actionParam=webHook icon="remove"}}
|
||||
{{d-button class="destroy btn-danger" action=(action "destroy") actionParam=webHook icon="times"}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
|
||||
@ -35,7 +35,8 @@ const REPLACEMENTS = {
|
||||
"notification.topic_reminder": "far-clock",
|
||||
"notification.watching_first_post": "far-dot-circle",
|
||||
"notification.group_message_summary": "users",
|
||||
"notification.post_approved": "check"
|
||||
"notification.post_approved": "check",
|
||||
"notification.membership_request_accepted": "user-plus"
|
||||
};
|
||||
|
||||
// TODO: use lib/svg_sprite/fa4-renames.json here
|
||||
@ -579,13 +580,9 @@ function warnIfMissing(id) {
|
||||
}
|
||||
|
||||
function warnIfDeprecated(oldId, newId) {
|
||||
if (
|
||||
typeof Discourse !== "undefined" &&
|
||||
Discourse.Environment === "development" &&
|
||||
!Ember.testing
|
||||
) {
|
||||
deprecated(`Icon "${oldId}" is now "${newId}".`);
|
||||
}
|
||||
deprecated(
|
||||
`Please replace all occurrences of "${oldId}"" with "${newId}". FontAwesome 4.7 icon names are now deprecated and will be removed in the next release.`
|
||||
);
|
||||
}
|
||||
|
||||
function handleIconId(icon) {
|
||||
|
||||
@ -6,13 +6,6 @@ export default Ember.Component.extend(UploadMixin, {
|
||||
tagName: "span",
|
||||
imageIsNotASquare: false,
|
||||
|
||||
@computed("uploading")
|
||||
uploadButtonText(uploading) {
|
||||
return uploading
|
||||
? I18n.t("uploading")
|
||||
: I18n.t("user.change_avatar.upload_picture");
|
||||
},
|
||||
|
||||
validateUploadedFilesOptions() {
|
||||
return { imagesOnly: true };
|
||||
},
|
||||
|
||||
@ -25,9 +25,9 @@ export default Ember.Component.extend({
|
||||
didRender() {
|
||||
this._super(...arguments);
|
||||
|
||||
const $backupCodes = this.$("#backupCodes");
|
||||
if ($backupCodes.length) {
|
||||
$backupCodes.height($backupCodes[0].scrollHeight);
|
||||
const backupCodes = this.element.querySelector("#backupCodes");
|
||||
if (backupCodes) {
|
||||
backupCodes.style.height = backupCodes.scrollHeight;
|
||||
}
|
||||
},
|
||||
|
||||
@ -49,8 +49,8 @@ export default Ember.Component.extend({
|
||||
},
|
||||
|
||||
_selectAllBackupCodes() {
|
||||
const $textArea = this.$("#backupCodes");
|
||||
$textArea[0].focus();
|
||||
$textArea[0].setSelectionRange(0, this.formattedBackupCodes.length);
|
||||
const textArea = this.element.querySelector("#backupCodes");
|
||||
textArea.focus();
|
||||
textArea.setSelectionRange(0, this.formattedBackupCodes.length);
|
||||
}
|
||||
});
|
||||
|
||||
@ -35,7 +35,7 @@ export default Ember.Component.extend(UploadMixin, {
|
||||
},
|
||||
|
||||
_init: function() {
|
||||
const $upload = this.$();
|
||||
const $upload = $(this.element);
|
||||
|
||||
$upload.on("fileuploadadd", (e, data) => {
|
||||
ajax("/admin/backups/upload_url", {
|
||||
|
||||
@ -33,6 +33,51 @@ export default Ember.Component.extend({
|
||||
}
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
|
||||
this.topics.forEach(topic => {
|
||||
const includeUnreadIndicator =
|
||||
typeof topic.unread_by_group_member !== "undefined";
|
||||
|
||||
if (includeUnreadIndicator) {
|
||||
const unreadIndicatorChannel = `/private-messages/unread-indicator/${topic.id}`;
|
||||
this.messageBus.subscribe(unreadIndicatorChannel, data => {
|
||||
const nodeClassList = document.querySelector(
|
||||
`.indicator-topic-${data.topic_id}`
|
||||
).classList;
|
||||
|
||||
if (data.show_indicator) {
|
||||
nodeClassList.remove("read");
|
||||
} else {
|
||||
nodeClassList.add("read");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
this._super(...arguments);
|
||||
|
||||
this.topics.forEach(topic => {
|
||||
const includeUnreadIndicator =
|
||||
typeof topic.unread_by_group_member !== "undefined";
|
||||
|
||||
if (includeUnreadIndicator) {
|
||||
const unreadIndicatorChannel = `/private-messages/unread-indicator/${topic.id}`;
|
||||
this.messageBus.unsubscribe(unreadIndicatorChannel);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@computed("topics")
|
||||
showUnreadIndicator(topics) {
|
||||
return topics.some(
|
||||
topic => typeof topic.unread_by_group_member !== "undefined"
|
||||
);
|
||||
},
|
||||
|
||||
click(e) {
|
||||
// Mobile basic-topic-list doesn't use the `topic-list-item` view so
|
||||
// the event for the topic entrance is never wired up.
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
const CategoryPanelBase = Ember.Component.extend({
|
||||
classNameBindings: [":modal-tab", "activeTab::invisible"]
|
||||
});
|
||||
|
||||
export default CategoryPanelBase;
|
||||
|
||||
export function buildCategoryPanel(tab, extras) {
|
||||
return CategoryPanelBase.extend(
|
||||
{
|
||||
activeTab: Ember.computed.equal("selectedTab", tab)
|
||||
},
|
||||
extras || {}
|
||||
);
|
||||
}
|
||||
@ -93,9 +93,9 @@ export default Ember.Component.extend(KeyEnterEscape, {
|
||||
},
|
||||
|
||||
setupComposerResizeEvents() {
|
||||
const $composer = this.$();
|
||||
const $grippie = this.$(".grippie");
|
||||
const $document = Ember.$(document);
|
||||
const $composer = $(this.element);
|
||||
const $grippie = $(this.element.querySelector(".grippie"));
|
||||
const $document = $(document);
|
||||
let origComposerSize = 0;
|
||||
let lastMousePos = 0;
|
||||
|
||||
@ -105,7 +105,7 @@ export default Ember.Component.extend(KeyEnterEscape, {
|
||||
const currentMousePos = mouseYPos(event);
|
||||
let size = origComposerSize + (lastMousePos - currentMousePos);
|
||||
|
||||
const winHeight = Ember.$(window).height();
|
||||
const winHeight = $(window).height();
|
||||
size = Math.min(size, winHeight - headerHeight());
|
||||
size = Math.max(size, MIN_COMPOSER_SIZE);
|
||||
this.movePanels(size);
|
||||
@ -145,11 +145,11 @@ export default Ember.Component.extend(KeyEnterEscape, {
|
||||
};
|
||||
triggerOpen();
|
||||
|
||||
afterTransition(this.$(), () => {
|
||||
afterTransition($(this.element), () => {
|
||||
resize();
|
||||
triggerOpen();
|
||||
});
|
||||
positioningWorkaround(this.$());
|
||||
positioningWorkaround($(this.element));
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
|
||||
@ -112,7 +112,7 @@ export default Ember.Component.extend({
|
||||
@observes("focusTarget")
|
||||
setFocus() {
|
||||
if (this.focusTarget === "editor") {
|
||||
this.$("textarea").putCursorAtEnd();
|
||||
$(this.element.querySelector("textarea")).putCursorAtEnd();
|
||||
}
|
||||
},
|
||||
|
||||
@ -155,21 +155,29 @@ export default Ember.Component.extend({
|
||||
};
|
||||
},
|
||||
|
||||
userSearchTerm(term) {
|
||||
const topicId = this.get("topic.id");
|
||||
// maybe this is a brand new topic, so grab category from composer
|
||||
const categoryId =
|
||||
this.get("topic.category_id") || this.get("composer.categoryId");
|
||||
|
||||
return userSearch({
|
||||
term,
|
||||
topicId,
|
||||
categoryId,
|
||||
includeMentionableGroups: true
|
||||
});
|
||||
},
|
||||
|
||||
@on("didInsertElement")
|
||||
_composerEditorInit() {
|
||||
const topicId = this.get("topic.id");
|
||||
const $input = this.$(".d-editor-input");
|
||||
const $preview = this.$(".d-editor-preview-wrapper");
|
||||
const $input = $(this.element.querySelector(".d-editor-input"));
|
||||
const $preview = $(this.element.querySelector(".d-editor-preview-wrapper"));
|
||||
|
||||
if (this.siteSettings.enable_mentions) {
|
||||
$input.autocomplete({
|
||||
template: findRawTemplate("user-selector-autocomplete"),
|
||||
dataSource: term =>
|
||||
userSearch({
|
||||
term,
|
||||
topicId,
|
||||
includeMentionableGroups: true
|
||||
}),
|
||||
dataSource: term => this.userSearchTerm.call(this, term),
|
||||
key: "@",
|
||||
transformComplete: v => v.username || v.name,
|
||||
afterComplete() {
|
||||
@ -206,7 +214,7 @@ export default Ember.Component.extend({
|
||||
!this.get("composer.canEditTitle") &&
|
||||
(!this.capabilities.isIOS || safariHacksDisabled())
|
||||
) {
|
||||
this.$(".d-editor-input").putCursorAtEnd();
|
||||
$(this.element.querySelector(".d-editor-input")).putCursorAtEnd();
|
||||
}
|
||||
|
||||
this._bindUploadTarget();
|
||||
@ -237,7 +245,7 @@ export default Ember.Component.extend({
|
||||
reason = I18n.t("composer.error.post_missing");
|
||||
} else if (missingReplyCharacters > 0) {
|
||||
reason = I18n.t("composer.error.post_length", { min: minimumPostLength });
|
||||
const tl = Discourse.User.currentProp("trust_level");
|
||||
const tl = this.get("currentUser.trust_level");
|
||||
if (tl === 0 || tl === 1) {
|
||||
reason +=
|
||||
"<br/>" +
|
||||
@ -345,12 +353,13 @@ export default Ember.Component.extend({
|
||||
},
|
||||
|
||||
_teardownInputPreviewSync() {
|
||||
[this.$(".d-editor-input"), this.$(".d-editor-preview-wrapper")].forEach(
|
||||
$element => {
|
||||
$element.off("mouseenter touchstart");
|
||||
$element.off("scroll");
|
||||
}
|
||||
);
|
||||
[
|
||||
$(this.element.querySelector(".d-editor-input")),
|
||||
$(this.element.querySelector(".d-editor-preview-wrapper"))
|
||||
].forEach($element => {
|
||||
$element.off("mouseenter touchstart");
|
||||
$element.off("scroll");
|
||||
});
|
||||
|
||||
REBUILD_SCROLL_MAP_EVENTS.forEach(event => {
|
||||
this.appEvents.off(event, this, this._resetShouldBuildScrollMap);
|
||||
@ -647,14 +656,11 @@ export default Ember.Component.extend({
|
||||
this._unbindUploadTarget(); // in case it's still bound, let's clean it up first
|
||||
this._pasted = false;
|
||||
|
||||
const $element = this.$();
|
||||
const csrf = this.session.get("csrfToken");
|
||||
const $element = $(this.element);
|
||||
|
||||
$element.fileupload({
|
||||
url: Discourse.getURL(
|
||||
`/uploads.json?client_id=${
|
||||
this.messageBus.clientId
|
||||
}&authenticity_token=${encodeURIComponent(csrf)}`
|
||||
`/uploads.json?client_id=${this.messageBus.clientId}`
|
||||
),
|
||||
dataType: "json",
|
||||
pasteZone: $element
|
||||
@ -867,7 +873,8 @@ export default Ember.Component.extend({
|
||||
// wraps previewed upload markdown in a codeblock in its own class to keep a track
|
||||
// of indexes later on to replace the correct upload placeholder in the composer
|
||||
if ($preview.find(".codeblock-image").length === 0) {
|
||||
this.$(".d-editor-preview *")
|
||||
$(this.element)
|
||||
.find(".d-editor-preview *")
|
||||
.contents()
|
||||
.each(function() {
|
||||
if (this.nodeType !== 3) return; // TEXT_NODE
|
||||
@ -890,7 +897,7 @@ export default Ember.Component.extend({
|
||||
this._validUploads = 0;
|
||||
$("#reply-control .mobile-file-upload").off("click.uploader");
|
||||
this.messageBus.unsubscribe("/uploads/composer");
|
||||
const $uploadTarget = this.$();
|
||||
const $uploadTarget = $(this.element);
|
||||
try {
|
||||
$uploadTarget.fileupload("destroy");
|
||||
} catch (e) {
|
||||
@ -925,7 +932,7 @@ export default Ember.Component.extend({
|
||||
},
|
||||
|
||||
showPreview() {
|
||||
const $preview = this.$(".d-editor-preview-wrapper");
|
||||
const $preview = $(this.element.querySelector(".d-editor-preview-wrapper"));
|
||||
this._placeImageScaleButtons($preview);
|
||||
this.send("togglePreview");
|
||||
},
|
||||
@ -1071,7 +1078,7 @@ export default Ember.Component.extend({
|
||||
if (this._enableAdvancedEditorPreviewSync()) {
|
||||
this._syncScroll(
|
||||
this._syncEditorAndPreviewScroll,
|
||||
this.$(".d-editor-input"),
|
||||
$(this.element.querySelector(".d-editor-input")),
|
||||
$preview
|
||||
);
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ export default Ember.Component.extend({
|
||||
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
this.$().show();
|
||||
this.element.style.display = "block";
|
||||
},
|
||||
|
||||
actions: {
|
||||
|
||||
@ -14,9 +14,9 @@ export default Ember.Component.extend({
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
if (this.focusTarget === "title") {
|
||||
const $input = this.$("input");
|
||||
const $input = $(this.element.querySelector("input"));
|
||||
|
||||
afterTransition(this.$().closest("#reply-control"), () => {
|
||||
afterTransition($(this.element).closest("#reply-control"), () => {
|
||||
$input.putCursorAtEnd();
|
||||
});
|
||||
}
|
||||
@ -133,14 +133,14 @@ export default Ember.Component.extend({
|
||||
.finally(() => {
|
||||
this.set("composer.loading", false);
|
||||
Ember.run.schedule("afterRender", () => {
|
||||
this.$("input").putCursorAtEnd();
|
||||
$(this.element.querySelector("input")).putCursorAtEnd();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
this._updatePost(loadOnebox);
|
||||
this.set("composer.loading", false);
|
||||
Ember.run.schedule("afterRender", () => {
|
||||
this.$("input").putCursorAtEnd();
|
||||
$(this.element.querySelector("input")).putCursorAtEnd();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,14 +12,14 @@ export default Ember.Component.extend({
|
||||
this._super(...arguments);
|
||||
|
||||
if (this.focusTarget === "usernames") {
|
||||
this.$("input").putCursorAtEnd();
|
||||
$(this.element.querySelector("input")).putCursorAtEnd();
|
||||
}
|
||||
},
|
||||
|
||||
@observes("usernames")
|
||||
_checkWidth() {
|
||||
let width = 0;
|
||||
const $acWrap = this.$().find(".ac-wrap");
|
||||
const $acWrap = $(this.element).find(".ac-wrap");
|
||||
const limit = $acWrap.width();
|
||||
this.set("defaultUsernameCount", 0);
|
||||
|
||||
@ -76,7 +76,7 @@ export default Ember.Component.extend({
|
||||
this.set("showSelector", true);
|
||||
|
||||
Ember.run.schedule("afterRender", () => {
|
||||
this.$()
|
||||
$(this.element)
|
||||
.find("input")
|
||||
.focus();
|
||||
});
|
||||
@ -84,7 +84,7 @@ export default Ember.Component.extend({
|
||||
|
||||
triggerResize() {
|
||||
this.appEvents.trigger("composer:resize");
|
||||
const $this = this.$().find(".ac-wrap");
|
||||
const $this = $(this.element).find(".ac-wrap");
|
||||
if ($this.height() >= 150) $this.scrollTop($this.height());
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ export default Ember.Component.extend({
|
||||
this.set("email", $.cookie("email"));
|
||||
}
|
||||
|
||||
this.$().on("keydown.discourse-create-account", e => {
|
||||
$(this.element).on("keydown.discourse-create-account", e => {
|
||||
if (!this.disabled && e.keyCode === 13) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@ -17,7 +17,7 @@ export default Ember.Component.extend({
|
||||
}
|
||||
});
|
||||
|
||||
this.$().on("click.dropdown-user-field-label", "[for]", event => {
|
||||
$(this.element).on("click.dropdown-user-field-label", "[for]", event => {
|
||||
const $element = $(event.target);
|
||||
const $target = $(`#${$element.attr("for")}`);
|
||||
|
||||
@ -31,7 +31,7 @@ export default Ember.Component.extend({
|
||||
willDestroyElement() {
|
||||
this._super(...arguments);
|
||||
|
||||
this.$().off("keydown.discourse-create-account");
|
||||
this.$().off("click.dropdown-user-field-label");
|
||||
$(this.element).off("keydown.discourse-create-account");
|
||||
$(this.element).off("click.dropdown-user-field-label");
|
||||
}
|
||||
});
|
||||
|
||||
@ -32,7 +32,7 @@ export default Ember.Component.extend(UploadMixin, {
|
||||
},
|
||||
|
||||
_init: function() {
|
||||
const $upload = this.$();
|
||||
const $upload = $(this.element);
|
||||
|
||||
$upload.on("fileuploadadd", (e, data) => {
|
||||
bootbox.confirm(
|
||||
|
||||
@ -7,8 +7,8 @@ export default Ember.Component.extend({
|
||||
_hiddenChanged() {
|
||||
if (!this.hidden) {
|
||||
Ember.run.scheduleOnce("afterRender", () => {
|
||||
const $modal = this.$();
|
||||
const $parent = this.$().closest(".d-editor");
|
||||
const $modal = $(this.element);
|
||||
const $parent = $(this.element).closest(".d-editor");
|
||||
const w = $parent.width();
|
||||
const h = $parent.height();
|
||||
const dir = $("html").css("direction") === "rtl" ? "right" : "left";
|
||||
@ -27,7 +27,7 @@ export default Ember.Component.extend({
|
||||
|
||||
@on("didInsertElement")
|
||||
_listenKeys() {
|
||||
this.$().on("keydown.d-modal", key => {
|
||||
$(this.element).on("keydown.d-modal", key => {
|
||||
if (this.hidden) {
|
||||
return;
|
||||
}
|
||||
@ -45,7 +45,7 @@ export default Ember.Component.extend({
|
||||
|
||||
@on("willDestroyElement")
|
||||
_stopListening() {
|
||||
this.$().off("keydown.d-modal");
|
||||
$(this.element).off("keydown.d-modal");
|
||||
},
|
||||
|
||||
actions: {
|
||||
|
||||
@ -220,6 +220,7 @@ export default Ember.Component.extend({
|
||||
_mouseTrap: null,
|
||||
showLink: true,
|
||||
emojiPickerIsActive: false,
|
||||
emojiStore: Ember.inject.service("emoji-store"),
|
||||
|
||||
@computed("placeholder")
|
||||
placeholderTranslated(placeholder) {
|
||||
@ -231,7 +232,7 @@ export default Ember.Component.extend({
|
||||
this.set("ready", true);
|
||||
|
||||
if (this.autofocus) {
|
||||
this.$("textarea").focus();
|
||||
this.element.querySelector("textarea").focus();
|
||||
}
|
||||
},
|
||||
|
||||
@ -244,13 +245,13 @@ export default Ember.Component.extend({
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
|
||||
const $editorInput = this.$(".d-editor-input");
|
||||
const $editorInput = $(this.element.querySelector(".d-editor-input"));
|
||||
this._applyEmojiAutocomplete($editorInput);
|
||||
this._applyCategoryHashtagAutocomplete($editorInput);
|
||||
|
||||
Ember.run.scheduleOnce("afterRender", this, this._readyNow);
|
||||
|
||||
const mouseTrap = Mousetrap(this.$(".d-editor-input")[0]);
|
||||
const mouseTrap = Mousetrap(this.element.querySelector(".d-editor-input"));
|
||||
const shortcuts = this.get("toolbar.shortcuts");
|
||||
|
||||
Object.keys(shortcuts).forEach(sc => {
|
||||
@ -262,28 +263,31 @@ export default Ember.Component.extend({
|
||||
});
|
||||
|
||||
// disable clicking on links in the preview
|
||||
this.$(".d-editor-preview").on("click.preview", e => {
|
||||
if (wantsNewWindow(e)) {
|
||||
return;
|
||||
$(this.element.querySelector(".d-editor-preview")).on(
|
||||
"click.preview",
|
||||
e => {
|
||||
if (wantsNewWindow(e)) {
|
||||
return;
|
||||
}
|
||||
const $target = $(e.target);
|
||||
if ($target.is("a.mention")) {
|
||||
this.appEvents.trigger(
|
||||
"click.discourse-preview-user-card-mention",
|
||||
$target
|
||||
);
|
||||
}
|
||||
if ($target.is("a.mention-group")) {
|
||||
this.appEvents.trigger(
|
||||
"click.discourse-preview-group-card-mention-group",
|
||||
$target
|
||||
);
|
||||
}
|
||||
if ($target.is("a")) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const $target = $(e.target);
|
||||
if ($target.is("a.mention")) {
|
||||
this.appEvents.trigger(
|
||||
"click.discourse-preview-user-card-mention",
|
||||
$target
|
||||
);
|
||||
}
|
||||
if ($target.is("a.mention-group")) {
|
||||
this.appEvents.trigger(
|
||||
"click.discourse-preview-group-card-mention-group",
|
||||
$target
|
||||
);
|
||||
}
|
||||
if ($target.is("a")) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
if (this.composerEvents) {
|
||||
this.appEvents.on("composer:insert-block", this, "_insertBlock");
|
||||
@ -313,7 +317,7 @@ export default Ember.Component.extend({
|
||||
Object.keys(this.get("toolbar.shortcuts")).forEach(sc =>
|
||||
mouseTrap.unbind(sc)
|
||||
);
|
||||
this.$(".d-editor-preview").off("click.preview");
|
||||
$(this.element.querySelector(".d-editor-preview")).off("click.preview");
|
||||
},
|
||||
|
||||
@computed
|
||||
@ -348,7 +352,7 @@ export default Ember.Component.extend({
|
||||
if (this._state !== "inDOM") {
|
||||
return;
|
||||
}
|
||||
const $preview = this.$(".d-editor-preview");
|
||||
const $preview = $(this.element.querySelector(".d-editor-preview"));
|
||||
if ($preview.length === 0) return;
|
||||
|
||||
if (this.previewUpdated) {
|
||||
@ -375,7 +379,7 @@ export default Ember.Component.extend({
|
||||
_applyCategoryHashtagAutocomplete() {
|
||||
const siteSettings = this.siteSettings;
|
||||
|
||||
this.$(".d-editor-input").autocomplete({
|
||||
$(this.element.querySelector(".d-editor-input")).autocomplete({
|
||||
template: findRawTemplate("category-tag-autocomplete"),
|
||||
key: "#",
|
||||
afterComplete: () => this._focusTextArea(),
|
||||
@ -419,6 +423,7 @@ export default Ember.Component.extend({
|
||||
|
||||
transformComplete: v => {
|
||||
if (v.code) {
|
||||
this.emojiStore.track(v.code);
|
||||
return `${v.code}:`;
|
||||
} else {
|
||||
$editorInput.autocomplete({ cancel: true });
|
||||
@ -455,7 +460,17 @@ export default Ember.Component.extend({
|
||||
}
|
||||
|
||||
if (term === "") {
|
||||
return resolve(["slight_smile", "smile", "wink", "sunny", "blush"]);
|
||||
if (this.emojiStore.favorites.length) {
|
||||
return resolve(this.emojiStore.favorites.slice(0, 5));
|
||||
} else {
|
||||
return resolve([
|
||||
"slight_smile",
|
||||
"smile",
|
||||
"wink",
|
||||
"sunny",
|
||||
"blush"
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if (translations[full]) {
|
||||
@ -500,7 +515,7 @@ export default Ember.Component.extend({
|
||||
return;
|
||||
}
|
||||
|
||||
const textarea = this.$("textarea.d-editor-input")[0];
|
||||
const textarea = this.element.querySelector("textarea.d-editor-input");
|
||||
const value = textarea.value;
|
||||
let start = textarea.selectionStart;
|
||||
let end = textarea.selectionEnd;
|
||||
@ -533,8 +548,8 @@ export default Ember.Component.extend({
|
||||
|
||||
_selectText(from, length) {
|
||||
Ember.run.scheduleOnce("afterRender", () => {
|
||||
const $textarea = this.$("textarea.d-editor-input");
|
||||
const textarea = $textarea[0];
|
||||
const textarea = this.element.querySelector("textarea.d-editor-input");
|
||||
const $textarea = $(textarea);
|
||||
const oldScrollPos = $textarea.scrollTop();
|
||||
if (!this.capabilities.isIOS || safariHacksDisabled()) {
|
||||
$textarea.focus();
|
||||
@ -687,7 +702,7 @@ export default Ember.Component.extend({
|
||||
return;
|
||||
}
|
||||
|
||||
const textarea = this.$("textarea.d-editor-input")[0];
|
||||
const textarea = this.element.querySelector("textarea.d-editor-input");
|
||||
|
||||
// Determine post-replace selection.
|
||||
const newSelection = determinePostReplaceSelection({
|
||||
@ -737,7 +752,7 @@ export default Ember.Component.extend({
|
||||
}
|
||||
|
||||
const value = pre + text + post;
|
||||
const $textarea = this.$("textarea.d-editor-input");
|
||||
const $textarea = $(this.element.querySelector("textarea.d-editor-input"));
|
||||
|
||||
this.set("value", value);
|
||||
|
||||
@ -749,7 +764,7 @@ export default Ember.Component.extend({
|
||||
},
|
||||
|
||||
_addText(sel, text, options) {
|
||||
const $textarea = this.$("textarea.d-editor-input");
|
||||
const $textarea = $(this.element.querySelector("textarea.d-editor-input"));
|
||||
|
||||
if (options && options.ensureSpace) {
|
||||
if ((sel.pre + "").length > 0) {
|
||||
@ -870,8 +885,11 @@ export default Ember.Component.extend({
|
||||
|
||||
// ensures textarea scroll position is correct
|
||||
_focusTextArea() {
|
||||
const $textarea = this.$("textarea.d-editor-input");
|
||||
Ember.run.scheduleOnce("afterRender", () => $textarea.blur().focus());
|
||||
const textarea = this.element.querySelector("textarea.d-editor-input");
|
||||
Ember.run.scheduleOnce("afterRender", () => {
|
||||
textarea.blur();
|
||||
textarea.focus();
|
||||
});
|
||||
},
|
||||
|
||||
actions: {
|
||||
|
||||
@ -7,7 +7,7 @@ export default Ember.Component.extend({
|
||||
this._super(...arguments);
|
||||
$("#modal-alert").hide();
|
||||
|
||||
let fixedParent = this.$().closest(".d-modal.fixed-modal");
|
||||
let fixedParent = $(this.element).closest(".d-modal.fixed-modal");
|
||||
if (fixedParent.length) {
|
||||
this.set("fixed", true);
|
||||
fixedParent.modal("show");
|
||||
@ -26,8 +26,12 @@ export default Ember.Component.extend({
|
||||
},
|
||||
|
||||
_afterFirstRender() {
|
||||
if (!this.site.mobileView && this.autoFocus !== "false") {
|
||||
this.$("input:first").focus();
|
||||
if (
|
||||
!this.site.mobileView &&
|
||||
this.autoFocus !== "false" &&
|
||||
this.element.querySelector("input")
|
||||
) {
|
||||
this.element.querySelector("input").focus();
|
||||
}
|
||||
|
||||
const maxHeight = this.maxHeight;
|
||||
@ -35,7 +39,7 @@ export default Ember.Component.extend({
|
||||
const maxHeightFloat = parseFloat(maxHeight) / 100.0;
|
||||
if (maxHeightFloat > 0) {
|
||||
const viewPortHeight = $(window).height();
|
||||
this.$().css(
|
||||
$(this.element).css(
|
||||
"max-height",
|
||||
Math.floor(maxHeightFloat * viewPortHeight) + "px"
|
||||
);
|
||||
|
||||
@ -66,7 +66,7 @@ export default Ember.Component.extend({
|
||||
}
|
||||
|
||||
if (data.fixed) {
|
||||
this.$().removeClass("hidden");
|
||||
this.element.classList.remove("hidden");
|
||||
}
|
||||
|
||||
if (data.title) {
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
|
||||
export default Ember.Component.extend({
|
||||
router: Ember.inject.service(),
|
||||
persistedQueryParams: null,
|
||||
|
||||
tagName: "",
|
||||
|
||||
@computed("category")
|
||||
@ -27,9 +30,25 @@ export default Ember.Component.extend({
|
||||
if (filterMode.indexOf("top/") === 0) {
|
||||
filterMode = filterMode.replace("top/", "");
|
||||
}
|
||||
|
||||
let params;
|
||||
const currentRouteQueryParams = this.get("router.currentRoute.queryParams");
|
||||
if (this.persistedQueryParams && currentRouteQueryParams) {
|
||||
const currentKeys = Object.keys(currentRouteQueryParams);
|
||||
const discoveryKeys = Object.keys(this.persistedQueryParams);
|
||||
const supportedKeys = currentKeys.filter(
|
||||
i => discoveryKeys.indexOf(i) > 0
|
||||
);
|
||||
params = supportedKeys.reduce((object, key) => {
|
||||
object[key] = currentRouteQueryParams[key];
|
||||
return object;
|
||||
}, {});
|
||||
}
|
||||
|
||||
return Discourse.NavItem.buildList(category, {
|
||||
filterMode,
|
||||
noSubcategories
|
||||
noSubcategories,
|
||||
persistedQueryParams: params
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
101
app/assets/javascripts/discourse/components/date-input.js.es6
Normal file
101
app/assets/javascripts/discourse/components/date-input.js.es6
Normal file
@ -0,0 +1,101 @@
|
||||
/* global Pikaday:true */
|
||||
import loadScript from "discourse/lib/load-script";
|
||||
import {
|
||||
default as computed,
|
||||
on
|
||||
} from "ember-addons/ember-computed-decorators";
|
||||
|
||||
export default Ember.Component.extend({
|
||||
classNames: ["d-date-input"],
|
||||
date: null,
|
||||
_picker: null,
|
||||
|
||||
@computed("site.mobileView")
|
||||
inputType(mobileView) {
|
||||
return mobileView ? "date" : "text";
|
||||
},
|
||||
|
||||
@on("didInsertElement")
|
||||
_loadDatePicker() {
|
||||
const container = this.element.querySelector(`#${this.containerId}`);
|
||||
|
||||
if (this.site.mobileView) {
|
||||
this._loadNativePicker(container);
|
||||
} else {
|
||||
this._loadPikadayPicker(container);
|
||||
}
|
||||
},
|
||||
|
||||
didUpdateAttrs() {
|
||||
this._super(...arguments);
|
||||
|
||||
if (this._picker) {
|
||||
this._picker.setDate(this.date, true);
|
||||
}
|
||||
},
|
||||
|
||||
_loadPikadayPicker(container) {
|
||||
loadScript("/javascripts/pikaday.js").then(() => {
|
||||
Ember.run.next(() => {
|
||||
const default_opts = {
|
||||
field: this.element.querySelector(".date-picker"),
|
||||
container: container || this.element,
|
||||
bound: container === null,
|
||||
format: "LL",
|
||||
firstDay: 1,
|
||||
i18n: {
|
||||
previousMonth: I18n.t("dates.previous_month"),
|
||||
nextMonth: I18n.t("dates.next_month"),
|
||||
months: moment.months(),
|
||||
weekdays: moment.weekdays(),
|
||||
weekdaysShort: moment.weekdaysShort()
|
||||
},
|
||||
onSelect: date => this._handleSelection(date)
|
||||
};
|
||||
|
||||
this._picker = new Pikaday(Object.assign(default_opts, this._opts()));
|
||||
this._picker.setDate(this.date, true);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
_loadNativePicker(container) {
|
||||
const wrapper = container || this.element;
|
||||
const picker = wrapper.querySelector("input.date-picker");
|
||||
picker.onchange = () => this._handleSelection(picker.value);
|
||||
picker.hide = () => {
|
||||
/* do nothing for native */
|
||||
};
|
||||
picker.destroy = () => {
|
||||
/* do nothing for native */
|
||||
};
|
||||
this._picker = picker;
|
||||
},
|
||||
|
||||
_handleSelection(value) {
|
||||
if (!this.element || this.isDestroying || this.isDestroyed) return;
|
||||
|
||||
this._picker && this._picker.hide();
|
||||
|
||||
if (this.onChange) {
|
||||
this.onChange(moment(value).toDate());
|
||||
}
|
||||
},
|
||||
|
||||
@on("willDestroyElement")
|
||||
_destroy() {
|
||||
if (this._picker) {
|
||||
this._picker.destroy();
|
||||
}
|
||||
this._picker = null;
|
||||
},
|
||||
|
||||
@computed()
|
||||
placeholder() {
|
||||
return I18n.t("dates.placeholder");
|
||||
},
|
||||
|
||||
_opts() {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
@ -41,7 +41,7 @@ export default Ember.Component.extend({
|
||||
nextMonth: I18n.t("dates.next_month"),
|
||||
months: moment.months(),
|
||||
weekdays: moment.weekdays(),
|
||||
weekdaysShort: moment.weekdaysShort()
|
||||
weekdaysShort: moment.weekdaysMin()
|
||||
},
|
||||
onSelect: date => this._handleSelection(date)
|
||||
};
|
||||
|
||||
@ -0,0 +1,51 @@
|
||||
export default Ember.Component.extend({
|
||||
classNames: ["d-date-time-input-range"],
|
||||
|
||||
from: null,
|
||||
to: null,
|
||||
onChangeTo: null,
|
||||
onChangeFrom: null,
|
||||
currentPanel: "from",
|
||||
showFromTime: true,
|
||||
showToTime: true,
|
||||
error: null,
|
||||
|
||||
fromPanelActive: Ember.computed.equal("currentPanel", "from"),
|
||||
toPanelActive: Ember.computed.equal("currentPanel", "to"),
|
||||
|
||||
_valid(state) {
|
||||
if (state.to < state.from) {
|
||||
return I18n.t("date_time_picker.errors.to_before_from");
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
actions: {
|
||||
_onChange(options, value) {
|
||||
if (this.onChange) {
|
||||
const state = {
|
||||
from: this.from,
|
||||
to: this.to
|
||||
};
|
||||
|
||||
const diff = {};
|
||||
diff[options.prop] = value;
|
||||
|
||||
const newState = Object.assign(state, diff);
|
||||
|
||||
const validation = this._valid(newState);
|
||||
if (validation === true) {
|
||||
this.set("error", null);
|
||||
this.onChange(newState);
|
||||
} else {
|
||||
this.set("error", validation);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onChangePanel(panel) {
|
||||
this.set("currentPanel", panel);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,35 @@
|
||||
export default Ember.Component.extend({
|
||||
classNames: ["d-date-time-input"],
|
||||
date: null,
|
||||
showTime: true,
|
||||
|
||||
_hours: Ember.computed("date", function() {
|
||||
return this.date ? this.date.getHours() : null;
|
||||
}),
|
||||
|
||||
_minutes: Ember.computed("date", function() {
|
||||
return this.date ? this.date.getMinutes() : null;
|
||||
}),
|
||||
|
||||
actions: {
|
||||
onChangeTime(time) {
|
||||
if (this.onChange) {
|
||||
const year = this.date.getFullYear();
|
||||
const month = this.date.getMonth();
|
||||
const day = this.date.getDate();
|
||||
this.onChange(new Date(year, month, day, time.hours, time.minutes));
|
||||
}
|
||||
},
|
||||
|
||||
onChangeDate(date) {
|
||||
if (this.onChange) {
|
||||
const year = date.getFullYear();
|
||||
const month = date.getMonth();
|
||||
const day = date.getDate();
|
||||
this.onChange(
|
||||
new Date(year, month, day, this._hours || 0, this._minutes || 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -102,7 +102,7 @@ export default Ember.Component.extend(
|
||||
|
||||
$(window).on("resize.discourse-on-scroll", () => this.scrolled());
|
||||
|
||||
this.$().on(
|
||||
$(this.element).on(
|
||||
"click.discourse-redirect",
|
||||
".cooked a, a.track-link",
|
||||
function(e) {
|
||||
@ -120,7 +120,10 @@ export default Ember.Component.extend(
|
||||
$(window).unbind("resize.discourse-on-scroll");
|
||||
|
||||
// Unbind link tracking
|
||||
this.$().off("click.discourse-redirect", ".cooked a, a.track-link");
|
||||
$(this.element).off(
|
||||
"click.discourse-redirect",
|
||||
".cooked a, a.track-link"
|
||||
);
|
||||
|
||||
this.resetExamineDockCache();
|
||||
|
||||
|
||||
@ -22,6 +22,11 @@ const DiscoveryTopicsListComponent = Ember.Component.extend(
|
||||
}
|
||||
},
|
||||
|
||||
@observes("topicTrackingState.states")
|
||||
_updateTopics() {
|
||||
this.topicTrackingState.updateTopics(this.model.topics);
|
||||
},
|
||||
|
||||
@observes("incomingCount")
|
||||
_updateTitle() {
|
||||
Discourse.updateContextCount(this.incomingCount);
|
||||
|
||||
@ -1,12 +1,33 @@
|
||||
import { buildCategoryPanel } from "discourse/components/edit-category-panel";
|
||||
import PermissionType from "discourse/models/permission-type";
|
||||
import { on } from "ember-addons/ember-computed-decorators";
|
||||
|
||||
export default buildCategoryPanel("security", {
|
||||
editingPermissions: false,
|
||||
selectedGroup: null,
|
||||
selectedPermission: null,
|
||||
showPendingGroupChangesAlert: false,
|
||||
interactedWithDropdowns: false,
|
||||
|
||||
@on("init")
|
||||
_registerValidator() {
|
||||
this.registerValidator(() => {
|
||||
if (
|
||||
!this.showPendingGroupChangesAlert &&
|
||||
this.interactedWithDropdowns &&
|
||||
this.activeTab
|
||||
) {
|
||||
this.set("showPendingGroupChangesAlert", true);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
actions: {
|
||||
onDropdownChange() {
|
||||
this.set("interactedWithDropdowns", true);
|
||||
},
|
||||
|
||||
editPermissions() {
|
||||
if (!this.get("category.is_special")) {
|
||||
this.set("editingPermissions", true);
|
||||
@ -25,6 +46,10 @@ export default buildCategoryPanel("security", {
|
||||
"selectedGroup",
|
||||
this.get("category.availableGroups.firstObject")
|
||||
);
|
||||
this.setProperties({
|
||||
showPendingGroupChangesAlert: false,
|
||||
interactedWithDropdowns: false
|
||||
});
|
||||
},
|
||||
|
||||
removePermission(permission) {
|
||||
|
||||
@ -27,7 +27,7 @@ export default Ember.Component.extend({
|
||||
},
|
||||
|
||||
_resetModalScrollState() {
|
||||
const $modalBody = this.$()
|
||||
const $modalBody = $(this.element)
|
||||
.parents("#discourse-modal")
|
||||
.find(".modal-body");
|
||||
if ($modalBody.length === 1) {
|
||||
|
||||
@ -4,7 +4,7 @@ export default buildCategoryPanel("topic-template", {
|
||||
_activeTabChanged: function() {
|
||||
if (this.activeTab) {
|
||||
Ember.run.scheduleOnce("afterRender", () =>
|
||||
this.$(".d-editor-input").focus()
|
||||
this.element.querySelector(".d-editor-input").focus()
|
||||
);
|
||||
}
|
||||
}.observes("activeTab")
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { on, observes } from "ember-addons/ember-computed-decorators";
|
||||
import { findRawTemplate } from "discourse/lib/raw-templates";
|
||||
import { emojiUrlFor } from "discourse/lib/text";
|
||||
import KeyValueStore from "discourse/lib/key-value-store";
|
||||
|
||||
import {
|
||||
extendedEmojiList,
|
||||
isSkinTonableEmoji,
|
||||
@ -10,21 +10,14 @@ import {
|
||||
import { safariHacksDisabled } from "discourse/lib/utilities";
|
||||
const { run } = Ember;
|
||||
|
||||
const keyValueStore = new KeyValueStore("discourse_emojis_");
|
||||
const EMOJI_USAGE = "emojiUsage";
|
||||
const EMOJI_SELECTED_DIVERSITY = "emojiSelectedDiversity";
|
||||
const PER_ROW = 11;
|
||||
const customEmojis = _.keys(extendedEmojiList()).map(code => {
|
||||
return { code, src: emojiUrlFor(code) };
|
||||
});
|
||||
|
||||
export function resetCache() {
|
||||
keyValueStore.setObject({ key: EMOJI_USAGE, value: [] });
|
||||
keyValueStore.setObject({ key: EMOJI_SELECTED_DIVERSITY, value: 1 });
|
||||
}
|
||||
|
||||
export default Ember.Component.extend({
|
||||
automaticPositioning: true,
|
||||
emojiStore: Ember.inject.service("emoji-store"),
|
||||
|
||||
close() {
|
||||
this._unbindEvents();
|
||||
@ -46,11 +39,10 @@ export default Ember.Component.extend({
|
||||
this.$results = this.$picker.find(".results");
|
||||
this.$list = this.$picker.find(".list");
|
||||
|
||||
this.set(
|
||||
"selectedDiversity",
|
||||
keyValueStore.getObject(EMOJI_SELECTED_DIVERSITY) || 1
|
||||
);
|
||||
this.set("recentEmojis", keyValueStore.getObject(EMOJI_USAGE) || []);
|
||||
this.setProperties({
|
||||
selectedDiversity: this.emojiStore.diversity,
|
||||
recentEmojis: this.emojiStore.favorites
|
||||
});
|
||||
|
||||
run.scheduleOnce("afterRender", this, function() {
|
||||
this._bindEvents();
|
||||
@ -86,20 +78,9 @@ export default Ember.Component.extend({
|
||||
|
||||
@on("didInsertElement")
|
||||
_setup() {
|
||||
this.$picker = this.$(".emoji-picker");
|
||||
this.$modal = this.$(".emoji-picker-modal");
|
||||
|
||||
this.$picker = $(this.element.querySelector(".emoji-picker"));
|
||||
this.$modal = $(this.element.querySelector(".emoji-picker-modal"));
|
||||
this.appEvents.on("emoji-picker:close", this, "_closeEmojiPicker");
|
||||
|
||||
if (!keyValueStore.getObject(EMOJI_USAGE)) {
|
||||
keyValueStore.setObject({ key: EMOJI_USAGE, value: [] });
|
||||
} else if (_.isPlainObject(keyValueStore.getObject(EMOJI_USAGE))) {
|
||||
// handle legacy format
|
||||
keyValueStore.setObject({
|
||||
key: EMOJI_USAGE,
|
||||
value: _.keys(keyValueStore.getObject(EMOJI_USAGE))
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@on("didUpdateAttrs")
|
||||
@ -116,10 +97,7 @@ export default Ember.Component.extend({
|
||||
|
||||
@observes("selectedDiversity")
|
||||
selectedDiversityChanged() {
|
||||
keyValueStore.setObject({
|
||||
key: EMOJI_SELECTED_DIVERSITY,
|
||||
value: this.selectedDiversity
|
||||
});
|
||||
this.emojiStore.diversity = this.selectedDiversity;
|
||||
|
||||
$.each(
|
||||
this.$list.find(".emoji[data-loaded='1'].diversity"),
|
||||
@ -228,8 +206,8 @@ export default Ember.Component.extend({
|
||||
|
||||
@on("willDestroyElement")
|
||||
_unbindEvents() {
|
||||
this.$().off();
|
||||
this.$(window).off("resize");
|
||||
$(this.element).off();
|
||||
$(window).off("resize");
|
||||
clearInterval(this._refreshInterval);
|
||||
$("#reply-control").off("div-resizing");
|
||||
$("html").off("mouseup.emoji-picker");
|
||||
@ -312,7 +290,7 @@ export default Ember.Component.extend({
|
||||
},
|
||||
|
||||
_bindResizing() {
|
||||
this.$(window).on("resize", () => {
|
||||
$(window).on("resize", () => {
|
||||
run.throttle(this, this._positionPicker, 16);
|
||||
});
|
||||
|
||||
@ -326,7 +304,7 @@ export default Ember.Component.extend({
|
||||
".section[data-section='recent'] .clear-recent"
|
||||
);
|
||||
$recent.on("click", () => {
|
||||
keyValueStore.setObject({ key: EMOJI_USAGE, value: [] });
|
||||
this.emojiStore.favorites = [];
|
||||
this.set("recentEmojis", []);
|
||||
this._scrollTo(0);
|
||||
return false;
|
||||
@ -468,7 +446,7 @@ export default Ember.Component.extend({
|
||||
|
||||
_isReplyControlExpanded() {
|
||||
const verticalSpace =
|
||||
this.$(window).height() -
|
||||
$(window).height() -
|
||||
$(".d-header").height() -
|
||||
$("#reply-control").height();
|
||||
|
||||
@ -480,7 +458,7 @@ export default Ember.Component.extend({
|
||||
return;
|
||||
}
|
||||
|
||||
let windowWidth = this.$(window).width();
|
||||
let windowWidth = $(window).width();
|
||||
|
||||
const desktopModalePositioning = options => {
|
||||
let attributes = {
|
||||
@ -608,12 +586,8 @@ export default Ember.Component.extend({
|
||||
},
|
||||
|
||||
_trackEmojiUsage(code) {
|
||||
let recent = keyValueStore.getObject(EMOJI_USAGE) || [];
|
||||
recent = recent.filter(r => r !== code);
|
||||
recent.unshift(code);
|
||||
recent.length = Math.min(recent.length, PER_ROW);
|
||||
keyValueStore.setObject({ key: EMOJI_USAGE, value: recent });
|
||||
this.set("recentEmojis", recent);
|
||||
this.emojiStore.track(code);
|
||||
this.set("recentEmojis", this.emojiStore.favorites.slice(0, PER_ROW));
|
||||
},
|
||||
|
||||
_scrollTo(y) {
|
||||
|
||||
@ -5,7 +5,7 @@ export default Ember.TextArea.extend({
|
||||
@on("didInsertElement")
|
||||
_startWatching() {
|
||||
Ember.run.scheduleOnce("afterRender", () => {
|
||||
this.$().focus();
|
||||
$(this.element).focus();
|
||||
autosize(this.element);
|
||||
});
|
||||
},
|
||||
@ -19,6 +19,6 @@ export default Ember.TextArea.extend({
|
||||
|
||||
@on("willDestroyElement")
|
||||
_disableAutosize() {
|
||||
autosize.destroy(this.$());
|
||||
autosize.destroy($(this.element));
|
||||
}
|
||||
});
|
||||
|
||||
@ -3,14 +3,14 @@ import { observes } from "ember-addons/ember-computed-decorators";
|
||||
// Mostly hacks because `flag.hbs` didn't use `radio-button`
|
||||
export default Ember.Component.extend({
|
||||
_selectRadio() {
|
||||
this.$("input[type='radio']").prop("checked", false);
|
||||
this.element.querySelector("input[type='radio']").checked = false;
|
||||
|
||||
const nameKey = this.nameKey;
|
||||
if (!nameKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$("#radio_" + nameKey).prop("checked", "true");
|
||||
this.element.querySelector("#radio_" + nameKey).checked = "true";
|
||||
},
|
||||
|
||||
@observes("nameKey")
|
||||
|
||||
@ -91,7 +91,7 @@ const FooterNavComponent = MountWidget.extend(
|
||||
// in the header, otherwise, we hide it.
|
||||
@observes("mobileScrollDirection")
|
||||
toggleMobileFooter() {
|
||||
this.$().toggleClass(
|
||||
$(this.element).toggleClass(
|
||||
"visible",
|
||||
this.mobileScrollDirection === null ? true : false
|
||||
);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
export default Ember.Component.extend({
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
this.$("input")
|
||||
$(this.element.querySelector("input"))
|
||||
.select()
|
||||
.focus();
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ export default Ember.Component.extend({
|
||||
let selectedGroups;
|
||||
let groupNames = this.groupNames;
|
||||
|
||||
this.$("input").autocomplete({
|
||||
$(this.element.querySelector("input")).autocomplete({
|
||||
allowAny: false,
|
||||
items: _.isArray(groupNames)
|
||||
? groupNames
|
||||
|
||||
@ -19,12 +19,12 @@ export default Ember.Component.extend({
|
||||
@computed("model.visibility_level", "model.public_admission")
|
||||
disableMembershipRequestSetting(visibility_level, publicAdmission) {
|
||||
visibility_level = parseInt(visibility_level);
|
||||
return visibility_level !== 0 || publicAdmission;
|
||||
return ![0, 1].includes(visibility_level) || publicAdmission;
|
||||
},
|
||||
|
||||
@computed("model.visibility_level", "model.allow_membership_requests")
|
||||
disablePublicSetting(visibility_level, allowMembershipRequests) {
|
||||
visibility_level = parseInt(visibility_level);
|
||||
return visibility_level !== 0 || allowMembershipRequests;
|
||||
return ![0, 1].includes(visibility_level) || allowMembershipRequests;
|
||||
}
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user