diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 0000000000..aa854cde75
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,13 @@
+{
+ "name": "Discourse",
+ "image": "discourse/discourse_dev:release",
+ "workspaceMount": "source=${localWorkspaceFolder}/../..,target=/var/www/discourse,type=bind",
+ "workspaceFolder": "/var/www/discourse",
+ "settings": {
+ "terminal.integrated.shell.linux": "/bin/bash"
+ },
+ "postCreateCommand": "sudo /sbin/boot",
+ "extensions": ["rebornix.Ruby"],
+ "forwardPorts": [9292],
+ "remoteUser": "discourse"
+}
\ No newline at end of file
diff --git a/.eslintrc b/.eslintrc
index 58952b4eb3..320310db8d 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -2,7 +2,8 @@
"extends": "eslint-config-discourse",
"rules": {
"discourse-ember/global-ember": 2,
- "no-duplicate-imports": 2
+ "no-duplicate-imports": 2,
+ "sort-imports": 2
},
"globals": {
"moduleFor": "off",
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index 7e97daba6d..ab85796b3c 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -45,10 +45,13 @@ bf88410126f73aab47b7e694e3c5b46453cec1b6
ce3fe2f4c4ddf166949ee3cec3d9ecbf9108ab52
# REFACTOR: Move qunit tests to a different directory structure
-bc97c79a35d8acd283d4d8b79aa079bce9d127c6
+445d6ba45fe954fb7de11ce7b1392232160e2b63
# REFACTOR: Move javascript tests inside discourse app
23f24bfb510edb25b18b6a0d5485270c88df9b24
# DEV: Tidy up imports. (#11364)
1c2358ba162eb9f9ba9095c9afe30cf51dd85e04
+
+# DEV: Sort imports alphabetically (#11382)
+bbe5d8d5cf1220165842985c0e2cd4c454d501cd
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 7b1bb84427..aefab9fadb 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,5 +1,9 @@
version: 2
updates:
+- package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
- package-ecosystem: bundler
directory: "/"
schedule:
diff --git a/.gitignore b/.gitignore
index d0359a12ee..2cf8e9eb13 100644
--- a/.gitignore
+++ b/.gitignore
@@ -137,8 +137,10 @@ node_modules
# ignore generated api documentation files
openapi/*
-# ignore VSCode config files
-.vscode
+# ignore custom VSCode config files
+.vscode/*
+!.vscode/launch.json
+!.vscode/tasks.json
# ignore direnv
.envrc
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000000..e1231a270f
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,19 @@
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Discourse",
+ "type": "Ruby",
+ "request": "launch",
+ "cwd": "/home/discourse/workspace/discourse",
+ // run bundle install before rails server
+ "preLaunchTask": "Prepare discourse",
+ "env": { "DISCOURSE_DEV_HOSTS": "${env:CLOUDENV_ENVIRONMENT_ID}-9292.apps.codespaces.githubusercontent.com", "UNICORN_BIND_ALL": "1", "UNICORN_WORKERS": "4", "DISCOURSE_DEV_ALLOW_ANON_TO_IMPERSONATE": "1" },
+ "program": "bin/unicorn",
+ "args": ["-x"],
+ }
+ ]
+}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000000..ad8af2fea2
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,12 @@
+{
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
+ // for the documentation about the tasks.json format
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "Prepare discourse",
+ "type": "shell",
+ "command": "cd /home/discourse/workspace/discourse && bundle install && yarn && bin/rake db:migrate"
+ },
+ ],
+}
diff --git a/Dangerfile b/Dangerfile
deleted file mode 100644
index 33cf8fc565..0000000000
--- a/Dangerfile
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-if github.pr_json && (github.pr_json["additions"] || 0) > 250 || (github.pr_json["deletions"] || 0) > 250
- warn("This pull request is big! We prefer smaller PRs whenever possible, as they are easier to review. Can this be split into a few smaller PRs?")
-end
-
-prettier_offenses = `yarn --silent prettier --list-different "app/assets/stylesheets/**/*.scss" "app/assets/javascripts/**/*.js" "app/assets/javascripts/**/*.es6" "test/javascripts/**/*.es6"`.split("\n")
-
-unless prettier_offenses.empty?
- fail(%{
-This PR doesn't match our required code formatting standards, as enforced by prettier.io. Here's how to set up prettier in your code editor.\n
-#{prettier_offenses.map { |o| github.html_link(o) }.join("\n")}
- })
-end
-
-locales_changes = git.modified_files.grep(%r{config/locales})
-has_non_en_locales_changes = locales_changes.grep_v(%r{config/locales/(?:client|server)\.(?:en|en_US)\.yml}).any?
-
-if locales_changes.any? && has_non_en_locales_changes
- fail("Please submit your non-English translation updates via [Crowdin](https://translate.discourse.org/). You can read more on how to contribute translations [here](https://meta.discourse.org/t/contribute-a-translation-to-discourse/14882).")
-end
-
-files = (git.added_files + git.modified_files)
- .select { |path| !path.start_with?("plugins/") }
- .select { |path| path.end_with?("es6") || path.end_with?("js") || path.end_with?("rb") }
-
-js_files = files.select { |path| path.end_with?(".js.es6") || path.end_with?(".js") }
-js_test_files = js_files.select { |path| path.end_with?("-test.js.es6") }
-
-super_offenses = []
-self_offenses = []
-js_files.each do |path|
- diff = git.diff_for_file(path)
-
- next if !diff
-
- diff.patch.lines.grep(/^\+\s\s/).each do |added_line|
- super_offenses << path if added_line['this._super()']
- self_offenses << path if added_line[/(?:(^|\W)self\.?)/]
- end
-end
-
-jquery_find_offenses = []
-js_test_files.each do |path|
- diff = git.diff_for_file(path)
-
- next if !diff
-
- diff.patch.lines.grep(/^\+\s\s/).each do |added_line|
- jquery_find_offenses << path if added_line['this.$(']
- end
-end
-
-if !self_offenses.empty?
- warn(%{
-Use fat arrow instead of self pattern.\n
-#{self_offenses.uniq.map { |o| github.html_link(o) }.join("\n")}
- })
-end
-
-if !super_offenses.empty?
- warn(%{
-When possible use `this._super(...arguments)` instead of `this._super()`\n
-#{super_offenses.uniq.map { |o| github.html_link(o) }.join("\n")}
- })
-end
-
-if !jquery_find_offenses.empty?
- warn(%{
-Use `find()` instead of `this.$` in js tests`\n
-#{jquery_find_offenses.uniq.map { |o| github.html_link(o) }.join("\n")}
- })
-end
diff --git a/Gemfile b/Gemfile
index cb86d7e4ba..3ea59bc92e 100644
--- a/Gemfile
+++ b/Gemfile
@@ -192,7 +192,6 @@ gem 'htmlentities', require: false
# If you want to amend mini profiler to do the monkey patches in the railties
# we are open to it. by deferring require to the initializer we can configure discourse installs without it
-gem 'flamegraph', require: false
gem 'rack-mini-profiler', require: ['enable_rails_patches']
gem 'unicorn', require: false, platform: :ruby
diff --git a/Gemfile.lock b/Gemfile.lock
index 4f06749322..3b16e87e10 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -70,31 +70,32 @@ GEM
coderay (>= 1.0.0)
erubi (>= 1.0.0)
rack (>= 0.9.0)
- binding_of_caller (0.8.0)
+ binding_of_caller (1.0.0)
debug_inspector (>= 0.0.1)
bootsnap (1.5.1)
msgpack (~> 1.0)
builder (3.2.4)
- bullet (6.1.0)
+ bullet (6.1.2)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11)
byebug (11.1.3)
cbor (0.5.9.6)
certified (1.0.0)
- chunky_png (1.3.14)
+ chunky_png (1.4.0)
coderay (1.1.3)
colored2 (3.1.2)
- concurrent-ruby (1.1.7)
+ concurrent-ruby (1.1.8)
connection_pool (2.2.3)
cose (1.2.0)
cbor (~> 0.5.9)
openssl-signature_algorithm (~> 1.0)
cppjieba_rb (0.3.3)
- crack (0.4.4)
+ crack (0.4.5)
+ rexml
crass (1.0.6)
css_parser (1.7.1)
addressable
- debug_inspector (0.0.3)
+ debug_inspector (1.0.0)
diff-lcs (1.4.4)
diffy (3.4.0)
discourse-ember-rails (0.18.6)
@@ -112,7 +113,7 @@ GEM
image_size (~> 1.5)
in_threads (~> 1.3)
progress (~> 3.0, >= 3.0.1)
- docile (1.3.2)
+ docile (1.3.5)
email_reply_trimmer (0.1.13)
ember-data-source (3.0.2)
ember-source (>= 2, < 3.0)
@@ -121,19 +122,20 @@ GEM
sprockets (>= 3.3, < 4.1)
ember-source (2.18.2)
erubi (1.10.0)
- excon (0.78.0)
+ excon (0.78.1)
execjs (2.7.0)
exifr (1.3.9)
fabrication (2.21.1)
fakeweb (1.3.0)
- faraday (1.1.0)
+ faraday (1.3.0)
+ faraday-net_http (~> 1.0)
multipart-post (>= 1.2, < 3)
ruby2_keywords
+ faraday-net_http (1.0.1)
fast_blank (1.0.0)
fast_xs (0.8.0)
- fastimage (2.2.0)
- ffi (1.13.1)
- flamegraph (0.9.5)
+ fastimage (2.2.1)
+ ffi (1.14.2)
fspath (3.1.2)
gc_tracer (1.5.1)
globalid (0.4.2)
@@ -145,7 +147,7 @@ GEM
hkdf (0.3.0)
htmlentities (4.3.4)
http_accept_language (2.1.1)
- i18n (1.8.5)
+ i18n (1.8.7)
concurrent-ruby (~> 1.0)
image_size (1.5.0)
in_threads (1.5.4)
@@ -154,13 +156,17 @@ GEM
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
- json (2.3.1)
+ json (2.5.1)
json-schema (2.8.1)
addressable (>= 2.4)
jwt (2.2.2)
kgio (2.11.3)
libv8 (8.4.255.0)
- listen (3.3.1)
+ libv8 (8.4.255.0-x86_64-darwin-18)
+ libv8 (8.4.255.0-x86_64-darwin-19)
+ libv8 (8.4.255.0-x86_64-darwin-20)
+ libv8 (8.4.255.0-x86_64-linux)
+ listen (3.4.1)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
lograge (0.11.2)
@@ -172,7 +178,7 @@ GEM
logstash-logger (0.26.1)
logstash-event (~> 1.2)
logster (2.9.4)
- loofah (2.8.0)
+ loofah (2.9.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
lru_redux (1.1.0)
@@ -180,40 +186,46 @@ GEM
mail (2.7.1)
mini_mime (>= 0.1.1)
maxminddb (0.1.22)
- memory_profiler (0.9.14)
+ memory_profiler (1.0.0)
message_bus (3.3.4)
rack (>= 1.1.3)
method_source (1.0.0)
mini_mime (1.0.2)
- mini_portile2 (2.4.0)
+ mini_portile2 (2.5.0)
mini_racer (0.3.1)
libv8 (~> 8.4.255)
- mini_scheduler (0.12.3)
- sidekiq
- mini_sql (0.3)
+ mini_scheduler (0.13.0)
+ sidekiq (>= 4.2.3)
+ mini_sql (1.0.1)
mini_suffix (0.3.0)
ffi (~> 1.9)
- minitest (5.14.2)
- mocha (1.11.2)
- mock_redis (0.26.0)
+ minitest (5.14.3)
+ mocha (1.12.0)
+ mock_redis (0.27.3)
+ ruby2_keywords
msgpack (1.3.3)
multi_json (1.15.0)
multi_xml (0.6.0)
multipart-post (2.1.1)
mustache (1.1.1)
nio4r (2.5.4)
- nokogiri (1.10.10)
- mini_portile2 (~> 2.4.0)
- nokogumbo (2.0.2)
+ nokogiri (1.11.1)
+ mini_portile2 (~> 2.5.0)
+ racc (~> 1.4)
+ nokogiri (1.11.1-x86_64-darwin)
+ racc (~> 1.4)
+ nokogiri (1.11.1-x86_64-linux)
+ racc (~> 1.4)
+ nokogumbo (2.0.4)
nokogiri (~> 1.8, >= 1.8.4)
- oauth (0.5.4)
+ oauth (0.5.5)
oauth2 (1.4.4)
faraday (>= 0.8, < 2.0)
jwt (>= 1.0, < 3.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
- oj (3.10.16)
+ oj (3.11.0)
omniauth (1.9.1)
hashie (>= 3.4.6)
rack (>= 1.6.2, < 3)
@@ -222,20 +234,21 @@ GEM
omniauth-github (1.4.0)
omniauth (~> 1.5)
omniauth-oauth2 (>= 1.4.0, < 2.0)
- omniauth-google-oauth2 (0.8.0)
+ omniauth-google-oauth2 (0.8.1)
jwt (>= 2.0)
+ oauth2 (~> 1.1)
omniauth (>= 1.1.1)
omniauth-oauth2 (>= 1.6)
omniauth-oauth (1.1.0)
oauth
omniauth (~> 1.0)
- omniauth-oauth2 (1.7.0)
+ omniauth-oauth2 (1.7.1)
oauth2 (~> 1.4)
- omniauth (~> 1.9)
+ omniauth (>= 1.9, < 3)
omniauth-twitter (1.4.0)
omniauth-oauth (~> 1.1)
rack
- onebox (2.2.1)
+ onebox (2.2.2)
addressable (~> 2.7.0)
htmlentities (~> 4.3)
multi_json (~> 1.11)
@@ -247,7 +260,7 @@ GEM
parallel (1.20.1)
parallel_tests (3.4.0)
parallel
- parser (2.7.2.0)
+ parser (3.0.0.0)
ast (~> 2.4.1)
pg (1.2.3)
progress (3.5.2)
@@ -260,11 +273,12 @@ GEM
pry-rails (0.3.9)
pry (>= 0.10.4)
public_suffix (4.0.6)
- puma (5.0.4)
+ puma (5.1.1)
nio4r (~> 2.0)
r2 (0.2.7)
+ racc (1.5.2)
rack (2.2.3)
- rack-mini-profiler (2.2.0)
+ rack-mini-profiler (2.3.0)
rack (>= 1.2.0)
rack-protection (2.1.0)
rack
@@ -275,7 +289,7 @@ GEM
nokogiri (>= 1.6)
rails-html-sanitizer (1.3.0)
loofah (~> 2.3)
- rails_failover (0.6.2)
+ rails_failover (0.6.5)
activerecord (~> 6.0)
concurrent-ruby
railties (~> 6.0)
@@ -290,7 +304,7 @@ GEM
thor (>= 0.20.3, < 2.0)
rainbow (3.0.0)
raindrops (0.19.1)
- rake (13.0.1)
+ rake (13.0.3)
rb-fsevent (0.10.4)
rb-inotify (0.10.1)
ffi (~> 1.0)
@@ -302,70 +316,70 @@ GEM
redis (4.2.5)
redis-namespace (1.8.0)
redis (>= 3.0.4)
- regexp_parser (2.0.0)
+ regexp_parser (2.0.3)
request_store (1.5.0)
rack (>= 1.4)
rexml (3.2.4)
rinku (2.0.6)
rotp (6.2.0)
- rqrcode (1.1.2)
+ rqrcode (1.2.0)
chunky_png (~> 1.0)
- rqrcode_core (~> 0.1)
- rqrcode_core (0.1.2)
+ rqrcode_core (~> 0.2)
+ rqrcode_core (0.2.0)
rspec (3.10.0)
rspec-core (~> 3.10.0)
rspec-expectations (~> 3.10.0)
rspec-mocks (~> 3.10.0)
- rspec-core (3.10.0)
+ rspec-core (3.10.1)
rspec-support (~> 3.10.0)
- rspec-expectations (3.10.0)
+ rspec-expectations (3.10.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-html-matchers (0.9.4)
nokogiri (~> 1)
rspec (>= 3.0.0.a, < 4)
- rspec-mocks (3.10.0)
+ rspec-mocks (3.10.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
- rspec-rails (4.0.1)
+ rspec-rails (4.0.2)
actionpack (>= 4.2)
activesupport (>= 4.2)
railties (>= 4.2)
- rspec-core (~> 3.9)
- rspec-expectations (~> 3.9)
- rspec-mocks (~> 3.9)
- rspec-support (~> 3.9)
- rspec-support (3.10.0)
+ rspec-core (~> 3.10)
+ rspec-expectations (~> 3.10)
+ rspec-mocks (~> 3.10)
+ rspec-support (~> 3.10)
+ rspec-support (3.10.1)
rswag-specs (2.3.1)
activesupport (>= 3.1, < 7.0)
json-schema (~> 2.2)
railties (>= 3.1, < 7.0)
rtlit (0.0.5)
- rubocop (1.4.2)
+ rubocop (1.8.1)
parallel (~> 1.10)
- parser (>= 2.7.1.5)
+ parser (>= 3.0.0.0)
rainbow (>= 2.2.2, < 4.0)
- regexp_parser (>= 1.8)
+ regexp_parser (>= 1.8, < 3.0)
rexml
- rubocop-ast (>= 1.1.1)
+ rubocop-ast (>= 1.2.0, < 2.0)
ruby-progressbar (~> 1.7)
- unicode-display_width (>= 1.4.0, < 2.0)
- rubocop-ast (1.2.0)
+ unicode-display_width (>= 1.4.0, < 3.0)
+ rubocop-ast (1.4.0)
parser (>= 2.7.1.5)
rubocop-discourse (2.4.1)
rubocop (>= 1.1.0)
rubocop-rspec (>= 2.0.0)
- rubocop-rspec (2.0.0)
+ rubocop-rspec (2.1.0)
rubocop (~> 1.0)
rubocop-ast (>= 1.1.0)
ruby-prof (1.4.2)
- ruby-progressbar (1.10.1)
+ ruby-progressbar (1.11.0)
ruby-readability (0.7.0)
guess_html_encoding (>= 0.0.4)
nokogiri (>= 1.6.0)
- ruby2_keywords (0.0.2)
+ ruby2_keywords (0.0.4)
rubyzip (2.3.0)
- sanitize (5.2.1)
+ sanitize (5.2.3)
crass (~> 1.0.2)
nokogiri (>= 1.8.0)
nokogumbo (~> 2.0)
@@ -381,13 +395,13 @@ GEM
seed-fu (2.3.9)
activerecord (>= 3.1)
activesupport (>= 3.1)
- shoulda-matchers (4.4.1)
+ shoulda-matchers (4.5.0)
activesupport (>= 4.2.0)
sidekiq (6.1.2)
connection_pool (>= 2.2.2)
rack (~> 2.0)
redis (>= 4.2.0)
- simplecov (0.20.0)
+ simplecov (0.21.2)
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1)
@@ -403,22 +417,22 @@ GEM
sshkey (2.0.0)
stackprof (0.2.16)
test-prof (0.12.2)
- thor (1.0.1)
+ thor (1.1.0)
thread_safe (0.3.6)
tilt (2.0.10)
- tzinfo (1.2.8)
+ tzinfo (1.2.9)
thread_safe (~> 0.1)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.7)
- unicode-display_width (1.7.0)
- unicorn (5.7.0)
+ unicode-display_width (2.0.0)
+ unicorn (5.8.0)
kgio (~> 2.6)
raindrops (~> 0.7)
- uniform_notifier (1.13.0)
- webmock (3.10.0)
+ uniform_notifier (1.13.2)
+ webmock (3.11.1)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
@@ -427,10 +441,14 @@ GEM
jwt (~> 2.0)
xorcist (1.1.2)
yaml-lint (0.0.10)
- zeitwerk (2.4.1)
+ zeitwerk (2.4.2)
PLATFORMS
ruby
+ x86_64-darwin-18
+ x86_64-darwin-19
+ x86_64-darwin-20
+ x86_64-linux
DEPENDENCIES
actionmailer (= 6.0.3.3)
@@ -471,7 +489,6 @@ DEPENDENCIES
fast_blank
fast_xs
fastimage
- flamegraph
gc_tracer
highline
htmlentities
@@ -558,4 +575,4 @@ DEPENDENCIES
yaml-lint
BUNDLED WITH
- 2.1.4
+ 2.2.3
diff --git a/README.md b/README.md
index 91a9304300..9b78068886 100644
--- a/README.md
+++ b/README.md
@@ -94,7 +94,7 @@ The original Discourse code contributors can be found in [**AUTHORS.MD**](docs/A
## Copyright / License
-Copyright 2014 - 2020 Civilized Discourse Construction Kit, Inc.
+Copyright 2014 - 2021 Civilized Discourse Construction Kit, Inc.
Licensed under the GNU General Public License Version 2.0 (or later);
you may not use this work except in compliance with the License.
diff --git a/app/assets/javascripts/admin.js.erb b/app/assets/javascripts/admin.js.erb
index 41f0315deb..dda5756177 100644
--- a/app/assets/javascripts/admin.js.erb
+++ b/app/assets/javascripts/admin.js.erb
@@ -3,10 +3,10 @@ require_asset("main_include_admin.js")
DiscoursePluginRegistry.admin_javascripts.each { |js| require_asset(js) }
-DiscoursePluginRegistry.each_globbed_asset(admin: true) do |f, ext|
+DiscoursePluginRegistry.each_globbed_asset(admin: true) do |f|
if File.directory?(f)
depend_on(f)
- elsif f.to_s.end_with?(".#{ext}")
+ else
require_asset(f)
end
end
diff --git a/app/assets/javascripts/admin/addon/components/ace-editor.js b/app/assets/javascripts/admin/addon/components/ace-editor.js
index 41c22eff56..4f70345003 100644
--- a/app/assets/javascripts/admin/addon/components/ace-editor.js
+++ b/app/assets/javascripts/admin/addon/components/ace-editor.js
@@ -1,6 +1,6 @@
import Component from "@ember/component";
-import loadScript from "discourse/lib/load-script";
import getURL from "discourse-common/lib/get-url";
+import loadScript from "discourse/lib/load-script";
import { observes } from "discourse-common/utils/decorators";
import { on } from "@ember/object/evented";
diff --git a/app/assets/javascripts/admin/addon/components/admin-backups-logs.js b/app/assets/javascripts/admin/addon/components/admin-backups-logs.js
index 1bb36931a0..f691f3ffc6 100644
--- a/app/assets/javascripts/admin/addon/components/admin-backups-logs.js
+++ b/app/assets/javascripts/admin/addon/components/admin-backups-logs.js
@@ -1,8 +1,8 @@
-import I18n from "I18n";
-import { scheduleOnce } from "@ember/runloop";
-import Component from "@ember/component";
-import discourseDebounce from "discourse/lib/debounce";
import { observes, on } from "discourse-common/utils/decorators";
+import Component from "@ember/component";
+import I18n from "I18n";
+import discourseDebounce from "discourse-common/lib/debounce";
+import { scheduleOnce } from "@ember/runloop";
export default Component.extend({
classNames: ["admin-backups-logs"],
@@ -33,9 +33,7 @@ export default Component.extend({
}
},
- @on("init")
- @observes("logs.[]")
- _updateFormattedLogs: discourseDebounce(function () {
+ _updateFormattedLogsFunc: function () {
const logs = this.logs;
if (logs.length === 0) {
return;
@@ -57,7 +55,13 @@ export default Component.extend({
this.renderLogs();
scheduleOnce("afterRender", this, this._scrollDown);
- }, 150),
+ },
+
+ @on("init")
+ @observes("logs.[]")
+ _updateFormattedLogs() {
+ discourseDebounce(this, this._updateFormattedLogsFunc, 150);
+ },
renderLogs() {
const formattedLogs = this.formattedLogs;
diff --git a/app/assets/javascripts/admin/addon/components/admin-report-chart.js b/app/assets/javascripts/admin/addon/components/admin-report-chart.js
index 20a190d9d2..8a894b9562 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report-chart.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report-chart.js
@@ -1,8 +1,9 @@
-import { makeArray } from "discourse-common/lib/helpers";
-import { debounce, schedule } from "@ember/runloop";
import Component from "@ember/component";
-import { number } from "discourse/lib/formatter";
+import discourseDebounce from "discourse-common/lib/debounce";
import loadScript from "discourse/lib/load-script";
+import { makeArray } from "discourse-common/lib/helpers";
+import { number } from "discourse/lib/formatter";
+import { schedule } from "@ember/runloop";
export default Component.extend({
classNames: ["admin-report-chart"],
@@ -14,7 +15,7 @@ export default Component.extend({
this._super(...arguments);
this.resizeHandler = () =>
- debounce(this, this._scheduleChartRendering, 500);
+ discourseDebounce(this, this._scheduleChartRendering, 500);
},
didInsertElement() {
@@ -34,7 +35,7 @@ export default Component.extend({
didReceiveAttrs() {
this._super(...arguments);
- debounce(this, this._scheduleChartRendering, 100);
+ discourseDebounce(this, this._scheduleChartRendering, 100);
},
_scheduleChartRendering() {
diff --git a/app/assets/javascripts/admin/addon/components/admin-report-counts.js b/app/assets/javascripts/admin/addon/components/admin-report-counts.js
index 6d3c0b398b..03c690dbbd 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report-counts.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report-counts.js
@@ -1,5 +1,5 @@
-import { match } from "@ember/object/computed";
import Component from "@ember/component";
+import { match } from "@ember/object/computed";
export default Component.extend({
allTime: true,
tagName: "tr",
diff --git a/app/assets/javascripts/admin/addon/components/admin-report-stacked-chart.js b/app/assets/javascripts/admin/addon/components/admin-report-stacked-chart.js
index 3519e6a163..4cac3b15db 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report-stacked-chart.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report-stacked-chart.js
@@ -1,8 +1,9 @@
-import { makeArray } from "discourse-common/lib/helpers";
-import { debounce, schedule } from "@ember/runloop";
import Component from "@ember/component";
-import { number } from "discourse/lib/formatter";
+import discourseDebounce from "discourse-common/lib/debounce";
import loadScript from "discourse/lib/load-script";
+import { makeArray } from "discourse-common/lib/helpers";
+import { number } from "discourse/lib/formatter";
+import { schedule } from "@ember/runloop";
export default Component.extend({
classNames: ["admin-report-chart", "admin-report-stacked-chart"],
@@ -11,7 +12,7 @@ export default Component.extend({
this._super(...arguments);
this.resizeHandler = () =>
- debounce(this, this._scheduleChartRendering, 500);
+ discourseDebounce(this, this._scheduleChartRendering, 500);
},
didInsertElement() {
@@ -31,7 +32,7 @@ export default Component.extend({
didReceiveAttrs() {
this._super(...arguments);
- debounce(this, this._scheduleChartRendering, 100);
+ discourseDebounce(this, this._scheduleChartRendering, 100);
},
_scheduleChartRendering() {
diff --git a/app/assets/javascripts/admin/addon/components/admin-report-storage-stats.js b/app/assets/javascripts/admin/addon/components/admin-report-storage-stats.js
index b41304ec34..e12bc6432f 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report-storage-stats.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report-storage-stats.js
@@ -1,7 +1,7 @@
-import I18n from "I18n";
-import discourseComputed from "discourse-common/utils/decorators";
-import { alias } from "@ember/object/computed";
import Component from "@ember/component";
+import I18n from "I18n";
+import { alias } from "@ember/object/computed";
+import discourseComputed from "discourse-common/utils/decorators";
import { setting } from "discourse/lib/computed";
export default Component.extend({
diff --git a/app/assets/javascripts/admin/addon/components/admin-report-table-cell.js b/app/assets/javascripts/admin/addon/components/admin-report-table-cell.js
index 967370ab8e..aadf6e0f73 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report-table-cell.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report-table-cell.js
@@ -1,6 +1,6 @@
-import discourseComputed from "discourse-common/utils/decorators";
-import { alias } from "@ember/object/computed";
import Component from "@ember/component";
+import { alias } from "@ember/object/computed";
+import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({
tagName: "td",
diff --git a/app/assets/javascripts/admin/addon/components/admin-report-table-header.js b/app/assets/javascripts/admin/addon/components/admin-report-table-header.js
index f7c91dcab6..5c7cdf1e4c 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report-table-header.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report-table-header.js
@@ -1,5 +1,5 @@
-import discourseComputed from "discourse-common/utils/decorators";
import Component from "@ember/component";
+import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({
tagName: "th",
diff --git a/app/assets/javascripts/admin/addon/components/admin-report-table.js b/app/assets/javascripts/admin/addon/components/admin-report-table.js
index b44ea784dd..a237e93ee4 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report-table.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report-table.js
@@ -1,7 +1,7 @@
+import Component from "@ember/component";
+import { alias } from "@ember/object/computed";
import discourseComputed from "discourse-common/utils/decorators";
import { makeArray } from "discourse-common/lib/helpers";
-import { alias } from "@ember/object/computed";
-import Component from "@ember/component";
const PAGES_LIMIT = 8;
diff --git a/app/assets/javascripts/admin/addon/components/admin-report.js b/app/assets/javascripts/admin/addon/components/admin-report.js
index eb9b06f703..31fc2c2973 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report.js
@@ -1,16 +1,16 @@
-import I18n from "I18n";
-import discourseComputed from "discourse-common/utils/decorators";
-import { makeArray } from "discourse-common/lib/helpers";
-import { alias, or, and, equal, notEmpty } from "@ember/object/computed";
-import EmberObject, { computed, action } from "@ember/object";
-import { next } from "@ember/runloop";
-import Component from "@ember/component";
-import ReportLoader from "discourse/lib/reports-loader";
-import { exportEntity } from "discourse/lib/export-csv";
-import { outputExportResult } from "discourse/lib/export-result";
+import EmberObject, { action, computed } from "@ember/object";
import Report, { SCHEMA_VERSION } from "admin/models/report";
+import { alias, and, equal, notEmpty, or } from "@ember/object/computed";
+import Component from "@ember/component";
+import I18n from "I18n";
+import ReportLoader from "discourse/lib/reports-loader";
+import discourseComputed from "discourse-common/utils/decorators";
+import { exportEntity } from "discourse/lib/export-csv";
import { isPresent } from "@ember/utils";
import { isTesting } from "discourse-common/config/environment";
+import { makeArray } from "discourse-common/lib/helpers";
+import { next } from "@ember/runloop";
+import { outputExportResult } from "discourse/lib/export-result";
const TABLE_OPTIONS = {
perPage: 8,
diff --git a/app/assets/javascripts/admin/addon/components/admin-theme-editor.js b/app/assets/javascripts/admin/addon/components/admin-theme-editor.js
index c453c877d6..ac073c4b55 100644
--- a/app/assets/javascripts/admin/addon/components/admin-theme-editor.js
+++ b/app/assets/javascripts/admin/addon/components/admin-theme-editor.js
@@ -1,8 +1,8 @@
-import I18n from "I18n";
-import { next } from "@ember/runloop";
import Component from "@ember/component";
+import I18n from "I18n";
import discourseComputed from "discourse-common/utils/decorators";
import { fmt } from "discourse/lib/computed";
+import { next } from "@ember/runloop";
export default Component.extend({
@discourseComputed("theme.targets", "onlyOverridden", "showAdvanced")
diff --git a/app/assets/javascripts/admin/addon/components/admin-user-field-item.js b/app/assets/javascripts/admin/addon/components/admin-user-field-item.js
index 17634d5c49..c9642e3c94 100644
--- a/app/assets/javascripts/admin/addon/components/admin-user-field-item.js
+++ b/app/assets/javascripts/admin/addon/components/admin-user-field-item.js
@@ -1,16 +1,16 @@
-import I18n from "I18n";
-import { isEmpty } from "@ember/utils";
-import { empty } from "@ember/object/computed";
-import { scheduleOnce } from "@ember/runloop";
-import Component from "@ember/component";
-import UserField from "admin/models/user-field";
-import { bufferedProperty } from "discourse/mixins/buffered-content";
-import { popupAjaxError } from "discourse/lib/ajax-error";
-import { propertyEqual, i18n } from "discourse/lib/computed";
import discourseComputed, {
observes,
on,
} from "discourse-common/utils/decorators";
+import { i18n, propertyEqual } from "discourse/lib/computed";
+import Component from "@ember/component";
+import I18n from "I18n";
+import UserField from "admin/models/user-field";
+import { bufferedProperty } from "discourse/mixins/buffered-content";
+import { empty } from "@ember/object/computed";
+import { isEmpty } from "@ember/utils";
+import { popupAjaxError } from "discourse/lib/ajax-error";
+import { scheduleOnce } from "@ember/runloop";
export default Component.extend(bufferedProperty("userField"), {
editing: empty("userField.id"),
diff --git a/app/assets/javascripts/admin/addon/components/admin-watched-word.js b/app/assets/javascripts/admin/addon/components/admin-watched-word.js
index 061c83d56a..266b02b3c6 100644
--- a/app/assets/javascripts/admin/addon/components/admin-watched-word.js
+++ b/app/assets/javascripts/admin/addon/components/admin-watched-word.js
@@ -1,7 +1,7 @@
-import I18n from "I18n";
import Component from "@ember/component";
-import { iconHTML } from "discourse-common/lib/icon-library";
+import I18n from "I18n";
import bootbox from "bootbox";
+import { iconHTML } from "discourse-common/lib/icon-library";
export default Component.extend({
classNames: ["watched-word"],
diff --git a/app/assets/javascripts/admin/addon/components/admin-web-hook-event-chooser.js b/app/assets/javascripts/admin/addon/components/admin-web-hook-event-chooser.js
index 98e39518bf..1c8e59fd27 100644
--- a/app/assets/javascripts/admin/addon/components/admin-web-hook-event-chooser.js
+++ b/app/assets/javascripts/admin/addon/components/admin-web-hook-event-chooser.js
@@ -1,7 +1,7 @@
-import I18n from "I18n";
-import discourseComputed from "discourse-common/utils/decorators";
-import { alias } from "@ember/object/computed";
import Component from "@ember/component";
+import I18n from "I18n";
+import { alias } from "@ember/object/computed";
+import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({
classNames: ["hook-event"],
diff --git a/app/assets/javascripts/admin/addon/components/admin-web-hook-event.js b/app/assets/javascripts/admin/addon/components/admin-web-hook-event.js
index 75f1326a48..fbcf1594e0 100644
--- a/app/assets/javascripts/admin/addon/components/admin-web-hook-event.js
+++ b/app/assets/javascripts/admin/addon/components/admin-web-hook-event.js
@@ -1,10 +1,10 @@
-import I18n from "I18n";
-import discourseComputed from "discourse-common/utils/decorators";
-import Component from "@ember/component";
-import { ajax } from "discourse/lib/ajax";
-import { popupAjaxError } from "discourse/lib/ajax-error";
import { ensureJSON, plainJSON, prettyJSON } from "discourse/lib/formatter";
+import Component from "@ember/component";
+import I18n from "I18n";
+import { ajax } from "discourse/lib/ajax";
import bootbox from "bootbox";
+import discourseComputed from "discourse-common/utils/decorators";
+import { popupAjaxError } from "discourse/lib/ajax-error";
export default Component.extend({
tagName: "li",
diff --git a/app/assets/javascripts/admin/addon/components/admin-web-hook-status.js b/app/assets/javascripts/admin/addon/components/admin-web-hook-status.js
index 818970f125..a80a769e94 100644
--- a/app/assets/javascripts/admin/addon/components/admin-web-hook-status.js
+++ b/app/assets/javascripts/admin/addon/components/admin-web-hook-status.js
@@ -1,6 +1,6 @@
+import Component from "@ember/component";
import I18n from "I18n";
import discourseComputed from "discourse-common/utils/decorators";
-import Component from "@ember/component";
import { iconHTML } from "discourse-common/lib/icon-library";
export default Component.extend({
diff --git a/app/assets/javascripts/admin/addon/components/color-input.js b/app/assets/javascripts/admin/addon/components/color-input.js
index 3d7dad5e00..c563fedc94 100644
--- a/app/assets/javascripts/admin/addon/components/color-input.js
+++ b/app/assets/javascripts/admin/addon/components/color-input.js
@@ -1,8 +1,8 @@
-import { schedule } from "@ember/runloop";
-import Component from "@ember/component";
-import { computed, action } from "@ember/object";
+import { action, computed } from "@ember/object";
import loadScript, { loadCSS } from "discourse/lib/load-script";
+import Component from "@ember/component";
import { observes } from "discourse-common/utils/decorators";
+import { schedule } from "@ember/runloop";
/**
An input field for a color.
diff --git a/app/assets/javascripts/admin/addon/components/email-styles-editor.js b/app/assets/javascripts/admin/addon/components/email-styles-editor.js
index c40f8a543e..6f7cf6d021 100644
--- a/app/assets/javascripts/admin/addon/components/email-styles-editor.js
+++ b/app/assets/javascripts/admin/addon/components/email-styles-editor.js
@@ -1,8 +1,8 @@
+import Component from "@ember/component";
import I18n from "I18n";
+import bootbox from "bootbox";
import discourseComputed from "discourse-common/utils/decorators";
import { reads } from "@ember/object/computed";
-import Component from "@ember/component";
-import bootbox from "bootbox";
export default Component.extend({
editorId: reads("fieldName"),
diff --git a/app/assets/javascripts/admin/addon/components/embeddable-host.js b/app/assets/javascripts/admin/addon/components/embeddable-host.js
index 9846c9fc7b..a0f546227b 100644
--- a/app/assets/javascripts/admin/addon/components/embeddable-host.js
+++ b/app/assets/javascripts/admin/addon/components/embeddable-host.js
@@ -1,16 +1,12 @@
+import Category from "discourse/models/category";
+import Component from "@ember/component";
import I18n from "I18n";
-import discourseComputed, {
- on,
- observes,
-} from "discourse-common/utils/decorators";
+import bootbox from "bootbox";
+import { bufferedProperty } from "discourse/mixins/buffered-content";
+import discourseComputed from "discourse-common/utils/decorators";
import { isEmpty } from "@ember/utils";
import { or } from "@ember/object/computed";
-import { schedule } from "@ember/runloop";
-import Component from "@ember/component";
-import { bufferedProperty } from "discourse/mixins/buffered-content";
import { popupAjaxError } from "discourse/lib/ajax-error";
-import Category from "discourse/models/category";
-import bootbox from "bootbox";
export default Component.extend(bufferedProperty("host"), {
editToggled: false,
@@ -19,14 +15,6 @@ export default Component.extend(bufferedProperty("host"), {
editing: or("host.isNew", "editToggled"),
- @on("didInsertElement")
- @observes("editing")
- _focusOnInput() {
- schedule("afterRender", () => {
- this.element.querySelector(".host-name").focus();
- });
- },
-
@discourseComputed("buffered.host", "host.isSaving")
cantSave(host, isSaving) {
return isSaving || isEmpty(host);
diff --git a/app/assets/javascripts/admin/addon/components/embedding-setting.js b/app/assets/javascripts/admin/addon/components/embedding-setting.js
index 8c1a187ac6..7b8417aa06 100644
--- a/app/assets/javascripts/admin/addon/components/embedding-setting.js
+++ b/app/assets/javascripts/admin/addon/components/embedding-setting.js
@@ -1,5 +1,5 @@
-import discourseComputed from "discourse-common/utils/decorators";
import Component from "@ember/component";
+import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({
classNames: ["embed-setting"],
diff --git a/app/assets/javascripts/admin/addon/components/highlighted-code.js b/app/assets/javascripts/admin/addon/components/highlighted-code.js
index f5486db8d9..21cfaf6b15 100644
--- a/app/assets/javascripts/admin/addon/components/highlighted-code.js
+++ b/app/assets/javascripts/admin/addon/components/highlighted-code.js
@@ -1,5 +1,5 @@
+import { observes, on } from "discourse-common/utils/decorators";
import Component from "@ember/component";
-import { on, observes } from "discourse-common/utils/decorators";
import highlightSyntax from "discourse/lib/highlight-syntax";
export default Component.extend({
diff --git a/app/assets/javascripts/admin/addon/components/ip-lookup.js b/app/assets/javascripts/admin/addon/components/ip-lookup.js
index db19cb25c3..99929048a4 100644
--- a/app/assets/javascripts/admin/addon/components/ip-lookup.js
+++ b/app/assets/javascripts/admin/addon/components/ip-lookup.js
@@ -1,12 +1,12 @@
-import I18n from "I18n";
-import EmberObject from "@ember/object";
-import { later } from "@ember/runloop";
-import Component from "@ember/component";
-import discourseComputed from "discourse-common/utils/decorators";
-import { ajax } from "discourse/lib/ajax";
import AdminUser from "admin/models/admin-user";
-import copyText from "discourse/lib/copy-text";
+import Component from "@ember/component";
+import EmberObject from "@ember/object";
+import I18n from "I18n";
+import { ajax } from "discourse/lib/ajax";
import bootbox from "bootbox";
+import copyText from "discourse/lib/copy-text";
+import discourseComputed from "discourse-common/utils/decorators";
+import { later } from "@ember/runloop";
export default Component.extend({
classNames: ["ip-lookup"],
diff --git a/app/assets/javascripts/admin/addon/components/penalty-post-action.js b/app/assets/javascripts/admin/addon/components/penalty-post-action.js
index 4a46bbbea7..e010272447 100644
--- a/app/assets/javascripts/admin/addon/components/penalty-post-action.js
+++ b/app/assets/javascripts/admin/addon/components/penalty-post-action.js
@@ -1,9 +1,9 @@
-import I18n from "I18n";
import discourseComputed, {
afterRender,
} from "discourse-common/utils/decorators";
-import { equal } from "@ember/object/computed";
import Component from "@ember/component";
+import I18n from "I18n";
+import { equal } from "@ember/object/computed";
const ACTIONS = ["delete", "delete_replies", "edit", "none"];
diff --git a/app/assets/javascripts/admin/addon/components/permalink-form.js b/app/assets/javascripts/admin/addon/components/permalink-form.js
index b7238f5700..a5a8a95e35 100644
--- a/app/assets/javascripts/admin/addon/components/permalink-form.js
+++ b/app/assets/javascripts/admin/addon/components/permalink-form.js
@@ -1,10 +1,10 @@
-import I18n from "I18n";
-import { schedule } from "@ember/runloop";
import Component from "@ember/component";
-import discourseComputed from "discourse-common/utils/decorators";
-import { fmt } from "discourse/lib/computed";
+import I18n from "I18n";
import Permalink from "admin/models/permalink";
import bootbox from "bootbox";
+import discourseComputed from "discourse-common/utils/decorators";
+import { fmt } from "discourse/lib/computed";
+import { schedule } from "@ember/runloop";
export default Component.extend({
classNames: ["permalink-form"],
diff --git a/app/assets/javascripts/admin/addon/components/report-filters/bool.js b/app/assets/javascripts/admin/addon/components/report-filters/bool.js
index 0a752c54e2..544709791c 100644
--- a/app/assets/javascripts/admin/addon/components/report-filters/bool.js
+++ b/app/assets/javascripts/admin/addon/components/report-filters/bool.js
@@ -1,5 +1,5 @@
-import { action } from "@ember/object";
import FilterComponent from "admin/components/report-filters/filter";
+import { action } from "@ember/object";
export default FilterComponent.extend({
checked: false,
diff --git a/app/assets/javascripts/admin/addon/components/report-filters/category.js b/app/assets/javascripts/admin/addon/components/report-filters/category.js
index 4cbe965193..877c3aee7a 100644
--- a/app/assets/javascripts/admin/addon/components/report-filters/category.js
+++ b/app/assets/javascripts/admin/addon/components/report-filters/category.js
@@ -1,6 +1,6 @@
+import FilterComponent from "admin/components/report-filters/filter";
import { action } from "@ember/object";
import { readOnly } from "@ember/object/computed";
-import FilterComponent from "admin/components/report-filters/filter";
export default FilterComponent.extend({
category: readOnly("filter.default"),
diff --git a/app/assets/javascripts/admin/addon/components/report-filters/group.js b/app/assets/javascripts/admin/addon/components/report-filters/group.js
index 5cf379332b..30dd4c7b1b 100644
--- a/app/assets/javascripts/admin/addon/components/report-filters/group.js
+++ b/app/assets/javascripts/admin/addon/components/report-filters/group.js
@@ -1,5 +1,5 @@
-import { computed } from "@ember/object";
import FilterComponent from "admin/components/report-filters/filter";
+import { computed } from "@ember/object";
export default FilterComponent.extend({
classNames: ["group-filter"],
diff --git a/app/assets/javascripts/admin/addon/components/resumable-upload.js b/app/assets/javascripts/admin/addon/components/resumable-upload.js
index 0afa189a1d..8e3ce18e8c 100644
--- a/app/assets/javascripts/admin/addon/components/resumable-upload.js
+++ b/app/assets/javascripts/admin/addon/components/resumable-upload.js
@@ -1,9 +1,9 @@
-import getURL from "discourse-common/lib/get-url";
-import I18n from "I18n";
+import discourseComputed, { on } from "discourse-common/utils/decorators";
import { later, schedule } from "@ember/runloop";
import Component from "@ember/component";
+import I18n from "I18n";
+import getURL from "discourse-common/lib/get-url";
import { iconHTML } from "discourse-common/lib/icon-library";
-import discourseComputed, { on } from "discourse-common/utils/decorators";
/*global Resumable:true */
diff --git a/app/assets/javascripts/admin/addon/components/screened-ip-address-form.js b/app/assets/javascripts/admin/addon/components/screened-ip-address-form.js
index e738c81b85..40dd71ad9a 100644
--- a/app/assets/javascripts/admin/addon/components/screened-ip-address-form.js
+++ b/app/assets/javascripts/admin/addon/components/screened-ip-address-form.js
@@ -1,9 +1,9 @@
-import I18n from "I18n";
import discourseComputed, { on } from "discourse-common/utils/decorators";
-import { schedule } from "@ember/runloop";
import Component from "@ember/component";
-import bootbox from "bootbox";
+import I18n from "I18n";
import ScreenedIpAddress from "admin/models/screened-ip-address";
+import bootbox from "bootbox";
+import { schedule } from "@ember/runloop";
/**
A form to create an IP address that will be blocked or allowed.
diff --git a/app/assets/javascripts/admin/addon/components/secret-value-list.js b/app/assets/javascripts/admin/addon/components/secret-value-list.js
index 9b59c26d3a..5ad0e5b3ce 100644
--- a/app/assets/javascripts/admin/addon/components/secret-value-list.js
+++ b/app/assets/javascripts/admin/addon/components/secret-value-list.js
@@ -1,6 +1,6 @@
+import Component from "@ember/component";
import I18n from "I18n";
import { isEmpty } from "@ember/utils";
-import Component from "@ember/component";
import { on } from "discourse-common/utils/decorators";
import { set } from "@ember/object";
diff --git a/app/assets/javascripts/admin/addon/components/simple-list.js b/app/assets/javascripts/admin/addon/components/simple-list.js
index f3db4c5973..96136c98e2 100644
--- a/app/assets/javascripts/admin/addon/components/simple-list.js
+++ b/app/assets/javascripts/admin/addon/components/simple-list.js
@@ -1,6 +1,6 @@
-import { empty } from "@ember/object/computed";
import Component from "@ember/component";
import { action } from "@ember/object";
+import { empty } from "@ember/object/computed";
import { on } from "discourse-common/utils/decorators";
export default Component.extend({
diff --git a/app/assets/javascripts/admin/addon/components/site-setting.js b/app/assets/javascripts/admin/addon/components/site-setting.js
index 695ddac781..888daa3117 100644
--- a/app/assets/javascripts/admin/addon/components/site-setting.js
+++ b/app/assets/javascripts/admin/addon/components/site-setting.js
@@ -1,7 +1,7 @@
-import Component from "@ember/component";
import BufferedContent from "discourse/mixins/buffered-content";
-import SiteSetting from "admin/models/site-setting";
+import Component from "@ember/component";
import SettingComponent from "admin/mixins/setting-component";
+import SiteSetting from "admin/models/site-setting";
import { readOnly } from "@ember/object/computed";
export default Component.extend(BufferedContent, SettingComponent, {
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/bool.js b/app/assets/javascripts/admin/addon/components/site-settings/bool.js
index a565648c6d..70d7c59ae0 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/bool.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/bool.js
@@ -1,6 +1,6 @@
+import Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators";
import { isEmpty } from "@ember/utils";
-import Component from "@ember/component";
export default Component.extend({
@discourseComputed("value")
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/category-list.js b/app/assets/javascripts/admin/addon/components/site-settings/category-list.js
index 0369756c08..9dc792e6de 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/category-list.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/category-list.js
@@ -1,5 +1,5 @@
-import Component from "@ember/component";
import Category from "discourse/models/category";
+import Component from "@ember/component";
import { computed } from "@ember/object";
export default Component.extend({
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/color.js b/app/assets/javascripts/admin/addon/components/site-settings/color.js
index 7e5e71effc..8d098cb7d8 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/color.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/color.js
@@ -1,5 +1,5 @@
+import { action, computed } from "@ember/object";
import Component from "@ember/component";
-import { computed, action } from "@ember/object";
function RGBToHex(rgb) {
// Choose correct separator
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/group-list.js b/app/assets/javascripts/admin/addon/components/site-settings/group-list.js
index f7ea894503..ad9dbbfd1c 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/group-list.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/group-list.js
@@ -1,5 +1,5 @@
-import { computed } from "@ember/object";
import Component from "@ember/component";
+import { computed } from "@ember/object";
export default Component.extend({
tokenSeparator: "|",
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/tag-list.js b/app/assets/javascripts/admin/addon/components/site-settings/tag-list.js
index e5723668d7..d679063df1 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/tag-list.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/tag-list.js
@@ -1,6 +1,6 @@
-import discourseComputed from "discourse-common/utils/decorators";
import Component from "@ember/component";
import { action } from "@ember/object";
+import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({
@discourseComputed("value")
diff --git a/app/assets/javascripts/admin/addon/components/site-text-summary.js b/app/assets/javascripts/admin/addon/components/site-text-summary.js
index abe4f5fa63..071091f12b 100644
--- a/app/assets/javascripts/admin/addon/components/site-text-summary.js
+++ b/app/assets/javascripts/admin/addon/components/site-text-summary.js
@@ -1,6 +1,6 @@
import Component from "@ember/component";
-import { on } from "discourse-common/utils/decorators";
import highlightHTML from "discourse/lib/highlight-html";
+import { on } from "discourse-common/utils/decorators";
export default Component.extend({
classNames: ["site-text"],
diff --git a/app/assets/javascripts/admin/addon/components/suspension-details.js b/app/assets/javascripts/admin/addon/components/suspension-details.js
index f9edc0e225..e99a7e1c5b 100644
--- a/app/assets/javascripts/admin/addon/components/suspension-details.js
+++ b/app/assets/javascripts/admin/addon/components/suspension-details.js
@@ -1,8 +1,8 @@
import Component from "@ember/component";
-import discourseComputed from "discourse-common/utils/decorators";
import I18n from "I18n";
-import { equal } from "@ember/object/computed";
import { action } from "@ember/object";
+import discourseComputed from "discourse-common/utils/decorators";
+import { equal } from "@ember/object/computed";
const CUSTOM_REASON_KEY = "custom";
diff --git a/app/assets/javascripts/admin/addon/components/tags-uploader.js b/app/assets/javascripts/admin/addon/components/tags-uploader.js
index 3c547adf8d..1dc3bfc467 100644
--- a/app/assets/javascripts/admin/addon/components/tags-uploader.js
+++ b/app/assets/javascripts/admin/addon/components/tags-uploader.js
@@ -1,7 +1,7 @@
-import I18n from "I18n";
-import { alias } from "@ember/object/computed";
import Component from "@ember/component";
+import I18n from "I18n";
import UploadMixin from "discourse/mixins/upload";
+import { alias } from "@ember/object/computed";
import bootbox from "bootbox";
export default Component.extend(UploadMixin, {
diff --git a/app/assets/javascripts/admin/addon/components/theme-setting-editor.js b/app/assets/javascripts/admin/addon/components/theme-setting-editor.js
index cf87683ff7..8ceaf32bbb 100644
--- a/app/assets/javascripts/admin/addon/components/theme-setting-editor.js
+++ b/app/assets/javascripts/admin/addon/components/theme-setting-editor.js
@@ -1,5 +1,5 @@
-import Component from "@ember/component";
import BufferedContent from "discourse/mixins/buffered-content";
+import Component from "@ember/component";
import SettingComponent from "admin/mixins/setting-component";
import { ajax } from "discourse/lib/ajax";
import { url } from "discourse/lib/computed";
diff --git a/app/assets/javascripts/admin/addon/components/theme-setting-relatives-selector.js b/app/assets/javascripts/admin/addon/components/theme-setting-relatives-selector.js
index b23760f665..4f02a14768 100644
--- a/app/assets/javascripts/admin/addon/components/theme-setting-relatives-selector.js
+++ b/app/assets/javascripts/admin/addon/components/theme-setting-relatives-selector.js
@@ -1,5 +1,5 @@
-import Component from "@ember/component";
import BufferedContent from "discourse/mixins/buffered-content";
+import Component from "@ember/component";
import SettingComponent from "admin/mixins/setting-component";
export default Component.extend(BufferedContent, SettingComponent, {
diff --git a/app/assets/javascripts/admin/addon/components/theme-translation.js b/app/assets/javascripts/admin/addon/components/theme-translation.js
index 6174aeb4eb..7a598db1c8 100644
--- a/app/assets/javascripts/admin/addon/components/theme-translation.js
+++ b/app/assets/javascripts/admin/addon/components/theme-translation.js
@@ -1,7 +1,7 @@
-import { alias } from "@ember/object/computed";
-import Component from "@ember/component";
import BufferedContent from "discourse/mixins/buffered-content";
+import Component from "@ember/component";
import SettingComponent from "admin/mixins/setting-component";
+import { alias } from "@ember/object/computed";
export default Component.extend(BufferedContent, SettingComponent, {
layoutName: "admin/templates/components/site-setting",
diff --git a/app/assets/javascripts/admin/addon/components/themes-list-item.js b/app/assets/javascripts/admin/addon/components/themes-list-item.js
index d8af9eabc7..edc1783535 100644
--- a/app/assets/javascripts/admin/addon/components/themes-list-item.js
+++ b/app/assets/javascripts/admin/addon/components/themes-list-item.js
@@ -1,10 +1,10 @@
-import { gt, and } from "@ember/object/computed";
-import { schedule } from "@ember/runloop";
-import Component from "@ember/component";
+import { and, gt } from "@ember/object/computed";
import discourseComputed, { observes } from "discourse-common/utils/decorators";
-import { iconHTML } from "discourse-common/lib/icon-library";
+import Component from "@ember/component";
import { escape } from "pretty-text/sanitizer";
+import { iconHTML } from "discourse-common/lib/icon-library";
import { isTesting } from "discourse-common/config/environment";
+import { schedule } from "@ember/runloop";
const MAX_COMPONENTS = 4;
diff --git a/app/assets/javascripts/admin/addon/components/themes-list.js b/app/assets/javascripts/admin/addon/components/themes-list.js
index cdad5e454a..715ca9ccee 100644
--- a/app/assets/javascripts/admin/addon/components/themes-list.js
+++ b/app/assets/javascripts/admin/addon/components/themes-list.js
@@ -1,6 +1,6 @@
-import { gt, equal } from "@ember/object/computed";
+import { COMPONENTS, THEMES } from "admin/models/theme";
+import { equal, gt } from "@ember/object/computed";
import Component from "@ember/component";
-import { THEMES, COMPONENTS } from "admin/models/theme";
import discourseComputed from "discourse-common/utils/decorators";
import { inject as service } from "@ember/service";
diff --git a/app/assets/javascripts/admin/addon/components/value-list.js b/app/assets/javascripts/admin/addon/components/value-list.js
index 9951eee3f4..aa89de7f38 100644
--- a/app/assets/javascripts/admin/addon/components/value-list.js
+++ b/app/assets/javascripts/admin/addon/components/value-list.js
@@ -1,7 +1,7 @@
import discourseComputed, { on } from "discourse-common/utils/decorators";
-import { makeArray } from "discourse-common/lib/helpers";
import { empty, reads } from "@ember/object/computed";
import Component from "@ember/component";
+import { makeArray } from "discourse-common/lib/helpers";
export default Component.extend({
classNameBindings: [":value-list"],
diff --git a/app/assets/javascripts/admin/addon/components/watched-word-form.js b/app/assets/javascripts/admin/addon/components/watched-word-form.js
index 5dc9d7b8e6..788103f793 100644
--- a/app/assets/javascripts/admin/addon/components/watched-word-form.js
+++ b/app/assets/javascripts/admin/addon/components/watched-word-form.js
@@ -1,13 +1,13 @@
-import I18n from "I18n";
-import { isEmpty } from "@ember/utils";
-import { schedule } from "@ember/runloop";
+import discourseComputed, {
+ observes,
+ on,
+} from "discourse-common/utils/decorators";
import Component from "@ember/component";
+import I18n from "I18n";
import WatchedWord from "admin/models/watched-word";
import bootbox from "bootbox";
-import discourseComputed, {
- on,
- observes,
-} from "discourse-common/utils/decorators";
+import { isEmpty } from "@ember/utils";
+import { schedule } from "@ember/runloop";
export default Component.extend({
classNames: ["watched-word-form"],
diff --git a/app/assets/javascripts/admin/addon/components/watched-word-uploader.js b/app/assets/javascripts/admin/addon/components/watched-word-uploader.js
index 800c0d4988..00c8ce4d99 100644
--- a/app/assets/javascripts/admin/addon/components/watched-word-uploader.js
+++ b/app/assets/javascripts/admin/addon/components/watched-word-uploader.js
@@ -1,9 +1,9 @@
-import I18n from "I18n";
-import discourseComputed from "discourse-common/utils/decorators";
-import { alias } from "@ember/object/computed";
import Component from "@ember/component";
+import I18n from "I18n";
import UploadMixin from "discourse/mixins/upload";
+import { alias } from "@ember/object/computed";
import bootbox from "bootbox";
+import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend(UploadMixin, {
type: "txt",
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-api-keys-index.js b/app/assets/javascripts/admin/addon/controllers/admin-api-keys-index.js
index 880a2c6435..5b4ee4ee0a 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-api-keys-index.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-api-keys-index.js
@@ -1,5 +1,5 @@
-import { popupAjaxError } from "discourse/lib/ajax-error";
import Controller from "@ember/controller";
+import { popupAjaxError } from "discourse/lib/ajax-error";
export default Controller.extend({
actions: {
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-api-keys-new.js b/app/assets/javascripts/admin/addon/controllers/admin-api-keys-new.js
index 06e495109c..8d56042a67 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-api-keys-new.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-api-keys-new.js
@@ -1,7 +1,7 @@
-import I18n from "I18n";
-import { isBlank } from "@ember/utils";
import Controller from "@ember/controller";
+import I18n from "I18n";
import discourseComputed from "discourse-common/utils/decorators";
+import { isBlank } from "@ember/utils";
import { popupAjaxError } from "discourse/lib/ajax-error";
import showModal from "discourse/lib/show-modal";
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-api-keys-show.js b/app/assets/javascripts/admin/addon/controllers/admin-api-keys-show.js
index 11251a45e6..28a883d985 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-api-keys-show.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-api-keys-show.js
@@ -1,8 +1,8 @@
-import { bufferedProperty } from "discourse/mixins/buffered-content";
import Controller from "@ember/controller";
+import { bufferedProperty } from "discourse/mixins/buffered-content";
+import { empty } from "@ember/object/computed";
import { isEmpty } from "@ember/utils";
import { popupAjaxError } from "discourse/lib/ajax-error";
-import { empty } from "@ember/object/computed";
import showModal from "discourse/lib/show-modal";
export default Controller.extend(bufferedProperty("model"), {
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-backups-index.js b/app/assets/javascripts/admin/addon/controllers/admin-backups-index.js
index c32e70f633..c53adeecf9 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-backups-index.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-backups-index.js
@@ -1,10 +1,10 @@
-import I18n from "I18n";
-import { alias, equal } from "@ember/object/computed";
import Controller, { inject as controller } from "@ember/controller";
+import { alias, equal } from "@ember/object/computed";
+import { i18n, setting } from "discourse/lib/computed";
+import I18n from "I18n";
import { ajax } from "discourse/lib/ajax";
-import discourseComputed from "discourse-common/utils/decorators";
-import { setting, i18n } from "discourse/lib/computed";
import bootbox from "bootbox";
+import discourseComputed from "discourse-common/utils/decorators";
export default Controller.extend({
adminBackups: controller(),
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-backups-logs.js b/app/assets/javascripts/admin/addon/controllers/admin-backups-logs.js
index 8c70f05439..e8a1694e2c 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-backups-logs.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-backups-logs.js
@@ -1,5 +1,5 @@
-import { alias } from "@ember/object/computed";
import Controller, { inject as controller } from "@ember/controller";
+import { alias } from "@ember/object/computed";
export default Controller.extend({
adminBackups: controller(),
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-backups.js b/app/assets/javascripts/admin/addon/controllers/admin-backups.js
index 83a93d8898..77dfbc3132 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-backups.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-backups.js
@@ -1,4 +1,4 @@
-import { not, and } from "@ember/object/computed";
+import { and, not } from "@ember/object/computed";
import Controller from "@ember/controller";
export default Controller.extend({
noOperationIsRunning: not("model.isOperationRunning"),
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-badges-award.js b/app/assets/javascripts/admin/addon/controllers/admin-badges-award.js
index f3ef51d701..218b3cb0e0 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-badges-award.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-badges-award.js
@@ -1,8 +1,8 @@
-import I18n from "I18n";
import Controller from "@ember/controller";
+import I18n from "I18n";
import { ajax } from "discourse/lib/ajax";
-import { popupAjaxError } from "discourse/lib/ajax-error";
import bootbox from "bootbox";
+import { popupAjaxError } from "discourse/lib/ajax-error";
export default Controller.extend({
saving: false,
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-badges-show.js b/app/assets/javascripts/admin/addon/controllers/admin-badges-show.js
index 3fec918ba9..3653af5fb1 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-badges-show.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-badges-show.js
@@ -1,12 +1,12 @@
-import I18n from "I18n";
-import discourseComputed, { observes } from "discourse-common/utils/decorators";
-import { reads } from "@ember/object/computed";
import Controller, { inject as controller } from "@ember/controller";
-import { popupAjaxError } from "discourse/lib/ajax-error";
-import { bufferedProperty } from "discourse/mixins/buffered-content";
-import { propertyNotEqual } from "discourse/lib/computed";
-import { run } from "@ember/runloop";
+import discourseComputed, { observes } from "discourse-common/utils/decorators";
+import I18n from "I18n";
import bootbox from "bootbox";
+import { bufferedProperty } from "discourse/mixins/buffered-content";
+import { popupAjaxError } from "discourse/lib/ajax-error";
+import { propertyNotEqual } from "discourse/lib/computed";
+import { reads } from "@ember/object/computed";
+import { run } from "@ember/runloop";
export default Controller.extend(bufferedProperty("model"), {
adminBadges: controller(),
@@ -56,6 +56,11 @@ export default Controller.extend(bufferedProperty("model"), {
return modelQuery && modelQuery.trim().length > 0;
},
+ @discourseComputed("model.i18n_name")
+ textCustomizationPrefix(i18n_name) {
+ return `badges.${i18n_name}.`;
+ },
+
@observes("model.id")
_resetSaving: function () {
this.set("saving", false);
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-badges.js b/app/assets/javascripts/admin/addon/controllers/admin-badges.js
index 433c49bac5..11d78fc4cc 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-badges.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-badges.js
@@ -1,6 +1,6 @@
import Controller from "@ember/controller";
-import { inject as service } from "@ember/service";
import discourseComputed from "discourse-common/utils/decorators";
+import { inject as service } from "@ember/service";
export default Controller.extend({
routing: service("-routing"),
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-customize-colors-show.js b/app/assets/javascripts/admin/addon/controllers/admin-customize-colors-show.js
index 5fa6218839..37394fd17f 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-customize-colors-show.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-customize-colors-show.js
@@ -1,8 +1,8 @@
+import Controller from "@ember/controller";
import I18n from "I18n";
+import bootbox from "bootbox";
import discourseComputed from "discourse-common/utils/decorators";
import { later } from "@ember/runloop";
-import Controller from "@ember/controller";
-import bootbox from "bootbox";
export default Controller.extend({
@discourseComputed("model.colors", "onlyOverridden")
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-customize-colors.js b/app/assets/javascripts/admin/addon/controllers/admin-customize-colors.js
index 01898b161a..7f06b1f3f0 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-customize-colors.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-customize-colors.js
@@ -1,8 +1,8 @@
-import I18n from "I18n";
-import EmberObject from "@ember/object";
import Controller from "@ember/controller";
-import showModal from "discourse/lib/show-modal";
+import EmberObject from "@ember/object";
+import I18n from "I18n";
import discourseComputed from "discourse-common/utils/decorators";
+import showModal from "discourse/lib/show-modal";
export default Controller.extend({
@discourseComputed("model.@each.id")
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-customize-email-style-edit.js b/app/assets/javascripts/admin/addon/controllers/admin-customize-email-style-edit.js
index f1190600e8..79813399b2 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-customize-email-style-edit.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-customize-email-style-edit.js
@@ -1,7 +1,7 @@
-import I18n from "I18n";
-import discourseComputed from "discourse-common/utils/decorators";
import Controller from "@ember/controller";
+import I18n from "I18n";
import bootbox from "bootbox";
+import discourseComputed from "discourse-common/utils/decorators";
export default Controller.extend({
@discourseComputed("model.isSaving")
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-customize-email-templates-edit.js b/app/assets/javascripts/admin/addon/controllers/admin-customize-email-templates-edit.js
index f5f7a563ef..d20f812ca3 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-customize-email-templates-edit.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-customize-email-templates-edit.js
@@ -1,10 +1,10 @@
-import I18n from "I18n";
-import discourseComputed from "discourse-common/utils/decorators";
import Controller, { inject as controller } from "@ember/controller";
-import { popupAjaxError } from "discourse/lib/ajax-error";
-import { bufferedProperty } from "discourse/mixins/buffered-content";
+import I18n from "I18n";
import { action } from "@ember/object";
import bootbox from "bootbox";
+import { bufferedProperty } from "discourse/mixins/buffered-content";
+import discourseComputed from "discourse-common/utils/decorators";
+import { popupAjaxError } from "discourse/lib/ajax-error";
export default Controller.extend(bufferedProperty("emailTemplate"), {
adminCustomizeEmailTemplates: controller(),
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-customize-email-templates.js b/app/assets/javascripts/admin/addon/controllers/admin-customize-email-templates.js
index 415cf1d157..a3d7f360e0 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-customize-email-templates.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-customize-email-templates.js
@@ -1,6 +1,6 @@
-import { sort } from "@ember/object/computed";
-import { action } from "@ember/object";
import Controller from "@ember/controller";
+import { action } from "@ember/object";
+import { sort } from "@ember/object/computed";
export default Controller.extend({
sortedTemplates: sort("emailTemplates", "titleSorting"),
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-customize-robots-txt.js b/app/assets/javascripts/admin/addon/controllers/admin-customize-robots-txt.js
index 7da0720744..a178f2c999 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-customize-robots-txt.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-customize-robots-txt.js
@@ -1,7 +1,7 @@
-import { not } from "@ember/object/computed";
import Controller from "@ember/controller";
import { ajax } from "discourse/lib/ajax";
import { bufferedProperty } from "discourse/mixins/buffered-content";
+import { not } from "@ember/object/computed";
import { propertyEqual } from "discourse/lib/computed";
export default Controller.extend(bufferedProperty("model"), {
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-customize-themes-edit.js b/app/assets/javascripts/admin/addon/controllers/admin-customize-themes-edit.js
index 889d90a921..2e1536d181 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-customize-themes-edit.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-customize-themes-edit.js
@@ -1,7 +1,7 @@
-import I18n from "I18n";
import Controller from "@ember/controller";
-import { url } from "discourse/lib/computed";
+import I18n from "I18n";
import discourseComputed from "discourse-common/utils/decorators";
+import { url } from "discourse/lib/computed";
export default Controller.extend({
section: null,
@@ -64,5 +64,9 @@ export default Controller.extend({
}
}
},
+
+ goBack() {
+ this.replaceRoute(this.showRouteName, this.model.id);
+ },
},
});
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-customize-themes-show.js b/app/assets/javascripts/admin/addon/controllers/admin-customize-themes-show.js
index 9e9afda71d..ba3a2d323c 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-customize-themes-show.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-customize-themes-show.js
@@ -1,21 +1,21 @@
-import I18n from "I18n";
-import { makeArray } from "discourse-common/lib/helpers";
+import { COMPONENTS, THEMES } from "admin/models/theme";
import {
empty,
filterBy,
- match,
mapBy,
+ match,
notEmpty,
} from "@ember/object/computed";
import Controller from "@ember/controller";
+import EmberObject from "@ember/object";
+import I18n from "I18n";
+import ThemeSettings from "admin/models/theme-settings";
+import bootbox from "bootbox";
import discourseComputed from "discourse-common/utils/decorators";
-import { url } from "discourse/lib/computed";
+import { makeArray } from "discourse-common/lib/helpers";
import { popupAjaxError } from "discourse/lib/ajax-error";
import showModal from "discourse/lib/show-modal";
-import ThemeSettings from "admin/models/theme-settings";
-import { THEMES, COMPONENTS } from "admin/models/theme";
-import EmberObject from "@ember/object";
-import bootbox from "bootbox";
+import { url } from "discourse/lib/computed";
const THEME_UPLOAD_VAR = 2;
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-customize-themes.js b/app/assets/javascripts/admin/addon/controllers/admin-customize-themes.js
index 3ffe9301f1..17dda66040 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-customize-themes.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-customize-themes.js
@@ -1,6 +1,6 @@
import Controller from "@ember/controller";
-import discourseComputed from "discourse-common/utils/decorators";
import { THEMES } from "admin/models/theme";
+import discourseComputed from "discourse-common/utils/decorators";
export default Controller.extend({
currentTab: THEMES,
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-dashboard-general.js b/app/assets/javascripts/admin/addon/controllers/admin-dashboard-general.js
index fe97fb0855..a831b686bc 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-dashboard-general.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-dashboard-general.js
@@ -1,13 +1,13 @@
-import I18n from "I18n";
-import discourseComputed from "discourse-common/utils/decorators";
-import { makeArray } from "discourse-common/lib/helpers";
import Controller, { inject } from "@ember/controller";
-import { setting } from "discourse/lib/computed";
import AdminDashboard from "admin/models/admin-dashboard";
-import Report from "admin/models/report";
+import I18n from "I18n";
import PeriodComputationMixin from "admin/mixins/period-computation";
+import Report from "admin/models/report";
import { computed } from "@ember/object";
+import discourseComputed from "discourse-common/utils/decorators";
import getURL from "discourse-common/lib/get-url";
+import { makeArray } from "discourse-common/lib/helpers";
+import { setting } from "discourse/lib/computed";
function staticReport(reportType) {
return computed("reports.[]", function () {
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-dashboard-moderation.js b/app/assets/javascripts/admin/addon/controllers/admin-dashboard-moderation.js
index 6781c50bde..16e632d6e2 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-dashboard-moderation.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-dashboard-moderation.js
@@ -1,8 +1,8 @@
-import getURL from "discourse-common/lib/get-url";
-import discourseComputed from "discourse-common/utils/decorators";
import Controller from "@ember/controller";
import PeriodComputationMixin from "admin/mixins/period-computation";
import { computed } from "@ember/object";
+import discourseComputed from "discourse-common/utils/decorators";
+import getURL from "discourse-common/lib/get-url";
export default Controller.extend(PeriodComputationMixin, {
@discourseComputed
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-dashboard-reports.js b/app/assets/javascripts/admin/addon/controllers/admin-dashboard-reports.js
index 966304a0e5..ab10591c80 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-dashboard-reports.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-dashboard-reports.js
@@ -1,7 +1,7 @@
-import discourseComputed from "discourse-common/utils/decorators";
-import { debounce } from "@ember/runloop";
import Controller from "@ember/controller";
import { INPUT_DELAY } from "discourse-common/config/environment";
+import discourseComputed from "discourse-common/utils/decorators";
+import discourseDebounce from "discourse-common/lib/debounce";
const { get } = Ember;
@@ -34,7 +34,7 @@ export default Controller.extend({
actions: {
filterReports(filter) {
- debounce(this, this._performFiltering, filter, INPUT_DELAY);
+ discourseDebounce(this, this._performFiltering, filter, INPUT_DELAY);
},
},
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-dashboard.js b/app/assets/javascripts/admin/addon/controllers/admin-dashboard.js
index 29e1ad0c5a..89955953fb 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-dashboard.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-dashboard.js
@@ -1,9 +1,9 @@
-import discourseComputed from "discourse-common/utils/decorators";
import Controller, { inject } from "@ember/controller";
-import { setting } from "discourse/lib/computed";
-import { computed } from "@ember/object";
import AdminDashboard from "admin/models/admin-dashboard";
import VersionCheck from "admin/models/version-check";
+import { computed } from "@ember/object";
+import discourseComputed from "discourse-common/utils/decorators";
+import { setting } from "discourse/lib/computed";
const PROBLEMS_CHECK_MINUTES = 1;
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-email-bounced.js b/app/assets/javascripts/admin/addon/controllers/admin-email-bounced.js
index 07721cdff0..1500549564 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-email-bounced.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-email-bounced.js
@@ -1,11 +1,11 @@
import AdminEmailLogsController from "admin/controllers/admin-email-logs";
-import discourseDebounce from "discourse/lib/debounce";
-import { observes } from "discourse-common/utils/decorators";
import { INPUT_DELAY } from "discourse-common/config/environment";
+import discourseDebounce from "discourse-common/lib/debounce";
+import { observes } from "discourse-common/utils/decorators";
export default AdminEmailLogsController.extend({
@observes("filter.{status,user,address,type}")
- filterEmailLogs: discourseDebounce(function () {
- this.loadLogs();
- }, INPUT_DELAY),
+ filterEmailLogs() {
+ discourseDebounce(this, this.loadLogs, INPUT_DELAY);
+ },
});
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-email-index.js b/app/assets/javascripts/admin/addon/controllers/admin-email-index.js
index f356731e6d..18bfd4a8c4 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-email-index.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-email-index.js
@@ -1,9 +1,9 @@
-import I18n from "I18n";
-import { empty } from "@ember/object/computed";
import Controller from "@ember/controller";
+import I18n from "I18n";
import { ajax } from "discourse/lib/ajax";
-import { observes } from "discourse-common/utils/decorators";
import bootbox from "bootbox";
+import { empty } from "@ember/object/computed";
+import { observes } from "discourse-common/utils/decorators";
export default Controller.extend({
/**
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-email-preview-digest.js b/app/assets/javascripts/admin/addon/controllers/admin-email-preview-digest.js
index 4b6ba80ce6..4210f9cff2 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-email-preview-digest.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-email-preview-digest.js
@@ -1,8 +1,8 @@
-import { empty, or, notEmpty } from "@ember/object/computed";
+import { empty, notEmpty, or } from "@ember/object/computed";
import Controller from "@ember/controller";
import EmailPreview from "admin/models/email-preview";
-import { popupAjaxError } from "discourse/lib/ajax-error";
import bootbox from "bootbox";
+import { popupAjaxError } from "discourse/lib/ajax-error";
export default Controller.extend({
username: null,
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-email-received.js b/app/assets/javascripts/admin/addon/controllers/admin-email-received.js
index ab02337866..0a2933fa23 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-email-received.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-email-received.js
@@ -1,14 +1,14 @@
import AdminEmailLogsController from "admin/controllers/admin-email-logs";
-import discourseDebounce from "discourse/lib/debounce";
-import IncomingEmail from "admin/models/incoming-email";
-import { observes } from "discourse-common/utils/decorators";
import { INPUT_DELAY } from "discourse-common/config/environment";
+import IncomingEmail from "admin/models/incoming-email";
+import discourseDebounce from "discourse-common/lib/debounce";
+import { observes } from "discourse-common/utils/decorators";
export default AdminEmailLogsController.extend({
@observes("filter.{status,from,to,subject}")
- filterIncomingEmails: discourseDebounce(function () {
- this.loadLogs(IncomingEmail);
- }, INPUT_DELAY),
+ filterIncomingEmails() {
+ discourseDebounce(this, this.loadLogs, IncomingEmail, INPUT_DELAY);
+ },
actions: {
loadMore() {
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-email-rejected.js b/app/assets/javascripts/admin/addon/controllers/admin-email-rejected.js
index 2c160648c6..89c67f3cf9 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-email-rejected.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-email-rejected.js
@@ -1,14 +1,14 @@
import AdminEmailLogsController from "admin/controllers/admin-email-logs";
-import discourseDebounce from "discourse/lib/debounce";
-import IncomingEmail from "admin/models/incoming-email";
-import { observes } from "discourse-common/utils/decorators";
import { INPUT_DELAY } from "discourse-common/config/environment";
+import IncomingEmail from "admin/models/incoming-email";
+import discourseDebounce from "discourse-common/lib/debounce";
+import { observes } from "discourse-common/utils/decorators";
export default AdminEmailLogsController.extend({
@observes("filter.{status,from,to,subject,error}")
- filterIncomingEmails: discourseDebounce(function () {
- this.loadLogs(IncomingEmail);
- }, INPUT_DELAY),
+ filterIncomingEmails() {
+ discourseDebounce(this, this.loadLogs, IncomingEmail, INPUT_DELAY);
+ },
actions: {
loadMore() {
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-email-sent.js b/app/assets/javascripts/admin/addon/controllers/admin-email-sent.js
index 2c7890cde8..5cc83109f8 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-email-sent.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-email-sent.js
@@ -1,11 +1,11 @@
import AdminEmailLogsController from "admin/controllers/admin-email-logs";
-import discourseDebounce from "discourse/lib/debounce";
-import { observes } from "discourse-common/utils/decorators";
import { INPUT_DELAY } from "discourse-common/config/environment";
+import discourseDebounce from "discourse-common/lib/debounce";
+import { observes } from "discourse-common/utils/decorators";
export default AdminEmailLogsController.extend({
@observes("filter.{status,user,address,type,reply_key}")
- filterEmailLogs: discourseDebounce(function () {
- this.loadLogs();
- }, INPUT_DELAY),
+ filterEmailLogs() {
+ discourseDebounce(this, this.loadLogs, INPUT_DELAY);
+ },
});
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-email-skipped.js b/app/assets/javascripts/admin/addon/controllers/admin-email-skipped.js
index 07721cdff0..1500549564 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-email-skipped.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-email-skipped.js
@@ -1,11 +1,11 @@
import AdminEmailLogsController from "admin/controllers/admin-email-logs";
-import discourseDebounce from "discourse/lib/debounce";
-import { observes } from "discourse-common/utils/decorators";
import { INPUT_DELAY } from "discourse-common/config/environment";
+import discourseDebounce from "discourse-common/lib/debounce";
+import { observes } from "discourse-common/utils/decorators";
export default AdminEmailLogsController.extend({
@observes("filter.{status,user,address,type}")
- filterEmailLogs: discourseDebounce(function () {
- this.loadLogs();
- }, INPUT_DELAY),
+ filterEmailLogs() {
+ discourseDebounce(this, this.loadLogs, INPUT_DELAY);
+ },
});
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-embedding.js b/app/assets/javascripts/admin/addon/controllers/admin-embedding.js
index df7f856ed5..147d4dd35a 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-embedding.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-embedding.js
@@ -1,5 +1,5 @@
-import discourseComputed from "discourse-common/utils/decorators";
import Controller from "@ember/controller";
+import discourseComputed from "discourse-common/utils/decorators";
import { popupAjaxError } from "discourse/lib/ajax-error";
export default Controller.extend({
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-emojis.js b/app/assets/javascripts/admin/addon/controllers/admin-emojis.js
index 4019cb188e..94e284c0c9 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-emojis.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-emojis.js
@@ -1,9 +1,9 @@
-import I18n from "I18n";
-import { sort } from "@ember/object/computed";
import EmberObject, { action, computed } from "@ember/object";
import Controller from "@ember/controller";
+import I18n from "I18n";
import { ajax } from "discourse/lib/ajax";
import bootbox from "bootbox";
+import { sort } from "@ember/object/computed";
const ALL_FILTER = "all";
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-logs-screened-emails.js b/app/assets/javascripts/admin/addon/controllers/admin-logs-screened-emails.js
index 134968eb10..ed3cd6489d 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-logs-screened-emails.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-logs-screened-emails.js
@@ -1,7 +1,7 @@
import Controller from "@ember/controller";
+import ScreenedEmail from "admin/models/screened-email";
import { exportEntity } from "discourse/lib/export-csv";
import { outputExportResult } from "discourse/lib/export-result";
-import ScreenedEmail from "admin/models/screened-email";
export default Controller.extend({
loading: false,
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-logs-screened-ip-addresses.js b/app/assets/javascripts/admin/addon/controllers/admin-logs-screened-ip-addresses.js
index 68ac649425..fb923131ed 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-logs-screened-ip-addresses.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-logs-screened-ip-addresses.js
@@ -1,25 +1,29 @@
-import I18n from "I18n";
import Controller from "@ember/controller";
-import discourseDebounce from "discourse/lib/debounce";
-import { outputExportResult } from "discourse/lib/export-result";
-import { exportEntity } from "discourse/lib/export-csv";
-import ScreenedIpAddress from "admin/models/screened-ip-address";
-import { observes } from "discourse-common/utils/decorators";
+import I18n from "I18n";
import { INPUT_DELAY } from "discourse-common/config/environment";
+import ScreenedIpAddress from "admin/models/screened-ip-address";
import bootbox from "bootbox";
+import discourseDebounce from "discourse-common/lib/debounce";
+import { exportEntity } from "discourse/lib/export-csv";
+import { observes } from "discourse-common/utils/decorators";
+import { outputExportResult } from "discourse/lib/export-result";
export default Controller.extend({
loading: false,
filter: null,
savedIpAddress: null,
- @observes("filter")
- show: discourseDebounce(function () {
+ _debouncedShow() {
this.set("loading", true);
ScreenedIpAddress.findAll(this.filter).then((result) => {
this.setProperties({ model: result, loading: false });
});
- }, INPUT_DELAY),
+ },
+
+ @observes("filter")
+ show() {
+ discourseDebounce(this, this._debouncedShow, INPUT_DELAY);
+ },
actions: {
allow(record) {
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-logs-screened-urls.js b/app/assets/javascripts/admin/addon/controllers/admin-logs-screened-urls.js
index 90d008bb86..86621f5968 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-logs-screened-urls.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-logs-screened-urls.js
@@ -1,7 +1,7 @@
import Controller from "@ember/controller";
+import ScreenedUrl from "admin/models/screened-url";
import { exportEntity } from "discourse/lib/export-csv";
import { outputExportResult } from "discourse/lib/export-result";
-import ScreenedUrl from "admin/models/screened-url";
export default Controller.extend({
loading: false,
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-logs-staff-action-logs.js b/app/assets/javascripts/admin/addon/controllers/admin-logs-staff-action-logs.js
index 70496049d1..2758a10aa1 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-logs-staff-action-logs.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-logs-staff-action-logs.js
@@ -1,10 +1,10 @@
import Controller from "@ember/controller";
import EmberObject from "@ember/object";
-import { scheduleOnce } from "@ember/runloop";
+import I18n from "I18n";
import discourseComputed from "discourse-common/utils/decorators";
import { exportEntity } from "discourse/lib/export-csv";
import { outputExportResult } from "discourse/lib/export-result";
-import I18n from "I18n";
+import { scheduleOnce } from "@ember/runloop";
export default Controller.extend({
queryParams: ["filters"],
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-permalinks.js b/app/assets/javascripts/admin/addon/controllers/admin-permalinks.js
index 729cdab0c8..b11b397311 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-permalinks.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-permalinks.js
@@ -1,22 +1,26 @@
-import I18n from "I18n";
import Controller from "@ember/controller";
-import discourseDebounce from "discourse/lib/debounce";
-import Permalink from "admin/models/permalink";
-import { observes } from "discourse-common/utils/decorators";
+import I18n from "I18n";
import { INPUT_DELAY } from "discourse-common/config/environment";
+import Permalink from "admin/models/permalink";
import bootbox from "bootbox";
+import discourseDebounce from "discourse-common/lib/debounce";
+import { observes } from "discourse-common/utils/decorators";
export default Controller.extend({
loading: false,
filter: null,
- @observes("filter")
- show: discourseDebounce(function () {
+ _debouncedShow() {
Permalink.findAll(this.filter).then((result) => {
this.set("model", result);
this.set("loading", false);
});
- }, INPUT_DELAY),
+ },
+
+ @observes("filter")
+ show() {
+ discourseDebounce(this, this._debouncedShow, INPUT_DELAY);
+ },
actions: {
recordAdded(arg) {
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-plugins.js b/app/assets/javascripts/admin/addon/controllers/admin-plugins.js
index 955aaba5c3..d19c5584aa 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-plugins.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-plugins.js
@@ -1,5 +1,5 @@
-import discourseComputed from "discourse-common/utils/decorators";
import Controller from "@ember/controller";
+import discourseComputed from "discourse-common/utils/decorators";
export default Controller.extend({
@discourseComputed
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-reports-show.js b/app/assets/javascripts/admin/addon/controllers/admin-reports-show.js
index c20dfc1c2e..64a2c5de93 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-reports-show.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-reports-show.js
@@ -1,5 +1,5 @@
-import discourseComputed from "discourse-common/utils/decorators";
import Controller from "@ember/controller";
+import discourseComputed from "discourse-common/utils/decorators";
export default Controller.extend({
queryParams: ["start_date", "end_date", "filters", "chart_grouping"],
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-search-logs-index.js b/app/assets/javascripts/admin/addon/controllers/admin-search-logs-index.js
index 2e2bcb4f73..bf110796f2 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-search-logs-index.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-search-logs-index.js
@@ -1,5 +1,5 @@
-import I18n from "I18n";
import Controller from "@ember/controller";
+import I18n from "I18n";
export const DEFAULT_PERIOD = "yearly";
export default Controller.extend({
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-search-logs-term.js b/app/assets/javascripts/admin/addon/controllers/admin-search-logs-term.js
index 8ee5dd5df1..2d4f22211b 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-search-logs-term.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-search-logs-term.js
@@ -1,6 +1,6 @@
-import I18n from "I18n";
import Controller from "@ember/controller";
import { DEFAULT_PERIOD } from "admin/controllers/admin-search-logs-index";
+import I18n from "I18n";
export default Controller.extend({
loading: false,
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-site-settings-category.js b/app/assets/javascripts/admin/addon/controllers/admin-site-settings-category.js
index 5a12f1d717..2727c56010 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-site-settings-category.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-site-settings-category.js
@@ -1,5 +1,5 @@
-import discourseComputed from "discourse-common/utils/decorators";
import Controller, { inject as controller } from "@ember/controller";
+import discourseComputed from "discourse-common/utils/decorators";
export default Controller.extend({
adminSiteSettings: controller(),
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-site-settings.js b/app/assets/javascripts/admin/addon/controllers/admin-site-settings.js
index 02e7ab8f07..58859ae933 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-site-settings.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-site-settings.js
@@ -1,10 +1,10 @@
-import I18n from "I18n";
-import { isEmpty } from "@ember/utils";
-import { alias } from "@ember/object/computed";
import Controller from "@ember/controller";
-import discourseDebounce from "discourse/lib/debounce";
-import { observes } from "discourse-common/utils/decorators";
+import I18n from "I18n";
import { INPUT_DELAY } from "discourse-common/config/environment";
+import { alias } from "@ember/object/computed";
+import discourseDebounce from "discourse-common/lib/debounce";
+import { isEmpty } from "@ember/utils";
+import { observes } from "discourse-common/utils/decorators";
export default Controller.extend({
filter: null,
@@ -112,13 +112,19 @@ export default Controller.extend({
},
@observes("filter", "onlyOverridden", "model")
- filterContent: discourseDebounce(function () {
- if (this._skipBounce) {
- this.set("_skipBounce", false);
- } else {
- this.filterContentNow(this.categoryNameKey);
- }
- }, INPUT_DELAY),
+ filterContent() {
+ discourseDebounce(
+ this,
+ () => {
+ if (this._skipBounce) {
+ this.set("_skipBounce", false);
+ } else {
+ this.filterContentNow(this.categoryNameKey);
+ }
+ },
+ INPUT_DELAY
+ );
+ },
actions: {
clearFilter() {
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-site-text-edit.js b/app/assets/javascripts/admin/addon/controllers/admin-site-text-edit.js
index b33bbe3968..cc7bac3267 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-site-text-edit.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-site-text-edit.js
@@ -1,12 +1,13 @@
-import I18n from "I18n";
-import discourseComputed from "discourse-common/utils/decorators";
import Controller from "@ember/controller";
-import { popupAjaxError } from "discourse/lib/ajax-error";
-import { bufferedProperty } from "discourse/mixins/buffered-content";
+import I18n from "I18n";
import bootbox from "bootbox";
+import { bufferedProperty } from "discourse/mixins/buffered-content";
+import discourseComputed from "discourse-common/utils/decorators";
+import { popupAjaxError } from "discourse/lib/ajax-error";
export default Controller.extend(bufferedProperty("siteText"), {
saved: false,
+ queryParams: ["locale"],
@discourseComputed("buffered.value")
saveDisabled(value) {
@@ -15,9 +16,11 @@ export default Controller.extend(bufferedProperty("siteText"), {
actions: {
saveChanges() {
- const buffered = this.buffered;
+ const attrs = this.buffered.getProperties("value");
+ attrs.locale = this.locale;
+
this.siteText
- .save(buffered.getProperties("value"))
+ .save(attrs)
.then(() => {
this.commitBuffer();
this.set("saved", true);
@@ -27,10 +30,11 @@ export default Controller.extend(bufferedProperty("siteText"), {
revertChanges() {
this.set("saved", false);
+
bootbox.confirm(I18n.t("admin.site_text.revert_confirm"), (result) => {
if (result) {
this.siteText
- .revert()
+ .revert(this.locale)
.then((props) => {
const buffered = this.buffered;
buffered.setProperties(props);
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-site-text-index.js b/app/assets/javascripts/admin/addon/controllers/admin-site-text-index.js
index e46096c751..2f2b708d17 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-site-text-index.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-site-text-index.js
@@ -1,43 +1,88 @@
-import { debounce } from "@ember/runloop";
import Controller from "@ember/controller";
+import discourseComputed from "discourse-common/utils/decorators";
+import discourseDebounce from "discourse-common/lib/debounce";
let lastSearch;
export default Controller.extend({
searching: false,
siteTexts: null,
preferred: false,
- queryParams: ["q", "overridden"],
+ queryParams: ["q", "overridden", "locale"],
+ locale: null,
q: null,
overridden: false,
+ init() {
+ this._super(...arguments);
+
+ this.set("locale", this.siteSettings.default_locale);
+ },
+
_performSearch() {
this.store
- .find("site-text", this.getProperties("q", "overridden"))
+ .find("site-text", this.getProperties("q", "overridden", "locale"))
.then((results) => {
this.set("siteTexts", results);
})
.finally(() => this.set("searching", false));
},
+ @discourseComputed()
+ availableLocales() {
+ return JSON.parse(this.siteSettings.available_locales);
+ },
+
+ @discourseComputed("locale")
+ fallbackLocaleFullName() {
+ if (this.siteTexts.extras.fallback_locale) {
+ return this.availableLocales.find((l) => {
+ return l.value === this.siteTexts.extras.fallback_locale;
+ }).name;
+ }
+ },
+
+ @discourseComputed("locale")
+ showFallbackLocaleWarning() {
+ return (
+ this.siteSettings.allow_user_locale &&
+ this.siteSettings.set_locale_from_accept_language_header &&
+ this.fallbackLocaleFullName
+ );
+ },
+
actions: {
edit(siteText) {
- this.transitionToRoute("adminSiteText.edit", siteText.get("id"));
+ this.transitionToRoute("adminSiteText.edit", siteText.get("id"), {
+ queryParams: {
+ locale: this.locale,
+ localeFullName: this.availableLocales[this.locale],
+ },
+ });
},
toggleOverridden() {
this.toggleProperty("overridden");
this.set("searching", true);
- debounce(this, this._performSearch, 400);
+ discourseDebounce(this, this._performSearch, 400);
},
search() {
const q = this.q;
if (q !== lastSearch) {
this.set("searching", true);
- debounce(this, this._performSearch, 400);
+ discourseDebounce(this, this._performSearch, 400);
lastSearch = q;
}
},
+
+ updateLocale(value) {
+ this.setProperties({
+ searching: true,
+ locale: value,
+ });
+
+ discourseDebounce(this, this._performSearch, 400);
+ },
},
});
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-user-badges.js b/app/assets/javascripts/admin/addon/controllers/admin-user-badges.js
index 6951a7b562..2c5212e4ba 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-user-badges.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-user-badges.js
@@ -1,11 +1,11 @@
-import I18n from "I18n";
-import discourseComputed from "discourse-common/utils/decorators";
-import { alias, sort } from "@ember/object/computed";
-import { next } from "@ember/runloop";
import Controller, { inject as controller } from "@ember/controller";
+import { alias, sort } from "@ember/object/computed";
import GrantBadgeController from "discourse/mixins/grant-badge-controller";
-import { popupAjaxError } from "discourse/lib/ajax-error";
+import I18n from "I18n";
import bootbox from "bootbox";
+import discourseComputed from "discourse-common/utils/decorators";
+import { next } from "@ember/runloop";
+import { popupAjaxError } from "discourse/lib/ajax-error";
export default Controller.extend(GrantBadgeController, {
adminUser: controller(),
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-user-fields.js b/app/assets/javascripts/admin/addon/controllers/admin-user-fields.js
index 913ed729a7..9b37e931da 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-user-fields.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-user-fields.js
@@ -1,8 +1,8 @@
-import I18n from "I18n";
import { gte, sort } from "@ember/object/computed";
import Controller from "@ember/controller";
-import { popupAjaxError } from "discourse/lib/ajax-error";
+import I18n from "I18n";
import bootbox from "bootbox";
+import { popupAjaxError } from "discourse/lib/ajax-error";
const MAX_FIELDS = 30;
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-user-index.js b/app/assets/javascripts/admin/addon/controllers/admin-user-index.js
index 2bed595b3f..81a42481e2 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-user-index.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-user-index.js
@@ -1,16 +1,19 @@
-import I18n from "I18n";
-import { notEmpty, and } from "@ember/object/computed";
-import { inject as service } from "@ember/service";
-import Controller from "@ember/controller";
-import { ajax } from "discourse/lib/ajax";
+import DiscourseURL, { userPath } from "discourse/lib/url";
+import { and, notEmpty } from "@ember/object/computed";
+import { fmt, propertyNotEqual, setting } from "discourse/lib/computed";
+import AdminUser from "admin/models/admin-user";
import CanCheckEmails from "discourse/mixins/can-check-emails";
-import { propertyNotEqual, setting, fmt } from "discourse/lib/computed";
-import { userPath } from "discourse/lib/url";
-import { popupAjaxError } from "discourse/lib/ajax-error";
-import discourseComputed from "discourse-common/utils/decorators";
-import { htmlSafe } from "@ember/template";
-import showModal from "discourse/lib/show-modal";
+import Controller from "@ember/controller";
+import I18n from "I18n";
+import { ajax } from "discourse/lib/ajax";
import bootbox from "bootbox";
+import discourseComputed from "discourse-common/utils/decorators";
+import getURL from "discourse-common/lib/get-url";
+import { htmlSafe } from "@ember/template";
+import { iconHTML } from "discourse-common/lib/icon-library";
+import { popupAjaxError } from "discourse/lib/ajax-error";
+import { inject as service } from "@ember/service";
+import showModal from "discourse/lib/show-modal";
export default Controller.extend(CanCheckEmails, {
adminTools: service(),
@@ -141,10 +144,21 @@ export default Controller.extend(CanCheckEmails, {
actions: {
impersonate() {
- return this.model.impersonate();
+ return this.model
+ .impersonate()
+ .then(() => DiscourseURL.redirectTo("/"))
+ .catch((e) => {
+ if (e.status === 404) {
+ bootbox.alert(I18n.t("admin.impersonate.not_found"));
+ } else {
+ bootbox.alert(I18n.t("admin.impersonate.invalid"));
+ }
+ });
},
logOut() {
- return this.model.logOut();
+ return this.model
+ .logOut()
+ .then(() => bootbox.alert(I18n.t("admin.user.logged_out")));
},
resetBounceScore() {
return this.model.resetBounceScore();
@@ -152,20 +166,56 @@ export default Controller.extend(CanCheckEmails, {
approve() {
return this.model.approve(this.currentUser);
},
+
+ _formatError(event) {
+ return `http: ${event.status} - ${event.body}`;
+ },
+
deactivate() {
- return this.model.deactivate();
+ return this.model
+ .deactivate()
+ .then(() =>
+ this.model.setProperties({ active: false, can_activate: true })
+ )
+ .catch((e) => {
+ const error = I18n.t("admin.user.deactivate_failed", {
+ error: this._formatError(e),
+ });
+ bootbox.alert(error);
+ });
},
sendActivationEmail() {
- return this.model.sendActivationEmail();
+ return this.model
+ .sendActivationEmail()
+ .then(() => bootbox.alert(I18n.t("admin.user.activation_email_sent")))
+ .catch(popupAjaxError);
},
activate() {
- return this.model.activate();
+ return this.model
+ .activate()
+ .then(() =>
+ this.model.setProperties({
+ active: true,
+ can_deactivate: !this.model.staff,
+ })
+ )
+ .catch((e) => {
+ const error = I18n.t("admin.user.activate_failed", {
+ error: this._formatError(e),
+ });
+ bootbox.alert(error);
+ });
},
revokeAdmin() {
return this.model.revokeAdmin();
},
grantAdmin() {
- return this.model.grantAdmin();
+ return this.model
+ .grantAdmin()
+ .then(() => {
+ bootbox.alert(I18n.t("admin.user.grant_admin_confirm"));
+ })
+ .catch(popupAjaxError);
},
revokeModeration() {
return this.model.revokeModeration();
@@ -174,13 +224,41 @@ export default Controller.extend(CanCheckEmails, {
return this.model.grantModeration();
},
saveTrustLevel() {
- return this.model.saveTrustLevel();
+ return this.model
+ .saveTrustLevel()
+ .then(() => window.location.reload())
+ .catch((e) => {
+ let error;
+ if (e.jqXHR.responseJSON && e.jqXHR.responseJSON.errors) {
+ error = e.jqXHR.responseJSON.errors[0];
+ }
+ error =
+ error ||
+ I18n.t("admin.user.trust_level_change_failed", {
+ error: this._formatError(e),
+ });
+ bootbox.alert(error);
+ });
},
restoreTrustLevel() {
return this.model.restoreTrustLevel();
},
lockTrustLevel(locked) {
- return this.model.lockTrustLevel(locked);
+ return this.model
+ .lockTrustLevel(locked)
+ .then(() => window.location.reload())
+ .catch((e) => {
+ let error;
+ if (e.jqXHR.responseJSON && e.jqXHR.responseJSON.errors) {
+ error = e.jqXHR.responseJSON.errors[0];
+ }
+ error =
+ error ||
+ I18n.t("admin.user.trust_level_change_failed", {
+ error: this._formatError(e),
+ });
+ bootbox.alert(error);
+ });
},
unsilence() {
return this.model.unsilence();
@@ -189,11 +267,119 @@ export default Controller.extend(CanCheckEmails, {
return this.model.silence();
},
deleteAllPosts() {
- return this.model.deleteAllPosts();
+ let deletedPosts = 0;
+ let deletedPercentage = 0;
+ const user = this.model;
+ const message = I18n.messageFormat(
+ "admin.user.delete_all_posts_confirm_MF",
+ {
+ POSTS: user.get("post_count"),
+ TOPICS: user.get("topic_count"),
+ }
+ );
+
+ const performDelete = (progressModal) => {
+ this.model
+ .deleteAllPosts()
+ .then(({ posts_deleted }) => {
+ if (posts_deleted === 0) {
+ user.set("post_count", 0);
+ progressModal.send("closeModal");
+ } else {
+ deletedPosts += posts_deleted;
+ deletedPercentage = Math.floor(
+ (deletedPosts * 100) / user.get("post_count")
+ );
+ progressModal.setProperties({
+ deletedPercentage: deletedPercentage,
+ });
+ performDelete(progressModal);
+ }
+ })
+ .catch((e) => {
+ progressModal.send("closeModal");
+ let error;
+ AdminUser.find(user.get("id")).then((u) => user.setProperties(u));
+ if (e.jqXHR.responseJSON && e.jqXHR.responseJSON.errors) {
+ error = e.jqXHR.responseJSON.errors[0];
+ }
+ error = error || I18n.t("admin.user.delete_posts_failed");
+ bootbox.alert(error);
+ });
+ };
+
+ const buttons = [
+ {
+ label: I18n.t("composer.cancel"),
+ class: "d-modal-cancel",
+ link: true,
+ },
+ {
+ label:
+ `${iconHTML("exclamation-triangle")} ` +
+ I18n.t("admin.user.delete_all_posts"),
+ class: "btn btn-danger",
+ callback: () => {
+ const progressModal = openProgressModal();
+ performDelete(progressModal);
+ },
+ },
+ ];
+
+ const openProgressModal = () => {
+ return showModal("admin-delete-user-posts-progress", {
+ admin: true,
+ });
+ };
+
+ bootbox.dialog(message, buttons, { classes: "delete-all-posts" });
},
+
anonymize() {
- return this.model.anonymize();
+ const user = this.model;
+ const message = I18n.t("admin.user.anonymize_confirm");
+
+ const performAnonymize = () => {
+ this.model
+ .anonymize()
+ .then((data) => {
+ if (data.success) {
+ if (data.username) {
+ document.location = getURL(
+ `/admin/users/${user.get("id")}/${data.username}`
+ );
+ } else {
+ document.location = getURL("/admin/users/list/active");
+ }
+ } else {
+ bootbox.alert(I18n.t("admin.user.anonymize_failed"));
+ if (data.user) {
+ user.setProperties(data.user);
+ }
+ }
+ })
+ .catch(() => bootbox.alert(I18n.t("admin.user.anonymize_failed")));
+ };
+ const buttons = [
+ {
+ label: I18n.t("composer.cancel"),
+ class: "cancel",
+ link: true,
+ },
+ {
+ label:
+ `${iconHTML("exclamation-triangle")} ` +
+ I18n.t("admin.user.anonymize_yes"),
+ class: "btn btn-danger",
+ callback: () => {
+ performAnonymize();
+ },
+ },
+ ];
+
+ bootbox.dialog(message, buttons, { classes: "delete-user-modal" });
},
+
disableSecondFactor() {
return this.model.disableSecondFactor();
},
@@ -210,11 +396,68 @@ export default Controller.extend(CanCheckEmails, {
destroy() {
const postCount = this.get("model.post_count");
const maxPostCount = this.siteSettings.delete_all_posts_max;
- if (postCount <= maxPostCount) {
- return this.model.destroy({ deletePosts: true });
- } else {
- return this.model.destroy();
- }
+ const user = this.model;
+ const message = I18n.t("admin.user.delete_confirm");
+ const location = document.location.pathname;
+
+ const performDestroy = (block) => {
+ bootbox.dialog(I18n.t("admin.user.deleting_user"));
+ let formData = { context: location };
+ if (block) {
+ formData["block_email"] = true;
+ formData["block_urls"] = true;
+ formData["block_ip"] = true;
+ }
+ if (postCount <= maxPostCount) {
+ formData["delete_posts"] = true;
+ }
+ this.model
+ .destroy(formData)
+ .then((data) => {
+ if (data.deleted) {
+ if (/^\/admin\/users\/list\//.test(location)) {
+ document.location = location;
+ } else {
+ document.location = getURL("/admin/users/list/active");
+ }
+ } else {
+ bootbox.alert(I18n.t("admin.user.delete_failed"));
+ if (data.user) {
+ user.setProperties(data.user);
+ }
+ }
+ })
+ .catch(() => {
+ AdminUser.find(user.get("id")).then((u) => user.setProperties(u));
+ bootbox.alert(I18n.t("admin.user.delete_failed"));
+ });
+ };
+
+ const buttons = [
+ {
+ label: I18n.t("composer.cancel"),
+ class: "btn",
+ link: true,
+ },
+ {
+ label:
+ `${iconHTML("exclamation-triangle")} ` +
+ I18n.t("admin.user.delete_and_block"),
+ class: "btn btn-danger",
+ callback: () => {
+ performDestroy(true);
+ },
+ },
+ {
+ label: I18n.t("admin.user.delete_dont_block"),
+ class: "btn btn-primary",
+ callback: () => {
+ performDestroy(false);
+ },
+ },
+ ];
+
+ bootbox.dialog(message, buttons, { classes: "delete-user-modal" });
},
promptTargetUser() {
@@ -235,7 +478,31 @@ export default Controller.extend(CanCheckEmails, {
},
merge(targetUsername) {
- return this.model.merge({ targetUsername });
+ const user = this.model;
+ const location = document.location.pathname;
+
+ let formData = { context: location };
+
+ if (targetUsername) {
+ formData["target_username"] = targetUsername;
+ }
+
+ this.model
+ .merge(formData)
+ .then((response) => {
+ if (response.success) {
+ showModal("admin-merge-users-progress", {
+ admin: true,
+ model: this.model,
+ });
+ } else {
+ bootbox.alert(I18n.t("admin.user.merge_failed"));
+ }
+ })
+ .catch(() => {
+ AdminUser.find(user.id).then((u) => user.setProperties(u));
+ bootbox.alert(I18n.t("admin.user.merge_failed"));
+ });
},
viewActionLogs() {
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-users-list-show.js b/app/assets/javascripts/admin/addon/controllers/admin-users-list-show.js
index fd20b6c308..b0b25706e5 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-users-list-show.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-users-list-show.js
@@ -1,11 +1,11 @@
-import I18n from "I18n";
import discourseComputed, { observes } from "discourse-common/utils/decorators";
-import Controller from "@ember/controller";
-import discourseDebounce from "discourse/lib/debounce";
-import { i18n } from "discourse/lib/computed";
import AdminUser from "admin/models/admin-user";
import CanCheckEmails from "discourse/mixins/can-check-emails";
+import Controller from "@ember/controller";
+import I18n from "I18n";
import { INPUT_DELAY } from "discourse-common/config/environment";
+import discourseDebounce from "discourse-common/lib/debounce";
+import { i18n } from "discourse/lib/computed";
export default Controller.extend(CanCheckEmails, {
model: null,
@@ -32,9 +32,9 @@ export default Controller.extend(CanCheckEmails, {
},
@observes("listFilter")
- _filterUsers: discourseDebounce(function () {
- this.resetFilters();
- }, INPUT_DELAY),
+ _filterUsers() {
+ discourseDebounce(this, this.resetFilters, INPUT_DELAY);
+ },
resetFilters() {
this._page = 1;
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-watched-words-action.js b/app/assets/javascripts/admin/addon/controllers/admin-watched-words-action.js
index 6a9b78bf29..1daa8a6ec3 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-watched-words-action.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-watched-words-action.js
@@ -1,13 +1,13 @@
-import I18n from "I18n";
-import discourseComputed from "discourse-common/utils/decorators";
-import { or } from "@ember/object/computed";
-import { schedule } from "@ember/runloop";
import Controller, { inject as controller } from "@ember/controller";
+import I18n from "I18n";
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";
import bootbox from "bootbox";
+import discourseComputed from "discourse-common/utils/decorators";
+import { fmt } from "discourse/lib/computed";
+import { or } from "@ember/object/computed";
+import { schedule } from "@ember/runloop";
+import showModal from "discourse/lib/show-modal";
export default Controller.extend({
adminWatchedWords: controller(),
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-watched-words.js b/app/assets/javascripts/admin/addon/controllers/admin-watched-words.js
index 151fc82c33..cfd86c6c22 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-watched-words.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-watched-words.js
@@ -1,10 +1,10 @@
-import { isEmpty } from "@ember/utils";
-import { alias } from "@ember/object/computed";
-import EmberObject from "@ember/object";
import Controller from "@ember/controller";
-import discourseDebounce from "discourse/lib/debounce";
-import { observes } from "discourse-common/utils/decorators";
+import EmberObject from "@ember/object";
import { INPUT_DELAY } from "discourse-common/config/environment";
+import { alias } from "@ember/object/computed";
+import discourseDebounce from "discourse-common/lib/debounce";
+import { isEmpty } from "@ember/utils";
+import { observes } from "discourse-common/utils/decorators";
export default Controller.extend({
filter: null,
@@ -48,10 +48,16 @@ export default Controller.extend({
},
@observes("filter")
- filterContent: discourseDebounce(function () {
- this.filterContentNow();
- this.set("filtered", !isEmpty(this.filter));
- }, INPUT_DELAY),
+ filterContent() {
+ discourseDebounce(
+ this,
+ function () {
+ this.filterContentNow();
+ this.set("filtered", !isEmpty(this.filter));
+ },
+ INPUT_DELAY
+ );
+ },
actions: {
clearFilter() {
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-web-hooks-show-events.js b/app/assets/javascripts/admin/addon/controllers/admin-web-hooks-show-events.js
index 49c87926d2..cdb4c9b615 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-web-hooks-show-events.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-web-hooks-show-events.js
@@ -1,7 +1,7 @@
-import discourseComputed from "discourse-common/utils/decorators";
-import { alias } from "@ember/object/computed";
import Controller from "@ember/controller";
import { ajax } from "discourse/lib/ajax";
+import { alias } from "@ember/object/computed";
+import discourseComputed from "discourse-common/utils/decorators";
import { popupAjaxError } from "discourse/lib/ajax-error";
export default Controller.extend({
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-web-hooks-show.js b/app/assets/javascripts/admin/addon/controllers/admin-web-hooks-show.js
index f2e9f2178d..26b5fb20d0 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-web-hooks-show.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-web-hooks-show.js
@@ -1,13 +1,13 @@
-import I18n from "I18n";
-import discourseComputed from "discourse-common/utils/decorators";
-import { isEmpty } from "@ember/utils";
-import { alias } from "@ember/object/computed";
import Controller, { inject as controller } from "@ember/controller";
-import { popupAjaxError } from "discourse/lib/ajax-error";
-import { extractDomainFromUrl } from "discourse/lib/utilities";
import EmberObject from "@ember/object";
-import { isAbsoluteURL } from "discourse-common/lib/get-url";
+import I18n from "I18n";
+import { alias } from "@ember/object/computed";
import bootbox from "bootbox";
+import discourseComputed from "discourse-common/utils/decorators";
+import { extractDomainFromUrl } from "discourse/lib/utilities";
+import { isAbsoluteURL } from "discourse-common/lib/get-url";
+import { isEmpty } from "@ember/utils";
+import { popupAjaxError } from "discourse/lib/ajax-error";
export default Controller.extend({
adminWebHooks: controller(),
diff --git a/app/assets/javascripts/admin/addon/controllers/admin-web-hooks.js b/app/assets/javascripts/admin/addon/controllers/admin-web-hooks.js
index cc13ea9e9d..6e1acf97dc 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-web-hooks.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-web-hooks.js
@@ -1,7 +1,7 @@
-import I18n from "I18n";
import Controller from "@ember/controller";
-import { popupAjaxError } from "discourse/lib/ajax-error";
+import I18n from "I18n";
import bootbox from "bootbox";
+import { popupAjaxError } from "discourse/lib/ajax-error";
export default Controller.extend({
actions: {
diff --git a/app/assets/javascripts/admin/addon/controllers/admin.js b/app/assets/javascripts/admin/addon/controllers/admin.js
index 4c51eb38b7..03838b789c 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin.js
@@ -1,7 +1,7 @@
-import discourseComputed from "discourse-common/utils/decorators";
-import { inject as service } from "@ember/service";
import Controller from "@ember/controller";
import { dasherize } from "@ember/string";
+import discourseComputed from "discourse-common/utils/decorators";
+import { inject as service } from "@ember/service";
export default Controller.extend({
router: service(),
diff --git a/app/assets/javascripts/admin/addon/controllers/modals/admin-add-upload.js b/app/assets/javascripts/admin/addon/controllers/modals/admin-add-upload.js
index 12b2be4f4a..876ac3ae9a 100644
--- a/app/assets/javascripts/admin/addon/controllers/modals/admin-add-upload.js
+++ b/app/assets/javascripts/admin/addon/controllers/modals/admin-add-upload.js
@@ -1,10 +1,10 @@
-import I18n from "I18n";
-import { isEmpty } from "@ember/utils";
-import { and, not } from "@ember/object/computed";
import Controller, { inject as controller } from "@ember/controller";
+import { and, not } from "@ember/object/computed";
+import discourseComputed, { observes } from "discourse-common/utils/decorators";
+import I18n from "I18n";
import ModalFunctionality from "discourse/mixins/modal-functionality";
import { ajax } from "discourse/lib/ajax";
-import discourseComputed, { observes } from "discourse-common/utils/decorators";
+import { isEmpty } from "@ember/utils";
import { popupAjaxError } from "discourse/lib/ajax-error";
const THEME_FIELD_VARIABLE_TYPE_IDS = [2, 3, 4];
diff --git a/app/assets/javascripts/admin/addon/controllers/modals/admin-badge-preview.js b/app/assets/javascripts/admin/addon/controllers/modals/admin-badge-preview.js
index 90af87cb73..322436303f 100644
--- a/app/assets/javascripts/admin/addon/controllers/modals/admin-badge-preview.js
+++ b/app/assets/javascripts/admin/addon/controllers/modals/admin-badge-preview.js
@@ -1,6 +1,6 @@
-import I18n from "I18n";
import { alias, map } from "@ember/object/computed";
import Controller from "@ember/controller";
+import I18n from "I18n";
import discourseComputed from "discourse-common/utils/decorators";
import { escapeExpression } from "discourse/lib/utilities";
diff --git a/app/assets/javascripts/admin/addon/controllers/modals/admin-delete-user-posts-progress.js b/app/assets/javascripts/admin/addon/controllers/modals/admin-delete-user-posts-progress.js
new file mode 100644
index 0000000000..61b9bae999
--- /dev/null
+++ b/app/assets/javascripts/admin/addon/controllers/modals/admin-delete-user-posts-progress.js
@@ -0,0 +1,6 @@
+import Controller from "@ember/controller";
+import ModalFunctionality from "discourse/mixins/modal-functionality";
+
+export default Controller.extend(ModalFunctionality, {
+ deletedPercentage: 0,
+});
diff --git a/app/assets/javascripts/admin/addon/controllers/modals/admin-edit-badge-groupings.js b/app/assets/javascripts/admin/addon/controllers/modals/admin-edit-badge-groupings.js
index cedbf43632..aa7d5665fa 100644
--- a/app/assets/javascripts/admin/addon/controllers/modals/admin-edit-badge-groupings.js
+++ b/app/assets/javascripts/admin/addon/controllers/modals/admin-edit-badge-groupings.js
@@ -1,10 +1,10 @@
-import I18n from "I18n";
-import Controller from "@ember/controller";
import { A } from "@ember/array";
-import { ajax } from "discourse/lib/ajax";
+import Controller from "@ember/controller";
+import I18n from "I18n";
import ModalFunctionality from "discourse/mixins/modal-functionality";
-import { observes } from "discourse-common/utils/decorators";
+import { ajax } from "discourse/lib/ajax";
import bootbox from "bootbox";
+import { observes } from "discourse-common/utils/decorators";
export default Controller.extend(ModalFunctionality, {
@observes("model")
diff --git a/app/assets/javascripts/admin/addon/controllers/modals/admin-incoming-email.js b/app/assets/javascripts/admin/addon/controllers/modals/admin-incoming-email.js
index 45df8e4628..6055baa1fe 100644
--- a/app/assets/javascripts/admin/addon/controllers/modals/admin-incoming-email.js
+++ b/app/assets/javascripts/admin/addon/controllers/modals/admin-incoming-email.js
@@ -1,7 +1,7 @@
-import discourseComputed from "discourse-common/utils/decorators";
import Controller from "@ember/controller";
-import ModalFunctionality from "discourse/mixins/modal-functionality";
import IncomingEmail from "admin/models/incoming-email";
+import ModalFunctionality from "discourse/mixins/modal-functionality";
+import discourseComputed from "discourse-common/utils/decorators";
import { longDate } from "discourse/lib/formatter";
import { popupAjaxError } from "discourse/lib/ajax-error";
diff --git a/app/assets/javascripts/admin/addon/controllers/modals/admin-install-theme.js b/app/assets/javascripts/admin/addon/controllers/modals/admin-install-theme.js
index 4bdb6ca85c..01cc315423 100644
--- a/app/assets/javascripts/admin/addon/controllers/modals/admin-install-theme.js
+++ b/app/assets/javascripts/admin/addon/controllers/modals/admin-install-theme.js
@@ -1,12 +1,12 @@
-import I18n from "I18n";
-import { equal, match, alias } from "@ember/object/computed";
+import { COMPONENTS, THEMES } from "admin/models/theme";
import Controller, { inject as controller } from "@ember/controller";
+import { alias, equal, match } from "@ember/object/computed";
+import discourseComputed, { observes } from "discourse-common/utils/decorators";
+import I18n from "I18n";
import ModalFunctionality from "discourse/mixins/modal-functionality";
+import { POPULAR_THEMES } from "discourse-common/helpers/popular-themes";
import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
-import discourseComputed, { observes } from "discourse-common/utils/decorators";
-import { THEMES, COMPONENTS } from "admin/models/theme";
-import { POPULAR_THEMES } from "discourse-common/helpers/popular-themes";
import { set } from "@ember/object";
const MIN_NAME_LENGTH = 4;
@@ -26,7 +26,6 @@ export default Controller.extend(ModalFunctionality, {
checkPrivate: match("uploadUrl", /^git/),
localFile: null,
uploadUrl: null,
- urlPlaceholder: "https://github.com/discourse/sample_theme",
advancedVisible: false,
selectedType: alias("themesController.currentTab"),
component: equal("selectedType", COMPONENTS),
@@ -76,12 +75,15 @@ export default Controller.extend(ModalFunctionality, {
);
},
+ @discourseComputed("privateChecked")
+ urlPlaceholder(privateChecked) {
+ return privateChecked
+ ? "git@github.com:discourse/sample_theme.git"
+ : "https://github.com/discourse/sample_theme";
+ },
+
@observes("privateChecked")
privateWasChecked() {
- this.privateChecked
- ? this.set("urlPlaceholder", "git@github.com:discourse/sample_theme.git")
- : this.set("urlPlaceholder", "https://github.com/discourse/sample_theme");
-
const checked = this.privateChecked;
if (checked && !this._keyLoading) {
this._keyLoading = true;
@@ -125,6 +127,27 @@ export default Controller.extend(ModalFunctionality, {
return privateChecked && checkPrivate && publicKey;
},
+ onClose() {
+ this.setProperties({
+ duplicateRemoteThemeWarning: null,
+ privateChecked: false,
+ privateKey: null,
+ localFile: null,
+ uploadUrl: null,
+ publicKey: null,
+ branch: null,
+ });
+ },
+
+ themeHasSameUrl(theme, url) {
+ const themeUrl = theme.remote_theme && theme.remote_theme.remote_url;
+ return (
+ themeUrl &&
+ url &&
+ url.replace(/\.git$/, "") === themeUrl.replace(/\.git$/, "")
+ );
+ },
+
actions: {
uploadLocaleFile() {
this.set("localFile", $("#file-input")[0].files[0]);
@@ -167,6 +190,17 @@ export default Controller.extend(ModalFunctionality, {
}
if (this.remote || this.popular) {
+ const duplicate = this.themesController.model.content.find((theme) =>
+ this.themeHasSameUrl(theme, this.uploadUrl)
+ );
+ if (duplicate && !this.duplicateRemoteThemeWarning) {
+ const warning = I18n.t(
+ "admin.customize.theme.duplicate_remote_theme",
+ { name: duplicate.name }
+ );
+ this.set("duplicateRemoteThemeWarning", warning);
+ return;
+ }
options.data = {
remote: this.uploadUrl,
branch: this.branch,
diff --git a/app/assets/javascripts/admin/addon/controllers/modals/admin-merge-users-confirmation.js b/app/assets/javascripts/admin/addon/controllers/modals/admin-merge-users-confirmation.js
index f2233c07a3..48be2946bc 100644
--- a/app/assets/javascripts/admin/addon/controllers/modals/admin-merge-users-confirmation.js
+++ b/app/assets/javascripts/admin/addon/controllers/modals/admin-merge-users-confirmation.js
@@ -1,9 +1,9 @@
-import I18n from "I18n";
import Controller, { inject as controller } from "@ember/controller";
+import I18n from "I18n";
import ModalFunctionality from "discourse/mixins/modal-functionality";
-import discourseComputed from "discourse-common/utils/decorators";
-import { alias } from "@ember/object/computed";
import { action } from "@ember/object";
+import { alias } from "@ember/object/computed";
+import discourseComputed from "discourse-common/utils/decorators";
export default Controller.extend(ModalFunctionality, {
adminUserIndex: controller(),
diff --git a/app/assets/javascripts/admin/addon/controllers/modals/admin-merge-users-progress.js b/app/assets/javascripts/admin/addon/controllers/modals/admin-merge-users-progress.js
new file mode 100644
index 0000000000..3d9248d36d
--- /dev/null
+++ b/app/assets/javascripts/admin/addon/controllers/modals/admin-merge-users-progress.js
@@ -0,0 +1,31 @@
+import Controller from "@ember/controller";
+import DiscourseURL from "discourse/lib/url";
+import I18n from "I18n";
+import ModalFunctionality from "discourse/mixins/modal-functionality";
+import messageBus from "message-bus-client";
+
+export default Controller.extend(ModalFunctionality, {
+ message: I18n.t("admin.user.merging_user"),
+
+ onShow() {
+ messageBus.subscribe("/merge_user", (data) => {
+ if (data.merged) {
+ if (/^\/admin\/users\/list\//.test(location)) {
+ DiscourseURL.redirectTo(location);
+ } else {
+ DiscourseURL.redirectTo(
+ `/admin/users/${data.user.id}/${data.user.username}`
+ );
+ }
+ } else if (data.message) {
+ this.set("message", data.message);
+ } else if (data.failed) {
+ this.set("message", I18n.t("admin.user.merge_failed"));
+ }
+ });
+ },
+
+ onClose() {
+ this.messageBus.unsubscribe("/merge_user");
+ },
+});
diff --git a/app/assets/javascripts/admin/addon/controllers/modals/admin-merge-users-prompt.js b/app/assets/javascripts/admin/addon/controllers/modals/admin-merge-users-prompt.js
index baaf7cef7a..2a088dff31 100644
--- a/app/assets/javascripts/admin/addon/controllers/modals/admin-merge-users-prompt.js
+++ b/app/assets/javascripts/admin/addon/controllers/modals/admin-merge-users-prompt.js
@@ -1,8 +1,8 @@
import Controller, { inject as controller } from "@ember/controller";
import ModalFunctionality from "discourse/mixins/modal-functionality";
-import discourseComputed from "discourse-common/utils/decorators";
-import { alias } from "@ember/object/computed";
import { action } from "@ember/object";
+import { alias } from "@ember/object/computed";
+import discourseComputed from "discourse-common/utils/decorators";
export default Controller.extend(ModalFunctionality, {
adminUserIndex: controller(),
diff --git a/app/assets/javascripts/admin/addon/controllers/modals/admin-reseed.js b/app/assets/javascripts/admin/addon/controllers/modals/admin-reseed.js
index b29a800aa0..672f6d8db3 100644
--- a/app/assets/javascripts/admin/addon/controllers/modals/admin-reseed.js
+++ b/app/assets/javascripts/admin/addon/controllers/modals/admin-reseed.js
@@ -1,5 +1,5 @@
-import I18n from "I18n";
import Controller from "@ember/controller";
+import I18n from "I18n";
import ModalFunctionality from "discourse/mixins/modal-functionality";
import { ajax } from "discourse/lib/ajax";
import bootbox from "bootbox";
diff --git a/app/assets/javascripts/admin/addon/controllers/modals/admin-silence-user.js b/app/assets/javascripts/admin/addon/controllers/modals/admin-silence-user.js
index e379b903c2..b76565f815 100644
--- a/app/assets/javascripts/admin/addon/controllers/modals/admin-silence-user.js
+++ b/app/assets/javascripts/admin/addon/controllers/modals/admin-silence-user.js
@@ -1,7 +1,7 @@
-import discourseComputed from "discourse-common/utils/decorators";
-import { isEmpty } from "@ember/utils";
import Controller from "@ember/controller";
import PenaltyController from "admin/mixins/penalty-controller";
+import discourseComputed from "discourse-common/utils/decorators";
+import { isEmpty } from "@ember/utils";
export default Controller.extend(PenaltyController, {
silenceUntil: null,
diff --git a/app/assets/javascripts/admin/addon/controllers/modals/admin-suspend-user.js b/app/assets/javascripts/admin/addon/controllers/modals/admin-suspend-user.js
index 4997f62947..2712b57cf2 100644
--- a/app/assets/javascripts/admin/addon/controllers/modals/admin-suspend-user.js
+++ b/app/assets/javascripts/admin/addon/controllers/modals/admin-suspend-user.js
@@ -1,7 +1,7 @@
-import discourseComputed from "discourse-common/utils/decorators";
-import { isEmpty } from "@ember/utils";
import Controller from "@ember/controller";
import PenaltyController from "admin/mixins/penalty-controller";
+import discourseComputed from "discourse-common/utils/decorators";
+import { isEmpty } from "@ember/utils";
export default Controller.extend(PenaltyController, {
suspendUntil: null,
diff --git a/app/assets/javascripts/admin/addon/controllers/modals/admin-uploaded-image-list.js b/app/assets/javascripts/admin/addon/controllers/modals/admin-uploaded-image-list.js
index 0aeffaad59..7ab4cb6984 100644
--- a/app/assets/javascripts/admin/addon/controllers/modals/admin-uploaded-image-list.js
+++ b/app/assets/javascripts/admin/addon/controllers/modals/admin-uploaded-image-list.js
@@ -1,5 +1,5 @@
+import { observes, on } from "discourse-common/utils/decorators";
import Controller from "@ember/controller";
-import { on, observes } from "discourse-common/utils/decorators";
import ModalFunctionality from "discourse/mixins/modal-functionality";
export default Controller.extend(ModalFunctionality, {
diff --git a/app/assets/javascripts/admin/addon/controllers/modals/admin-watched-word-test.js b/app/assets/javascripts/admin/addon/controllers/modals/admin-watched-word-test.js
index b088cccb75..215cc08a6d 100644
--- a/app/assets/javascripts/admin/addon/controllers/modals/admin-watched-word-test.js
+++ b/app/assets/javascripts/admin/addon/controllers/modals/admin-watched-word-test.js
@@ -1,6 +1,6 @@
import Controller from "@ember/controller";
-import discourseComputed from "discourse-common/utils/decorators";
import ModalFunctionality from "discourse/mixins/modal-functionality";
+import discourseComputed from "discourse-common/utils/decorators";
export default Controller.extend(ModalFunctionality, {
@discourseComputed("value", "model.compiledRegularExpression")
diff --git a/app/assets/javascripts/admin/addon/helpers/check-icon.js b/app/assets/javascripts/admin/addon/helpers/check-icon.js
index 51fb238550..14ae3e649c 100644
--- a/app/assets/javascripts/admin/addon/helpers/check-icon.js
+++ b/app/assets/javascripts/admin/addon/helpers/check-icon.js
@@ -1,6 +1,6 @@
+import { htmlSafe } from "@ember/template";
import { registerUnbound } from "discourse-common/lib/helpers";
import { renderIcon } from "discourse-common/lib/icon-library";
-import { htmlSafe } from "@ember/template";
registerUnbound("check-icon", function (value) {
let icon = value ? "check" : "times";
diff --git a/app/assets/javascripts/admin/addon/helpers/disposition-icon.js b/app/assets/javascripts/admin/addon/helpers/disposition-icon.js
index 03960ff289..5dbd069cf3 100644
--- a/app/assets/javascripts/admin/addon/helpers/disposition-icon.js
+++ b/app/assets/javascripts/admin/addon/helpers/disposition-icon.js
@@ -1,5 +1,5 @@
-import { iconHTML } from "discourse-common/lib/icon-library";
import Helper from "@ember/component/helper";
+import { iconHTML } from "discourse-common/lib/icon-library";
export default Helper.extend({
compute([disposition]) {
diff --git a/app/assets/javascripts/admin/addon/helpers/post-action-title.js b/app/assets/javascripts/admin/addon/helpers/post-action-title.js
index 2d8e3c3fe8..9a1d213d93 100644
--- a/app/assets/javascripts/admin/addon/helpers/post-action-title.js
+++ b/app/assets/javascripts/admin/addon/helpers/post-action-title.js
@@ -1,5 +1,5 @@
-import I18n from "I18n";
import Helper from "@ember/component/helper";
+import I18n from "I18n";
function postActionTitle([id, nameKey]) {
let title = I18n.t(`admin.flags.short_names.${nameKey}`, {
diff --git a/app/assets/javascripts/admin/addon/helpers/preserve-newlines.js b/app/assets/javascripts/admin/addon/helpers/preserve-newlines.js
index 16639f30cc..3d7f2e019e 100644
--- a/app/assets/javascripts/admin/addon/helpers/preserve-newlines.js
+++ b/app/assets/javascripts/admin/addon/helpers/preserve-newlines.js
@@ -1,5 +1,5 @@
-import { htmlHelper } from "discourse-common/lib/helpers";
import { escapeExpression } from "discourse/lib/utilities";
+import { htmlHelper } from "discourse-common/lib/helpers";
export default htmlHelper((str) =>
escapeExpression(str).replace(/\n/g, "
")
diff --git a/app/assets/javascripts/admin/addon/mixins/penalty-controller.js b/app/assets/javascripts/admin/addon/mixins/penalty-controller.js
index 250d60664f..55514dfe48 100644
--- a/app/assets/javascripts/admin/addon/mixins/penalty-controller.js
+++ b/app/assets/javascripts/admin/addon/mixins/penalty-controller.js
@@ -1,10 +1,10 @@
import I18n from "I18n";
-import ModalFunctionality from "discourse/mixins/modal-functionality";
-import { extractError } from "discourse/lib/ajax-error";
import Mixin from "@ember/object/mixin";
-import { next } from "@ember/runloop";
+import ModalFunctionality from "discourse/mixins/modal-functionality";
import { Promise } from "rsvp";
import bootbox from "bootbox";
+import { extractError } from "discourse/lib/ajax-error";
+import { next } from "@ember/runloop";
export default Mixin.create(ModalFunctionality, {
errorMessage: null,
diff --git a/app/assets/javascripts/admin/addon/mixins/period-computation.js b/app/assets/javascripts/admin/addon/mixins/period-computation.js
index 7b8afe796a..b46503e73c 100644
--- a/app/assets/javascripts/admin/addon/mixins/period-computation.js
+++ b/app/assets/javascripts/admin/addon/mixins/period-computation.js
@@ -1,6 +1,6 @@
-import discourseComputed from "discourse-common/utils/decorators";
import DiscourseURL from "discourse/lib/url";
import Mixin from "@ember/object/mixin";
+import discourseComputed from "discourse-common/utils/decorators";
export default Mixin.create({
queryParams: ["period"],
diff --git a/app/assets/javascripts/admin/addon/mixins/setting-component.js b/app/assets/javascripts/admin/addon/mixins/setting-component.js
index c7d42df43a..d96bd40c22 100644
--- a/app/assets/javascripts/admin/addon/mixins/setting-component.js
+++ b/app/assets/javascripts/admin/addon/mixins/setting-component.js
@@ -1,14 +1,14 @@
-import I18n from "I18n";
-import { warn } from "@ember/debug";
-import discourseComputed from "discourse-common/utils/decorators";
import { alias, oneWay } from "@ember/object/computed";
-import { categoryLinkHTML } from "discourse/helpers/category-link";
-import { on } from "@ember/object/evented";
+import I18n from "I18n";
import Mixin from "@ember/object/mixin";
-import showModal from "discourse/lib/show-modal";
import { Promise } from "rsvp";
import { ajax } from "discourse/lib/ajax";
+import { categoryLinkHTML } from "discourse/helpers/category-link";
+import discourseComputed from "discourse-common/utils/decorators";
import { htmlSafe } from "@ember/template";
+import { on } from "@ember/object/evented";
+import showModal from "discourse/lib/show-modal";
+import { warn } from "@ember/debug";
const CUSTOM_TYPES = [
"bool",
diff --git a/app/assets/javascripts/admin/addon/mixins/setting-object.js b/app/assets/javascripts/admin/addon/mixins/setting-object.js
index 5a40360b08..29dbb0d967 100644
--- a/app/assets/javascripts/admin/addon/mixins/setting-object.js
+++ b/app/assets/javascripts/admin/addon/mixins/setting-object.js
@@ -1,7 +1,7 @@
import I18n from "I18n";
-import discourseComputed from "discourse-common/utils/decorators";
-import { computed } from "@ember/object";
import Mixin from "@ember/object/mixin";
+import { computed } from "@ember/object";
+import discourseComputed from "discourse-common/utils/decorators";
import { isPresent } from "@ember/utils";
export default Mixin.create({
diff --git a/app/assets/javascripts/admin/addon/models/admin-dashboard.js b/app/assets/javascripts/admin/addon/models/admin-dashboard.js
index dec30faf2d..400ebe161b 100644
--- a/app/assets/javascripts/admin/addon/models/admin-dashboard.js
+++ b/app/assets/javascripts/admin/addon/models/admin-dashboard.js
@@ -1,5 +1,5 @@
-import { ajax } from "discourse/lib/ajax";
import EmberObject from "@ember/object";
+import { ajax } from "discourse/lib/ajax";
const GENERAL_ATTRIBUTES = [
"updated_at",
diff --git a/app/assets/javascripts/admin/addon/models/admin-user.js b/app/assets/javascripts/admin/addon/models/admin-user.js
index 0bc1132623..1a86426c5b 100644
--- a/app/assets/javascripts/admin/addon/models/admin-user.js
+++ b/app/assets/javascripts/admin/addon/models/admin-user.js
@@ -1,16 +1,14 @@
-import getURL from "discourse-common/lib/get-url";
-import I18n from "I18n";
-import discourseComputed from "discourse-common/utils/decorators";
-import { filter, or, gt, lt, not } from "@ember/object/computed";
-import { iconHTML } from "discourse-common/lib/icon-library";
-import { ajax } from "discourse/lib/ajax";
-import { propertyNotEqual } from "discourse/lib/computed";
-import { popupAjaxError } from "discourse/lib/ajax-error";
+import { filter, gt, lt, not, or } from "@ember/object/computed";
import Group from "discourse/models/group";
-import DiscourseURL, { userPath } from "discourse/lib/url";
+import I18n from "I18n";
import { Promise } from "rsvp";
import User from "discourse/models/user";
-import bootbox from "bootbox";
+import { ajax } from "discourse/lib/ajax";
+import discourseComputed from "discourse-common/utils/decorators";
+import getURL from "discourse-common/lib/get-url";
+import { popupAjaxError } from "discourse/lib/ajax-error";
+import { propertyNotEqual } from "discourse/lib/computed";
+import { userPath } from "discourse/lib/url";
const wrapAdmin = (user) => (user ? AdminUser.create(user) : null);
@@ -80,74 +78,9 @@ const AdminUser = User.extend({
},
deleteAllPosts() {
- let deletedPosts = 0;
- const user = this;
- const message = I18n.messageFormat(
- "admin.user.delete_all_posts_confirm_MF",
- {
- POSTS: user.get("post_count"),
- TOPICS: user.get("topic_count"),
- }
- );
- const buttons = [
- {
- label: I18n.t("composer.cancel"),
- class: "d-modal-cancel",
- link: true,
- },
- {
- label:
- `${iconHTML("exclamation-triangle")} ` +
- I18n.t("admin.user.delete_all_posts"),
- class: "btn btn-danger",
- callback: () => {
- openProgressModal();
- performDelete();
- },
- },
- ];
- const openProgressModal = () => {
- bootbox.dialog(
- `
${I18n.t(
- "admin.user.delete_posts_progress"
- )}
`,
- [],
- { classes: "delete-posts-progress" }
- );
- };
- const performDelete = () => {
- let deletedPercentage = 0;
- return ajax(`/admin/users/${user.get("id")}/delete_posts_batch`, {
- type: "PUT",
- })
- .then(({ posts_deleted }) => {
- if (posts_deleted === 0) {
- user.set("post_count", 0);
- bootbox.hideAll();
- } else {
- deletedPosts += posts_deleted;
- deletedPercentage = Math.floor(
- (deletedPosts * 100) / user.get("post_count")
- );
- $(".delete-posts-progress .progress-bar > span").css({
- width: `${deletedPercentage}%`,
- });
- performDelete();
- }
- })
- .catch((e) => {
- bootbox.hideAll();
- let error;
- AdminUser.find(user.get("id")).then((u) => user.setProperties(u));
- if (e.jqXHR.responseJSON && e.jqXHR.responseJSON.errors) {
- error = e.jqXHR.responseJSON.errors[0];
- }
- error = error || I18n.t("admin.user.delete_posts_failed");
- bootbox.alert(error);
- });
- };
-
- bootbox.dialog(message, buttons, { classes: "delete-all-posts" });
+ return ajax(`/admin/users/${this.get("id")}/delete_posts_batch`, {
+ type: "PUT",
+ });
},
revokeAdmin() {
@@ -165,11 +98,7 @@ const AdminUser = User.extend({
grantAdmin() {
return ajax(`/admin/users/${this.id}/grant_admin`, {
type: "PUT",
- })
- .then(() => {
- bootbox.alert(I18n.t("admin.user.grant_admin_confirm"));
- })
- .catch(popupAjaxError);
+ });
},
revokeModeration() {
@@ -232,20 +161,7 @@ const AdminUser = User.extend({
return ajax(`/admin/users/${this.id}/trust_level`, {
type: "PUT",
data: { level: this.trust_level },
- })
- .then(() => window.location.reload())
- .catch((e) => {
- let error;
- if (e.jqXHR.responseJSON && e.jqXHR.responseJSON.errors) {
- error = e.jqXHR.responseJSON.errors[0];
- }
- error =
- error ||
- I18n.t("admin.user.trust_level_change_failed", {
- error: this._formatError(e),
- });
- bootbox.alert(error);
- });
+ });
},
restoreTrustLevel() {
@@ -256,20 +172,7 @@ const AdminUser = User.extend({
return ajax(`/admin/users/${this.id}/trust_level_lock`, {
type: "PUT",
data: { locked: !!locked },
- })
- .then(() => window.location.reload())
- .catch((e) => {
- let error;
- if (e.jqXHR.responseJSON && e.jqXHR.responseJSON.errors) {
- error = e.jqXHR.responseJSON.errors[0];
- }
- error =
- error ||
- I18n.t("admin.user.trust_level_change_failed", {
- error: this._formatError(e),
- });
- bootbox.alert(error);
- });
+ });
},
canLockTrustLevel: lt("trust_level", 4),
@@ -300,49 +203,27 @@ const AdminUser = User.extend({
return ajax("/admin/users/" + this.id + "/log_out", {
type: "POST",
data: { username_or_email: this.username },
- }).then(() => bootbox.alert(I18n.t("admin.user.logged_out")));
+ });
},
impersonate() {
return ajax("/admin/impersonate", {
type: "POST",
data: { username_or_email: this.username },
- })
- .then(() => (document.location = getURL("/")))
- .catch((e) => {
- if (e.status === 404) {
- bootbox.alert(I18n.t("admin.impersonate.not_found"));
- } else {
- bootbox.alert(I18n.t("admin.impersonate.invalid"));
- }
- });
+ });
},
activate() {
return ajax(`/admin/users/${this.id}/activate`, {
type: "PUT",
- })
- .then(() => window.location.reload())
- .catch((e) => {
- const error = I18n.t("admin.user.activate_failed", {
- error: this._formatError(e),
- });
- bootbox.alert(error);
- });
+ });
},
deactivate() {
return ajax(`/admin/users/${this.id}/deactivate`, {
type: "PUT",
data: { context: document.location.pathname },
- })
- .then(() => window.location.reload())
- .catch((e) => {
- const error = I18n.t("admin.user.deactivate_failed", {
- error: this._formatError(e),
- });
- bootbox.alert(error);
- });
+ });
},
unsilence() {
@@ -370,160 +251,27 @@ const AdminUser = User.extend({
return ajax(userPath("action/send_activation_email"), {
type: "POST",
data: { username: this.username },
- })
- .then(() => bootbox.alert(I18n.t("admin.user.activation_email_sent")))
- .catch(popupAjaxError);
+ });
},
anonymize() {
- const user = this;
- const message = I18n.t("admin.user.anonymize_confirm");
-
- const performAnonymize = function () {
- return ajax(`/admin/users/${user.get("id")}/anonymize.json`, {
- type: "PUT",
- })
- .then(function (data) {
- if (data.success) {
- if (data.username) {
- document.location = getURL(
- `/admin/users/${user.get("id")}/${data.username}`
- );
- } else {
- document.location = getURL("/admin/users/list/active");
- }
- } else {
- bootbox.alert(I18n.t("admin.user.anonymize_failed"));
- if (data.user) {
- user.setProperties(data.user);
- }
- }
- })
- .catch(() => bootbox.alert(I18n.t("admin.user.anonymize_failed")));
- };
-
- const buttons = [
- {
- label: I18n.t("composer.cancel"),
- class: "cancel",
- link: true,
- },
- {
- label:
- `${iconHTML("exclamation-triangle")} ` +
- I18n.t("admin.user.anonymize_yes"),
- class: "btn btn-danger",
- callback: function () {
- performAnonymize();
- },
- },
- ];
-
- bootbox.dialog(message, buttons, { classes: "delete-user-modal" });
+ return ajax(`/admin/users/${this.id}/anonymize.json`, {
+ type: "PUT",
+ });
},
- destroy(opts) {
- const user = this;
- const message = I18n.t("admin.user.delete_confirm");
- const location = document.location.pathname;
-
- const performDestroy = function (block) {
- bootbox.dialog(I18n.t("admin.user.deleting_user"));
- let formData = { context: location };
- if (block) {
- formData["block_email"] = true;
- formData["block_urls"] = true;
- formData["block_ip"] = true;
- }
- if (opts && opts.deletePosts) {
- formData["delete_posts"] = true;
- }
- return ajax(`/admin/users/${user.get("id")}.json`, {
- type: "DELETE",
- data: formData,
- })
- .then(function (data) {
- if (data.deleted) {
- if (/^\/admin\/users\/list\//.test(location)) {
- document.location = location;
- } else {
- document.location = getURL("/admin/users/list/active");
- }
- } else {
- bootbox.alert(I18n.t("admin.user.delete_failed"));
- if (data.user) {
- user.setProperties(data.user);
- }
- }
- })
- .catch(function () {
- AdminUser.find(user.get("id")).then((u) => user.setProperties(u));
- bootbox.alert(I18n.t("admin.user.delete_failed"));
- });
- };
-
- const buttons = [
- {
- label: I18n.t("composer.cancel"),
- class: "btn",
- link: true,
- },
- {
- label:
- `${iconHTML("exclamation-triangle")} ` +
- I18n.t("admin.user.delete_and_block"),
- class: "btn btn-danger",
- callback: function () {
- performDestroy(true);
- },
- },
- {
- label: I18n.t("admin.user.delete_dont_block"),
- class: "btn btn-primary",
- callback: function () {
- performDestroy(false);
- },
- },
- ];
-
- bootbox.dialog(message, buttons, { classes: "delete-user-modal" });
+ destroy(formData) {
+ return ajax(`/admin/users/${this.id}.json`, {
+ type: "DELETE",
+ data: formData,
+ });
},
- merge(opts) {
- const user = this;
- const location = document.location.pathname;
-
- bootbox.dialog(I18n.t("admin.user.merging_user"));
- let formData = { context: location };
-
- if (opts && opts.targetUsername) {
- formData["target_username"] = opts.targetUsername;
- }
-
- return ajax(`/admin/users/${user.id}/merge.json`, {
+ merge(formData) {
+ return ajax(`/admin/users/${this.id}/merge.json`, {
type: "POST",
data: formData,
- })
- .then((data) => {
- if (data.merged) {
- if (/^\/admin\/users\/list\//.test(location)) {
- DiscourseURL.redirectTo(location);
- } else {
- DiscourseURL.redirectTo(
- `/admin/users/${data.user.id}/${data.user.username}`
- );
- }
- } else {
- bootbox.alert(I18n.t("admin.user.merge_failed"));
- if (data.user) {
- user.setProperties(data.user);
- }
- }
- })
- .catch(() => {
- AdminUser.find(user.id).then((u) => user.setProperties(u));
- bootbox.alert(I18n.t("admin.user.merge_failed"));
- });
+ });
},
loadDetails() {
@@ -553,10 +301,6 @@ const AdminUser = User.extend({
@discourseComputed("approved_by")
approvedBy: wrapAdmin,
- _formatError(event) {
- return `http: ${event.status} - ${event.body}`;
- },
-
deleteSSORecord() {
return ajax(`/admin/users/${this.id}/sso_record.json`, {
type: "DELETE",
diff --git a/app/assets/javascripts/admin/addon/models/api-key.js b/app/assets/javascripts/admin/addon/models/api-key.js
index adf186d454..be5475a4ab 100644
--- a/app/assets/javascripts/admin/addon/models/api-key.js
+++ b/app/assets/javascripts/admin/addon/models/api-key.js
@@ -1,8 +1,8 @@
-import discourseComputed from "discourse-common/utils/decorators";
import AdminUser from "admin/models/admin-user";
import RestModel from "discourse/models/rest";
import { ajax } from "discourse/lib/ajax";
import { computed } from "@ember/object";
+import discourseComputed from "discourse-common/utils/decorators";
import { fmt } from "discourse/lib/computed";
const ApiKey = RestModel.extend({
diff --git a/app/assets/javascripts/admin/addon/models/backup-status.js b/app/assets/javascripts/admin/addon/models/backup-status.js
index 474c3c1688..dffad0d060 100644
--- a/app/assets/javascripts/admin/addon/models/backup-status.js
+++ b/app/assets/javascripts/admin/addon/models/backup-status.js
@@ -1,6 +1,6 @@
+import EmberObject from "@ember/object";
import discourseComputed from "discourse-common/utils/decorators";
import { not } from "@ember/object/computed";
-import EmberObject from "@ember/object";
export default EmberObject.extend({
restoreDisabled: not("restoreEnabled"),
diff --git a/app/assets/javascripts/admin/addon/models/backup.js b/app/assets/javascripts/admin/addon/models/backup.js
index 4112b06f2b..717192e8ac 100644
--- a/app/assets/javascripts/admin/addon/models/backup.js
+++ b/app/assets/javascripts/admin/addon/models/backup.js
@@ -1,10 +1,6 @@
-import getURL from "discourse-common/lib/get-url";
-import I18n from "I18n";
-import { ajax } from "discourse/lib/ajax";
-import { extractError } from "discourse/lib/ajax-error";
import EmberObject from "@ember/object";
import MessageBus from "message-bus-client";
-import bootbox from "bootbox";
+import { ajax } from "discourse/lib/ajax";
const Backup = EmberObject.extend({
destroy() {
@@ -21,16 +17,7 @@ const Backup = EmberObject.extend({
Backup.reopenClass({
find() {
- return ajax("/admin/backups.json")
- .then((backups) => backups.map((backup) => Backup.create(backup)))
- .catch((error) => {
- bootbox.alert(
- I18n.t("admin.backups.backup_storage_error", {
- error_message: extractError(error),
- })
- );
- return [];
- });
+ return ajax("/admin/backups.json");
},
start(withUploads) {
@@ -43,33 +30,18 @@ Backup.reopenClass({
with_uploads: withUploads,
client_id: MessageBus.clientId,
},
- }).then((result) => {
- if (!result.success) {
- bootbox.alert(result.message);
- }
});
},
cancel() {
return ajax("/admin/backups/cancel.json", {
type: "DELETE",
- }).then((result) => {
- if (!result.success) {
- bootbox.alert(result.message);
- }
});
},
rollback() {
return ajax("/admin/backups/rollback.json", {
type: "POST",
- }).then((result) => {
- if (!result.success) {
- bootbox.alert(result.message);
- } else {
- // redirect to homepage (session might be lost)
- window.location = getURL("/");
- }
});
},
});
diff --git a/app/assets/javascripts/admin/addon/models/color-scheme-color.js b/app/assets/javascripts/admin/addon/models/color-scheme-color.js
index f5427d542c..49cb552a92 100644
--- a/app/assets/javascripts/admin/addon/models/color-scheme-color.js
+++ b/app/assets/javascripts/admin/addon/models/color-scheme-color.js
@@ -1,10 +1,10 @@
-import I18n from "I18n";
import discourseComputed, {
observes,
on,
} from "discourse-common/utils/decorators";
-import { propertyNotEqual } from "discourse/lib/computed";
import EmberObject from "@ember/object";
+import I18n from "I18n";
+import { propertyNotEqual } from "discourse/lib/computed";
const ColorSchemeColor = EmberObject.extend({
@on("init")
diff --git a/app/assets/javascripts/admin/addon/models/color-scheme.js b/app/assets/javascripts/admin/addon/models/color-scheme.js
index 4bce289ba7..e1b73ad14e 100644
--- a/app/assets/javascripts/admin/addon/models/color-scheme.js
+++ b/app/assets/javascripts/admin/addon/models/color-scheme.js
@@ -1,11 +1,11 @@
-import I18n from "I18n";
import { A } from "@ember/array";
import ArrayProxy from "@ember/array/proxy";
-import discourseComputed from "discourse-common/utils/decorators";
-import { not } from "@ember/object/computed";
-import { ajax } from "discourse/lib/ajax";
import ColorSchemeColor from "admin/models/color-scheme-color";
import EmberObject from "@ember/object";
+import I18n from "I18n";
+import { ajax } from "discourse/lib/ajax";
+import discourseComputed from "discourse-common/utils/decorators";
+import { not } from "@ember/object/computed";
const ColorScheme = EmberObject.extend({
init() {
diff --git a/app/assets/javascripts/admin/addon/models/email-log.js b/app/assets/javascripts/admin/addon/models/email-log.js
index 18406ceb7a..6565611974 100644
--- a/app/assets/javascripts/admin/addon/models/email-log.js
+++ b/app/assets/javascripts/admin/addon/models/email-log.js
@@ -1,7 +1,7 @@
-import getURL from "discourse-common/lib/get-url";
-import { ajax } from "discourse/lib/ajax";
import AdminUser from "admin/models/admin-user";
import EmberObject from "@ember/object";
+import { ajax } from "discourse/lib/ajax";
+import getURL from "discourse-common/lib/get-url";
const EmailLog = EmberObject.extend({});
diff --git a/app/assets/javascripts/admin/addon/models/email-preview.js b/app/assets/javascripts/admin/addon/models/email-preview.js
index 893fb5b4fb..96ffe2f949 100644
--- a/app/assets/javascripts/admin/addon/models/email-preview.js
+++ b/app/assets/javascripts/admin/addon/models/email-preview.js
@@ -1,5 +1,5 @@
-import { ajax } from "discourse/lib/ajax";
import EmberObject from "@ember/object";
+import { ajax } from "discourse/lib/ajax";
const EmailPreview = EmberObject.extend({});
diff --git a/app/assets/javascripts/admin/addon/models/email-settings.js b/app/assets/javascripts/admin/addon/models/email-settings.js
index 52ac14acec..f959df408f 100644
--- a/app/assets/javascripts/admin/addon/models/email-settings.js
+++ b/app/assets/javascripts/admin/addon/models/email-settings.js
@@ -1,5 +1,5 @@
-import { ajax } from "discourse/lib/ajax";
import EmberObject from "@ember/object";
+import { ajax } from "discourse/lib/ajax";
const EmailSettings = EmberObject.extend({});
diff --git a/app/assets/javascripts/admin/addon/models/email-template.js b/app/assets/javascripts/admin/addon/models/email-template.js
index b58da0457f..4be7d9fff9 100644
--- a/app/assets/javascripts/admin/addon/models/email-template.js
+++ b/app/assets/javascripts/admin/addon/models/email-template.js
@@ -1,5 +1,5 @@
-import { ajax } from "discourse/lib/ajax";
import RestModel from "discourse/models/rest";
+import { ajax } from "discourse/lib/ajax";
const { getProperties } = Ember;
export default RestModel.extend({
diff --git a/app/assets/javascripts/admin/addon/models/flag-type.js b/app/assets/javascripts/admin/addon/models/flag-type.js
index 607cb755d8..5859584ce7 100644
--- a/app/assets/javascripts/admin/addon/models/flag-type.js
+++ b/app/assets/javascripts/admin/addon/models/flag-type.js
@@ -1,6 +1,6 @@
import I18n from "I18n";
-import discourseComputed from "discourse-common/utils/decorators";
import RestModel from "discourse/models/rest";
+import discourseComputed from "discourse-common/utils/decorators";
export default RestModel.extend({
@discourseComputed("id")
diff --git a/app/assets/javascripts/admin/addon/models/incoming-email.js b/app/assets/javascripts/admin/addon/models/incoming-email.js
index 42eb995f85..8489ae8dd3 100644
--- a/app/assets/javascripts/admin/addon/models/incoming-email.js
+++ b/app/assets/javascripts/admin/addon/models/incoming-email.js
@@ -1,6 +1,6 @@
-import { ajax } from "discourse/lib/ajax";
import AdminUser from "admin/models/admin-user";
import EmberObject from "@ember/object";
+import { ajax } from "discourse/lib/ajax";
const IncomingEmail = EmberObject.extend({});
diff --git a/app/assets/javascripts/admin/addon/models/permalink.js b/app/assets/javascripts/admin/addon/models/permalink.js
index de61b27fd4..a2e8445b08 100644
--- a/app/assets/javascripts/admin/addon/models/permalink.js
+++ b/app/assets/javascripts/admin/addon/models/permalink.js
@@ -1,8 +1,8 @@
+import Category from "discourse/models/category";
+import DiscourseURL from "discourse/lib/url";
+import EmberObject from "@ember/object";
import { ajax } from "discourse/lib/ajax";
import discourseComputed from "discourse-common/utils/decorators";
-import DiscourseURL from "discourse/lib/url";
-import Category from "discourse/models/category";
-import EmberObject from "@ember/object";
const Permalink = EmberObject.extend({
save: function () {
diff --git a/app/assets/javascripts/admin/addon/models/report.js b/app/assets/javascripts/admin/addon/models/report.js
index a7b3d5786d..baa0aba16f 100644
--- a/app/assets/javascripts/admin/addon/models/report.js
+++ b/app/assets/javascripts/admin/addon/models/report.js
@@ -1,19 +1,19 @@
-import getURL from "discourse-common/lib/get-url";
-import I18n from "I18n";
-import discourseComputed from "discourse-common/utils/decorators";
-import { makeArray } from "discourse-common/lib/helpers";
-import { isEmpty } from "@ember/utils";
-import EmberObject from "@ember/object";
-import { ajax } from "discourse/lib/ajax";
-import round from "discourse/lib/round";
+import { durationTiny, number } from "discourse/lib/formatter";
import {
+ escapeExpression,
fillMissingDates,
formatUsername,
toNumber,
- escapeExpression,
} from "discourse/lib/utilities";
-import { number, durationTiny } from "discourse/lib/formatter";
+import EmberObject from "@ember/object";
+import I18n from "I18n";
+import { ajax } from "discourse/lib/ajax";
+import discourseComputed from "discourse-common/utils/decorators";
+import getURL from "discourse-common/lib/get-url";
+import { isEmpty } from "@ember/utils";
+import { makeArray } from "discourse-common/lib/helpers";
import { renderAvatar } from "discourse/helpers/user-avatar";
+import round from "discourse/lib/round";
// Change this line each time report format change
// and you want to ensure cache is reset
diff --git a/app/assets/javascripts/admin/addon/models/screened-email.js b/app/assets/javascripts/admin/addon/models/screened-email.js
index 4e902488d1..857cca0d63 100644
--- a/app/assets/javascripts/admin/addon/models/screened-email.js
+++ b/app/assets/javascripts/admin/addon/models/screened-email.js
@@ -1,7 +1,7 @@
-import I18n from "I18n";
-import discourseComputed from "discourse-common/utils/decorators";
-import { ajax } from "discourse/lib/ajax";
import EmberObject from "@ember/object";
+import I18n from "I18n";
+import { ajax } from "discourse/lib/ajax";
+import discourseComputed from "discourse-common/utils/decorators";
const ScreenedEmail = EmberObject.extend({
@discourseComputed("action")
diff --git a/app/assets/javascripts/admin/addon/models/screened-ip-address.js b/app/assets/javascripts/admin/addon/models/screened-ip-address.js
index 33e2b44317..a7d29aab31 100644
--- a/app/assets/javascripts/admin/addon/models/screened-ip-address.js
+++ b/app/assets/javascripts/admin/addon/models/screened-ip-address.js
@@ -1,8 +1,8 @@
+import EmberObject from "@ember/object";
import I18n from "I18n";
+import { ajax } from "discourse/lib/ajax";
import discourseComputed from "discourse-common/utils/decorators";
import { equal } from "@ember/object/computed";
-import { ajax } from "discourse/lib/ajax";
-import EmberObject from "@ember/object";
const ScreenedIpAddress = EmberObject.extend({
@discourseComputed("action_name")
diff --git a/app/assets/javascripts/admin/addon/models/screened-url.js b/app/assets/javascripts/admin/addon/models/screened-url.js
index a7bc7cfa6f..f3769c7d2f 100644
--- a/app/assets/javascripts/admin/addon/models/screened-url.js
+++ b/app/assets/javascripts/admin/addon/models/screened-url.js
@@ -1,7 +1,7 @@
-import I18n from "I18n";
-import discourseComputed from "discourse-common/utils/decorators";
-import { ajax } from "discourse/lib/ajax";
import EmberObject from "@ember/object";
+import I18n from "I18n";
+import { ajax } from "discourse/lib/ajax";
+import discourseComputed from "discourse-common/utils/decorators";
const ScreenedUrl = EmberObject.extend({
@discourseComputed("action")
diff --git a/app/assets/javascripts/admin/addon/models/site-setting.js b/app/assets/javascripts/admin/addon/models/site-setting.js
index 350281e616..49ed58366e 100644
--- a/app/assets/javascripts/admin/addon/models/site-setting.js
+++ b/app/assets/javascripts/admin/addon/models/site-setting.js
@@ -1,7 +1,7 @@
-import I18n from "I18n";
-import { ajax } from "discourse/lib/ajax";
-import Setting from "admin/mixins/setting-object";
import EmberObject from "@ember/object";
+import I18n from "I18n";
+import Setting from "admin/mixins/setting-object";
+import { ajax } from "discourse/lib/ajax";
import discourseComputed from "discourse-common/utils/decorators";
const SiteSetting = EmberObject.extend(Setting, {
diff --git a/app/assets/javascripts/admin/addon/models/site-text.js b/app/assets/javascripts/admin/addon/models/site-text.js
index 7dcd614402..c25a5b30a0 100644
--- a/app/assets/javascripts/admin/addon/models/site-text.js
+++ b/app/assets/javascripts/admin/addon/models/site-text.js
@@ -1,10 +1,10 @@
-import { ajax } from "discourse/lib/ajax";
import RestModel from "discourse/models/rest";
-const { getProperties } = Ember;
+import { ajax } from "discourse/lib/ajax";
+import { getProperties } from "@ember/object";
export default RestModel.extend({
- revert() {
- return ajax(`/admin/customize/site_texts/${this.id}`, {
+ revert(locale) {
+ return ajax(`/admin/customize/site_texts/${this.id}?locale=${locale}`, {
type: "DELETE",
}).then((result) => getProperties(result.site_text, "value", "can_revert"));
},
diff --git a/app/assets/javascripts/admin/addon/models/staff-action-log.js b/app/assets/javascripts/admin/addon/models/staff-action-log.js
index 09d84b6791..70d86c41e7 100644
--- a/app/assets/javascripts/admin/addon/models/staff-action-log.js
+++ b/app/assets/javascripts/admin/addon/models/staff-action-log.js
@@ -1,9 +1,9 @@
-import I18n from "I18n";
-import discourseComputed from "discourse-common/utils/decorators";
-import { ajax } from "discourse/lib/ajax";
import AdminUser from "admin/models/admin-user";
-import { escapeExpression } from "discourse/lib/utilities";
+import I18n from "I18n";
import RestModel from "discourse/models/rest";
+import { ajax } from "discourse/lib/ajax";
+import discourseComputed from "discourse-common/utils/decorators";
+import { escapeExpression } from "discourse/lib/utilities";
function format(label, value, escape = true) {
return value
diff --git a/app/assets/javascripts/admin/addon/models/theme-settings.js b/app/assets/javascripts/admin/addon/models/theme-settings.js
index a823592ad2..d91c3e583e 100644
--- a/app/assets/javascripts/admin/addon/models/theme-settings.js
+++ b/app/assets/javascripts/admin/addon/models/theme-settings.js
@@ -1,4 +1,4 @@
-import Setting from "admin/mixins/setting-object";
import EmberObject from "@ember/object";
+import Setting from "admin/mixins/setting-object";
export default EmberObject.extend(Setting, {});
diff --git a/app/assets/javascripts/admin/addon/models/theme.js b/app/assets/javascripts/admin/addon/models/theme.js
index 10c78c5b82..d41ecb7f5f 100644
--- a/app/assets/javascripts/admin/addon/models/theme.js
+++ b/app/assets/javascripts/admin/addon/models/theme.js
@@ -1,9 +1,9 @@
-import I18n from "I18n";
-import { get } from "@ember/object";
+import { gt, or } from "@ember/object/computed";
import { isBlank, isEmpty } from "@ember/utils";
-import { or, gt } from "@ember/object/computed";
+import I18n from "I18n";
import RestModel from "discourse/models/rest";
import discourseComputed from "discourse-common/utils/decorators";
+import { get } from "@ember/object";
import { popupAjaxError } from "discourse/lib/ajax-error";
const THEME_UPLOAD_VAR = 2;
@@ -253,6 +253,11 @@ const Theme = RestModel.extend({
}
},
+ @discourseComputed("recentlyInstalled", "component", "hasParents")
+ warnUnassignedComponent(recent, component, hasParents) {
+ return recent && component && !hasParents;
+ },
+
removeChildTheme(theme) {
const childThemes = this.childThemes;
childThemes.removeObject(theme);
diff --git a/app/assets/javascripts/admin/addon/models/tl3-requirements.js b/app/assets/javascripts/admin/addon/models/tl3-requirements.js
index a6b31363b9..920d6e5f66 100644
--- a/app/assets/javascripts/admin/addon/models/tl3-requirements.js
+++ b/app/assets/javascripts/admin/addon/models/tl3-requirements.js
@@ -1,5 +1,5 @@
-import discourseComputed from "discourse-common/utils/decorators";
import EmberObject from "@ember/object";
+import discourseComputed from "discourse-common/utils/decorators";
export default EmberObject.extend({
@discourseComputed("days_visited", "time_period")
diff --git a/app/assets/javascripts/admin/addon/models/version-check.js b/app/assets/javascripts/admin/addon/models/version-check.js
index 53882d6eca..4f939064af 100644
--- a/app/assets/javascripts/admin/addon/models/version-check.js
+++ b/app/assets/javascripts/admin/addon/models/version-check.js
@@ -1,6 +1,6 @@
-import discourseComputed from "discourse-common/utils/decorators";
-import { ajax } from "discourse/lib/ajax";
import EmberObject from "@ember/object";
+import { ajax } from "discourse/lib/ajax";
+import discourseComputed from "discourse-common/utils/decorators";
const VersionCheck = EmberObject.extend({
@discourseComputed("updated_at")
diff --git a/app/assets/javascripts/admin/addon/models/watched-word.js b/app/assets/javascripts/admin/addon/models/watched-word.js
index 938b25f7bc..741d037249 100644
--- a/app/assets/javascripts/admin/addon/models/watched-word.js
+++ b/app/assets/javascripts/admin/addon/models/watched-word.js
@@ -1,6 +1,6 @@
+import EmberObject from "@ember/object";
import I18n from "I18n";
import { ajax } from "discourse/lib/ajax";
-import EmberObject from "@ember/object";
const WatchedWord = EmberObject.extend({
save() {
diff --git a/app/assets/javascripts/admin/addon/models/web-hook.js b/app/assets/javascripts/admin/addon/models/web-hook.js
index 677d76aa88..8dd568a9fb 100644
--- a/app/assets/javascripts/admin/addon/models/web-hook.js
+++ b/app/assets/javascripts/admin/addon/models/web-hook.js
@@ -1,9 +1,9 @@
-import { isEmpty } from "@ember/utils";
-import RestModel from "discourse/models/rest";
+import discourseComputed, { observes } from "discourse-common/utils/decorators";
import Category from "discourse/models/category";
import Group from "discourse/models/group";
-import discourseComputed, { observes } from "discourse-common/utils/decorators";
+import RestModel from "discourse/models/rest";
import Site from "discourse/models/site";
+import { isEmpty } from "@ember/utils";
export default RestModel.extend({
content_type: 1, // json
diff --git a/app/assets/javascripts/admin/addon/routes/admin-backups-index.js b/app/assets/javascripts/admin/addon/routes/admin-backups-index.js
index aee755b705..cb05c26580 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-backups-index.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-backups-index.js
@@ -1,5 +1,5 @@
-import Route from "@ember/routing/route";
import Backup from "admin/models/backup";
+import Route from "@ember/routing/route";
export default Route.extend({
activate() {
@@ -12,7 +12,9 @@ export default Route.extend({
},
model() {
- return Backup.find();
+ return Backup.find().then((backups) =>
+ backups.map((backup) => Backup.create(backup))
+ );
},
deactivate() {
diff --git a/app/assets/javascripts/admin/addon/routes/admin-backups-logs.js b/app/assets/javascripts/admin/addon/routes/admin-backups-logs.js
index e2e3a933c8..8de1ef5240 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-backups-logs.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-backups-logs.js
@@ -1,6 +1,6 @@
import EmberObject from "@ember/object";
-import Route from "@ember/routing/route";
import PreloadStore from "discourse/lib/preload-store";
+import Route from "@ember/routing/route";
export default Route.extend({
// since the logs are pushed via the message bus
diff --git a/app/assets/javascripts/admin/addon/routes/admin-backups.js b/app/assets/javascripts/admin/addon/routes/admin-backups.js
index 41c6cb0f8b..063eeec9d7 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-backups.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-backups.js
@@ -1,14 +1,15 @@
-import getURL from "discourse-common/lib/get-url";
-import I18n from "I18n";
-import EmberObject from "@ember/object";
-import DiscourseRoute from "discourse/routes/discourse";
-import { ajax } from "discourse/lib/ajax";
-import showModal from "discourse/lib/show-modal";
-import BackupStatus from "admin/models/backup-status";
import Backup from "admin/models/backup";
+import BackupStatus from "admin/models/backup-status";
+import DiscourseRoute from "discourse/routes/discourse";
+import EmberObject from "@ember/object";
+import I18n from "I18n";
import PreloadStore from "discourse/lib/preload-store";
import User from "discourse/models/user";
+import { ajax } from "discourse/lib/ajax";
import bootbox from "bootbox";
+import { extractError } from "discourse/lib/ajax-error";
+import getURL from "discourse-common/lib/get-url";
+import showModal from "discourse/lib/show-modal";
const LOG_CHANNEL = "/admin/backups/logs";
@@ -74,7 +75,11 @@ export default DiscourseRoute.extend({
startBackup(withUploads) {
this.transitionTo("admin.backups.logs");
- Backup.start(withUploads);
+ Backup.start(withUploads).then((result) => {
+ if (!result.success) {
+ bootbox.alert(result.message);
+ }
+ });
},
destroyBackup(backup) {
@@ -135,7 +140,14 @@ export default DiscourseRoute.extend({
I18n.t("yes_value"),
(confirmed) => {
if (confirmed) {
- Backup.rollback();
+ Backup.rollback().then((result) => {
+ if (!result.success) {
+ bootbox.alert(result.message);
+ } else {
+ // redirect to homepage (session might be lost)
+ window.location = getURL("/");
+ }
+ });
}
}
);
@@ -152,12 +164,22 @@ export default DiscourseRoute.extend({
},
remoteUploadSuccess() {
- Backup.find().then((backups) => {
- this.controllerFor("adminBackupsIndex").set(
- "model",
- backups.map((backup) => Backup.create(backup))
- );
- });
+ Backup.find()
+ .then((backups) => backups.map((backup) => Backup.create(backup)))
+ .then((backups) => {
+ this.controllerFor("adminBackupsIndex").set(
+ "model",
+ backups.map((backup) => Backup.create(backup))
+ );
+ })
+ .catch((error) => {
+ bootbox.alert(
+ I18n.t("admin.backups.backup_storage_error", {
+ error_message: extractError(error),
+ })
+ );
+ return [];
+ });
},
},
});
diff --git a/app/assets/javascripts/admin/addon/routes/admin-badges-show.js b/app/assets/javascripts/admin/addon/routes/admin-badges-show.js
index c95cae8afa..a370cd32d8 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-badges-show.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-badges-show.js
@@ -1,10 +1,10 @@
+import Badge from "discourse/models/badge";
import I18n from "I18n";
-import { get } from "@ember/object";
import Route from "@ember/routing/route";
import { ajax } from "discourse/lib/ajax";
-import Badge from "discourse/models/badge";
-import showModal from "discourse/lib/show-modal";
import bootbox from "bootbox";
+import { get } from "@ember/object";
+import showModal from "discourse/lib/show-modal";
export default Route.extend({
serialize(m) {
diff --git a/app/assets/javascripts/admin/addon/routes/admin-badges.js b/app/assets/javascripts/admin/addon/routes/admin-badges.js
index 59bc0944cb..ac4b9e9b53 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-badges.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-badges.js
@@ -1,8 +1,8 @@
-import I18n from "I18n";
-import DiscourseRoute from "discourse/routes/discourse";
-import { ajax } from "discourse/lib/ajax";
import Badge from "discourse/models/badge";
import BadgeGrouping from "discourse/models/badge-grouping";
+import DiscourseRoute from "discourse/routes/discourse";
+import I18n from "I18n";
+import { ajax } from "discourse/lib/ajax";
export default DiscourseRoute.extend({
_json: null,
diff --git a/app/assets/javascripts/admin/addon/routes/admin-customize-colors.js b/app/assets/javascripts/admin/addon/routes/admin-customize-colors.js
index b2d4f2c16b..cf2dc3d18d 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-customize-colors.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-customize-colors.js
@@ -1,5 +1,5 @@
-import Route from "@ember/routing/route";
import ColorScheme from "admin/models/color-scheme";
+import Route from "@ember/routing/route";
export default Route.extend({
model() {
diff --git a/app/assets/javascripts/admin/addon/routes/admin-customize-themes-edit.js b/app/assets/javascripts/admin/addon/routes/admin-customize-themes-edit.js
index 030645e445..0d55baa6ce 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-customize-themes-edit.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-customize-themes-edit.js
@@ -28,7 +28,7 @@ export default Route.extend({
const fields = wrapper.model
.get("fields")
[wrapper.target].map((f) => f.name);
- if (wrapper.model.remote_theme) {
+ if (wrapper.model.remote_theme && wrapper.model.remote_theme.is_git) {
this.transitionTo("adminCustomizeThemes.index");
return;
}
diff --git a/app/assets/javascripts/admin/addon/routes/admin-customize-themes-show.js b/app/assets/javascripts/admin/addon/routes/admin-customize-themes-show.js
index feaf0ef7ae..5bcf95d3d2 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-customize-themes-show.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-customize-themes-show.js
@@ -1,7 +1,21 @@
+import { COMPONENTS, THEMES } from "admin/models/theme";
import I18n from "I18n";
import Route from "@ember/routing/route";
import { scrollTop } from "discourse/mixins/scroll-top";
-import { THEMES, COMPONENTS } from "admin/models/theme";
+
+export function showUnassignedComponentWarning(theme, callback) {
+ bootbox.confirm(
+ I18n.t("admin.customize.theme.unsaved_parent_themes"),
+ I18n.t("admin.customize.theme.discard"),
+ I18n.t("admin.customize.theme.stay"),
+ (result) => {
+ if (!result) {
+ theme.set("recentlyInstalled", false);
+ }
+ callback(result);
+ }
+ );
+}
export default Route.extend({
serialize(model) {
@@ -11,7 +25,7 @@ export default Route.extend({
model(params) {
const all = this.modelFor("adminCustomizeThemes");
const model = all.findBy("id", parseInt(params.theme_id, 10));
- return model ? model : this.replaceWith("adminCustomizeTheme.index");
+ return model ? model : this.replaceWith("adminCustomizeThemes.index");
},
setupController(controller, model) {
@@ -55,19 +69,13 @@ export default Route.extend({
},
willTransition(transition) {
const model = this.controller.model;
- if (model.recentlyInstalled && !model.hasParents && model.component) {
+ if (model.warnUnassignedComponent) {
transition.abort();
- bootbox.confirm(
- I18n.t("admin.customize.theme.unsaved_parent_themes"),
- I18n.t("admin.customize.theme.discard"),
- I18n.t("admin.customize.theme.stay"),
- (result) => {
- if (!result) {
- this.controller.model.setProperties({ recentlyInstalled: false });
- transition.retry();
- }
+ showUnassignedComponentWarning(model, (result) => {
+ if (!result) {
+ transition.retry();
}
- );
+ });
}
},
},
diff --git a/app/assets/javascripts/admin/addon/routes/admin-customize-themes.js b/app/assets/javascripts/admin/addon/routes/admin-customize-themes.js
index 2da0266f42..9397c938a9 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-customize-themes.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-customize-themes.js
@@ -1,5 +1,6 @@
import Route from "@ember/routing/route";
import showModal from "discourse/lib/show-modal";
+import { showUnassignedComponentWarning } from "admin/routes/admin-customize-themes-show";
export default Route.extend({
model() {
@@ -13,7 +14,17 @@ export default Route.extend({
actions: {
installModal() {
- showModal("admin-install-theme", { admin: true });
+ const currentTheme = this.controllerFor("adminCustomizeThemes.show")
+ .model;
+ if (currentTheme && currentTheme.warnUnassignedComponent) {
+ showUnassignedComponentWarning(currentTheme, (result) => {
+ if (!result) {
+ showModal("admin-install-theme", { admin: true });
+ }
+ });
+ } else {
+ showModal("admin-install-theme", { admin: true });
+ }
},
addTheme(theme) {
diff --git a/app/assets/javascripts/admin/addon/routes/admin-email-bounced.js b/app/assets/javascripts/admin/addon/routes/admin-email-bounced.js
index 041b25fc05..d89010c9ef 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-email-bounced.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-email-bounced.js
@@ -1,5 +1,5 @@
-import showModal from "discourse/lib/show-modal";
import AdminEmailLogs from "admin/routes/admin-email-logs";
+import showModal from "discourse/lib/show-modal";
export default AdminEmailLogs.extend({
status: "bounced",
diff --git a/app/assets/javascripts/admin/addon/routes/admin-email-preview-digest.js b/app/assets/javascripts/admin/addon/routes/admin-email-preview-digest.js
index 03d72f0f82..730bcd0e7e 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-email-preview-digest.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-email-preview-digest.js
@@ -1,5 +1,5 @@
-import DiscourseRoute from "discourse/routes/discourse";
import EmailPreview, { oneWeekAgo } from "admin/models/email-preview";
+import DiscourseRoute from "discourse/routes/discourse";
export default DiscourseRoute.extend({
model() {
diff --git a/app/assets/javascripts/admin/addon/routes/admin-email-rejected.js b/app/assets/javascripts/admin/addon/routes/admin-email-rejected.js
index e5d4501549..ce45fa8962 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-email-rejected.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-email-rejected.js
@@ -1,5 +1,5 @@
-import showModal from "discourse/lib/show-modal";
import AdminEmailIncomings from "admin/routes/admin-email-incomings";
+import showModal from "discourse/lib/show-modal";
export default AdminEmailIncomings.extend({
status: "rejected",
diff --git a/app/assets/javascripts/admin/addon/routes/admin-emojis.js b/app/assets/javascripts/admin/addon/routes/admin-emojis.js
index 5db8760a51..5047bd6f82 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-emojis.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-emojis.js
@@ -1,5 +1,5 @@
-import EmberObject from "@ember/object";
import DiscourseRoute from "discourse/routes/discourse";
+import EmberObject from "@ember/object";
import { ajax } from "discourse/lib/ajax";
export default DiscourseRoute.extend({
diff --git a/app/assets/javascripts/admin/addon/routes/admin-logs-staff-action-logs.js b/app/assets/javascripts/admin/addon/routes/admin-logs-staff-action-logs.js
index a3c3f196e0..68657da533 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-logs-staff-action-logs.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-logs-staff-action-logs.js
@@ -1,6 +1,6 @@
import DiscourseRoute from "discourse/routes/discourse";
-import showModal from "discourse/lib/show-modal";
import EmberObject from "@ember/object";
+import showModal from "discourse/lib/show-modal";
export default DiscourseRoute.extend({
queryParams: {
diff --git a/app/assets/javascripts/admin/addon/routes/admin-search-logs-index.js b/app/assets/javascripts/admin/addon/routes/admin-search-logs-index.js
index c688b8ebba..c04f3b22b8 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-search-logs-index.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-search-logs-index.js
@@ -1,5 +1,5 @@
-import EmberObject from "@ember/object";
import DiscourseRoute from "discourse/routes/discourse";
+import EmberObject from "@ember/object";
import { ajax } from "discourse/lib/ajax";
export default DiscourseRoute.extend({
diff --git a/app/assets/javascripts/admin/addon/routes/admin-search-logs-term.js b/app/assets/javascripts/admin/addon/routes/admin-search-logs-term.js
index 989d258384..b9613fe04f 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-search-logs-term.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-search-logs-term.js
@@ -1,5 +1,5 @@
-import EmberObject from "@ember/object";
import DiscourseRoute from "discourse/routes/discourse";
+import EmberObject from "@ember/object";
import { ajax } from "discourse/lib/ajax";
import { fillMissingDates } from "discourse/lib/utilities";
import { translateResults } from "discourse/lib/search";
diff --git a/app/assets/javascripts/admin/addon/routes/admin-site-settings-category.js b/app/assets/javascripts/admin/addon/routes/admin-site-settings-category.js
index be2a2180d2..aab0b337db 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-site-settings-category.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-site-settings-category.js
@@ -1,6 +1,6 @@
-import I18n from "I18n";
-import EmberObject from "@ember/object";
import DiscourseRoute from "discourse/routes/discourse";
+import EmberObject from "@ember/object";
+import I18n from "I18n";
export default DiscourseRoute.extend({
model(params) {
diff --git a/app/assets/javascripts/admin/addon/routes/admin-site-text-edit.js b/app/assets/javascripts/admin/addon/routes/admin-site-text-edit.js
index fe720907c7..40c74fced3 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-site-text-edit.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-site-text-edit.js
@@ -1,10 +1,30 @@
import Route from "@ember/routing/route";
+import { ajax } from "discourse/lib/ajax";
+
export default Route.extend({
+ queryParams: {
+ locale: { replace: true },
+ },
+
model(params) {
- return this.store.find("site-text", params.id);
+ return ajax(
+ `/admin/customize/site_texts/${params.id}?locale=${params.locale}`
+ ).then((result) => {
+ return this.store.createRecord("site-text", result.site_text);
+ });
},
setupController(controller, siteText) {
- controller.setProperties({ siteText, saved: false });
+ const locales = JSON.parse(this.siteSettings.available_locales);
+
+ const localeFullName = locales.find((locale) => {
+ return locale.value === controller.locale;
+ }).name;
+
+ controller.setProperties({
+ siteText,
+ saved: false,
+ localeFullName: localeFullName,
+ });
},
});
diff --git a/app/assets/javascripts/admin/addon/routes/admin-site-text-index.js b/app/assets/javascripts/admin/addon/routes/admin-site-text-index.js
index 036438235d..255315a846 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-site-text-index.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-site-text-index.js
@@ -1,17 +1,18 @@
import Route from "@ember/routing/route";
-import showModal from "discourse/lib/show-modal";
import { getProperties } from "@ember/object";
+import showModal from "discourse/lib/show-modal";
export default Route.extend({
queryParams: {
q: { replace: true },
overridden: { replace: true },
+ locale: { replace: true },
},
model(params) {
return this.store.find(
"site-text",
- getProperties(params, "q", "overridden")
+ getProperties(params, "q", "overridden", "locale")
);
},
diff --git a/app/assets/javascripts/admin/addon/routes/admin-user-badges.js b/app/assets/javascripts/admin/addon/routes/admin-user-badges.js
index f15649f92d..f9549e39e6 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-user-badges.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-user-badges.js
@@ -1,6 +1,6 @@
+import Badge from "discourse/models/badge";
import DiscourseRoute from "discourse/routes/discourse";
import UserBadge from "discourse/models/user-badge";
-import Badge from "discourse/models/badge";
export default DiscourseRoute.extend({
model() {
diff --git a/app/assets/javascripts/admin/addon/routes/admin-user.js b/app/assets/javascripts/admin/addon/routes/admin-user.js
index 90436dabd4..d9627ba571 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-user.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-user.js
@@ -1,6 +1,6 @@
-import { get } from "@ember/object";
-import DiscourseRoute from "discourse/routes/discourse";
import AdminUser from "admin/models/admin-user";
+import DiscourseRoute from "discourse/routes/discourse";
+import { get } from "@ember/object";
export default DiscourseRoute.extend({
serialize(model) {
diff --git a/app/assets/javascripts/admin/addon/routes/admin-users-list.js b/app/assets/javascripts/admin/addon/routes/admin-users-list.js
index db8106a8ed..4630c8efc8 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-users-list.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-users-list.js
@@ -1,7 +1,7 @@
+import AdminUser from "admin/models/admin-user";
import DiscourseRoute from "discourse/routes/discourse";
import { exportEntity } from "discourse/lib/export-csv";
import { outputExportResult } from "discourse/lib/export-result";
-import AdminUser from "admin/models/admin-user";
export default DiscourseRoute.extend({
actions: {
diff --git a/app/assets/javascripts/admin/addon/routes/admin-watched-words-action.js b/app/assets/javascripts/admin/addon/routes/admin-watched-words-action.js
index 3c770f7e09..fe1ce75ab7 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-watched-words-action.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-watched-words-action.js
@@ -1,6 +1,6 @@
-import I18n from "I18n";
-import EmberObject from "@ember/object";
import DiscourseRoute from "discourse/routes/discourse";
+import EmberObject from "@ember/object";
+import I18n from "I18n";
export default DiscourseRoute.extend({
model(params) {
diff --git a/app/assets/javascripts/admin/addon/routes/admin-web-hooks-show-events.js b/app/assets/javascripts/admin/addon/routes/admin-web-hooks-show-events.js
index b07b390d40..1b7923224b 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-web-hooks-show-events.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-web-hooks-show-events.js
@@ -1,5 +1,5 @@
-import { get } from "@ember/object";
import DiscourseRoute from "discourse/routes/discourse";
+import { get } from "@ember/object";
export default DiscourseRoute.extend({
model(params) {
diff --git a/app/assets/javascripts/admin/addon/routes/admin-web-hooks-show.js b/app/assets/javascripts/admin/addon/routes/admin-web-hooks-show.js
index a5eb3dd873..6d7c64f955 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-web-hooks-show.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-web-hooks-show.js
@@ -1,5 +1,5 @@
-import { get } from "@ember/object";
import DiscourseRoute from "discourse/routes/discourse";
+import { get } from "@ember/object";
export default DiscourseRoute.extend({
serialize(model) {
diff --git a/app/assets/javascripts/admin/addon/routes/admin.js b/app/assets/javascripts/admin/addon/routes/admin.js
index c84051d171..e0949ba414 100644
--- a/app/assets/javascripts/admin/addon/routes/admin.js
+++ b/app/assets/javascripts/admin/addon/routes/admin.js
@@ -1,5 +1,5 @@
-import I18n from "I18n";
import DiscourseRoute from "discourse/routes/discourse";
+import I18n from "I18n";
export default DiscourseRoute.extend({
titleToken() {
diff --git a/app/assets/javascripts/admin/addon/services/admin-tools.js b/app/assets/javascripts/admin/addon/services/admin-tools.js
index fc02b998fe..16294be1b3 100644
--- a/app/assets/javascripts/admin/addon/services/admin-tools.js
+++ b/app/assets/javascripts/admin/addon/services/admin-tools.js
@@ -1,16 +1,16 @@
-import I18n from "I18n";
+import AdminUser from "admin/models/admin-user";
// A service that can act as a bridge between the front end Discourse application
// and the admin application. Use this if you need front end code to access admin
// modules. Inject it optionally, and if it exists go to town!
-import AdminUser from "admin/models/admin-user";
-import { iconHTML } from "discourse-common/lib/icon-library";
-import { ajax } from "discourse/lib/ajax";
-import showModal from "discourse/lib/show-modal";
-import { getOwner } from "discourse-common/lib/get-owner";
-import Service from "@ember/service";
+import I18n from "I18n";
import { Promise } from "rsvp";
+import Service from "@ember/service";
+import { ajax } from "discourse/lib/ajax";
import bootbox from "bootbox";
+import { getOwner } from "discourse-common/lib/get-owner";
+import { iconHTML } from "discourse-common/lib/icon-library";
+import showModal from "discourse/lib/show-modal";
export default Service.extend({
init() {
diff --git a/app/assets/javascripts/admin/addon/templates/badges-show.hbs b/app/assets/javascripts/admin/addon/templates/badges-show.hbs
index 49741c8bc6..82057b103c 100644
--- a/app/assets/javascripts/admin/addon/templates/badges-show.hbs
+++ b/app/assets/javascripts/admin/addon/templates/badges-show.hbs
@@ -4,6 +4,11 @@
{{#if readOnly}}
{{input type="text" name="name" value=buffered.name disabled=true}}
+
+ {{#link-to "adminSiteText.edit" (concat textCustomizationPrefix "name")}}
+ {{i18n "admin.badges.read_only_setting_help"}}
+ {{/link-to}}
+
{{else}}
{{input type="text" name="name" value=buffered.name}}
{{/if}}
@@ -64,6 +69,11 @@
{{#if buffered.system}}
{{textarea name="description" value=buffered.description disabled=true}}
+
+ {{#link-to "adminSiteText.edit" (concat textCustomizationPrefix "description")}}
+ {{i18n "admin.badges.read_only_setting_help"}}
+ {{/link-to}}
+
{{else}}
{{textarea name="description" value=buffered.description}}
{{/if}}
@@ -73,6 +83,11 @@
{{#if buffered.system}}
{{textarea name="long_description" value=buffered.long_description disabled=true}}
+
+ {{#link-to "adminSiteText.edit" (concat textCustomizationPrefix "long_description")}}
+ {{i18n "admin.badges.read_only_setting_help"}}
+ {{/link-to}}
+
{{else}}
{{textarea name="long_description" value=buffered.long_description}}
{{/if}}
diff --git a/app/assets/javascripts/admin/addon/templates/components/embeddable-host.hbs b/app/assets/javascripts/admin/addon/templates/components/embeddable-host.hbs
index 7d73d93a2b..db8d108308 100644
--- a/app/assets/javascripts/admin/addon/templates/components/embeddable-host.hbs
+++ b/app/assets/javascripts/admin/addon/templates/components/embeddable-host.hbs
@@ -1,7 +1,7 @@
{{#if editing}}
{{i18n "admin.embedding.host"}}
- {{input value=buffered.host placeholder="example.com" enter=(action "save") class="host-name"}}
+ {{input value=buffered.host placeholder="example.com" enter=(action "save") class="host-name" autofocus=true}}
|
{{i18n "admin.embedding.class_name"}}
diff --git a/app/assets/javascripts/admin/addon/templates/components/watched-word-form.hbs b/app/assets/javascripts/admin/addon/templates/components/watched-word-form.hbs
index 0aa201b602..eba5ecabda 100644
--- a/app/assets/javascripts/admin/addon/templates/components/watched-word-form.hbs
+++ b/app/assets/javascripts/admin/addon/templates/components/watched-word-form.hbs
@@ -1,5 +1,5 @@
{{i18n "admin.watched_words.form.label"}}
-{{text-field value=word disabled=formSubmitted class="watched-word-input" autocorrect="off" autocapitalize="off" placeholderKey=placeholderKey}}
+{{text-field value=word disabled=formSubmitted class="watched-word-input" autocorrect="off" autocapitalize="off" placeholderKey=placeholderKey title=(i18n placeholderKey)}}
{{d-button class="btn-default" action=(action "submit") disabled=formSubmitted label="admin.watched_words.form.add"}}
{{#if showMessage}}
diff --git a/app/assets/javascripts/admin/addon/templates/customize-colors-show.hbs b/app/assets/javascripts/admin/addon/templates/customize-colors-show.hbs
index e359c1fe67..eeabe4e5c9 100644
--- a/app/assets/javascripts/admin/addon/templates/customize-colors-show.hbs
+++ b/app/assets/javascripts/admin/addon/templates/customize-colors-show.hbs
@@ -41,31 +41,34 @@
- {{#if model.theme_id}}
- {{inline-edit-checkbox action=(action "applyUserSelectable") labelKey="admin.customize.theme.color_scheme_user_selectable" checked=model.user_selectable modelId=model.id}}
- {{else}}
-
- {{/if}}
+ {{#unless model.theme_id}}
+
+
+
+ {{/unless}}
+
+
+ {{#if model.theme_id}}
+ {{inline-edit-checkbox action=(action "applyUserSelectable") labelKey="admin.customize.theme.color_scheme_user_selectable" checked=model.user_selectable modelId=model.id}}
+ {{else}}
+
+ {{/if}}
+
{{#if colors.length}}
- |
- |
+ |
{{i18n "admin.customize.color"}} |
-
- {{#unless model.theme_id}}
-
- {{/unless}}
- |
+ |
diff --git a/app/assets/javascripts/admin/addon/templates/customize-themes-edit.hbs b/app/assets/javascripts/admin/addon/templates/customize-themes-edit.hbs
index a4e7fa583f..32e3521f65 100644
--- a/app/assets/javascripts/admin/addon/templates/customize-themes-edit.hbs
+++ b/app/assets/javascripts/admin/addon/templates/customize-themes-edit.hbs
@@ -1,6 +1,21 @@
- {{i18n "admin.customize.theme.edit_css_html"}} {{#link-to showRouteName model.id replace=true}}{{model.name}}{{/link-to}}
+
+ {{d-button
+ title="go_back"
+ action=(action "goBack")
+ icon="chevron-left"
+ class="btn-small editor-back-button"
+ }}
+
+
+ {{i18n "admin.customize.theme.edit_css_html"}}
+ {{#link-to showRouteName model.id replace=true class="editor-theme-name"
+ }}
+ {{model.name}}
+ {{/link-to}}
+
+
{{admin-theme-editor
theme=model
@@ -15,14 +30,24 @@
-
- {{/unless}}
+ {{/if}}
+
diff --git a/app/assets/javascripts/discourse/app/templates/components/emoji-picker.hbs b/app/assets/javascripts/discourse/app/templates/components/emoji-picker.hbs
index f5873c44a1..7dd6db19eb 100644
--- a/app/assets/javascripts/discourse/app/templates/components/emoji-picker.hbs
+++ b/app/assets/javascripts/discourse/app/templates/components/emoji-picker.hbs
@@ -84,7 +84,7 @@
{{d-button
icon=diversityScale.icon
class=(concat "diversity-scale " diversityScale.name)
- title=(concat "emoji_picker." diversityScale.name "_tone")
+ title=diversityScale.title
action=(action "onDiversitySelection" index)
}}
{{/each}}
diff --git a/app/assets/javascripts/discourse/app/templates/components/future-date-input.hbs b/app/assets/javascripts/discourse/app/templates/components/future-date-input.hbs
index 43c7e421e0..aa92210bc7 100644
--- a/app/assets/javascripts/discourse/app/templates/components/future-date-input.hbs
+++ b/app/assets/javascripts/discourse/app/templates/components/future-date-input.hbs
@@ -1,7 +1,7 @@
+
+{{plugin-outlet
+ name="after-topic-list-body"
+ args=(hash
+ topics=topics
+ selected=selected
+ bulkSelectEnabled=bulkSelectEnabled
+ lastVisitedTopic=lastVisitedTopic
+ discoveryList=discoveryList
+ hideCategory=hideCategory)
+ tagName=""
+ connectorTagName=""}}
diff --git a/app/assets/javascripts/discourse/app/templates/components/user-card-contents.hbs b/app/assets/javascripts/discourse/app/templates/components/user-card-contents.hbs
index 28e08da19e..b14298cd26 100644
--- a/app/assets/javascripts/discourse/app/templates/components/user-card-contents.hbs
+++ b/app/assets/javascripts/discourse/app/templates/components/user-card-contents.hbs
@@ -81,9 +81,9 @@
{{d-button
class="btn-default"
- action=(action "togglePosts" this.user)
+ action=(action "filterPosts" this.user)
icon="filter"
- translatedLabel=this.togglePostsLabel}}
+ translatedLabel=this.filterPostsLabel}}
{{/if}}
{{#if this.hasUserFilters}}
@@ -142,7 +142,11 @@
{{else}}
{{#if this.user.bio_excerpt}}
- {{html-safe this.user.bio_excerpt}}
+
+ {{#html-with-links}}
+ {{html-safe this.user.bio_excerpt}}
+ {{/html-with-links}}
+
{{/if}}
{{/if}}
diff --git a/app/assets/javascripts/discourse/app/templates/components/user-notification-schedule-day.hbs b/app/assets/javascripts/discourse/app/templates/components/user-notification-schedule-day.hbs
new file mode 100644
index 0000000000..b03f167228
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/templates/components/user-notification-schedule-day.hbs
@@ -0,0 +1,22 @@
+
+ | {{dayLabel}} |
+
+ {{combo-box
+ valueProperty="value"
+ content=startTimeOptions
+ value=startTimeValue
+ onChange=onChangeStartTime
+ }}
+ |
+ {{#if endTimeOptions}}
+ {{i18n "user.notification_schedule.to"}} |
+
+ {{combo-box
+ valueProperty="value"
+ content=endTimeOptions
+ value=endTimeValue
+ onChange=onChangeEndTime
+ }}
+ |
+ {{/if}}
+
diff --git a/app/assets/javascripts/discourse/app/templates/components/user-notification-schedule.hbs b/app/assets/javascripts/discourse/app/templates/components/user-notification-schedule.hbs
new file mode 100644
index 0000000000..acc1486e76
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/templates/components/user-notification-schedule.hbs
@@ -0,0 +1,26 @@
+
+
+ {{preference-checkbox
+ labelKey="user.notification_schedule.label"
+ checked=model.user_notification_schedule.enabled}}
+
+ {{#if model.user_notification_schedule.enabled}}
+ {{i18n "user.notification_schedule.tip"}}
+
+
+
+ {{#each days as |day|}}
+ {{user-notification-schedule-day
+ day=day.day
+ startTimeOptions=day.startTimeOptions
+ startTimeValue=day.startTimeValue
+ onChangeStartTime=day.onChangeStartTime
+ endTimeOptions=day.endTimeOptions
+ endTimeValue=day.endTimeValue
+ onChangeEndTime=day.onChangeEndTime
+ }}
+ {{/each}}
+
+
+ {{/if}}
+
diff --git a/app/assets/javascripts/discourse/app/templates/discovery.hbs b/app/assets/javascripts/discourse/app/templates/discovery.hbs
index 6358886107..a5f57bbd41 100644
--- a/app/assets/javascripts/discourse/app/templates/discovery.hbs
+++ b/app/assets/javascripts/discourse/app/templates/discovery.hbs
@@ -1,41 +1,37 @@
-{{#if errorHtml}}
- {{html-safe errorHtml}}
-{{else}}
+
+ {{discourse-banner user=currentUser banner=site.banner}}
+ {{#unless viewingCategoriesList}}
+ {{category-read-only-banner category=category readOnly=navigationCategory.cannotCreateTopicOnCategory}}
+ {{/unless}}
+
+
+
- {{discourse-banner user=currentUser banner=site.banner}}
- {{#unless viewingCategoriesList}}
- {{category-read-only-banner category=category readOnly=navigationCategory.cannotCreateTopicOnCategory}}
- {{/unless}}
+ {{outlet "navigation-bar"}}
+
-
-
- {{outlet "navigation-bar"}}
-
-
+{{conditional-loading-spinner condition=loading}}
- {{conditional-loading-spinner condition=loading}}
+{{plugin-outlet name="discovery-above"}}
- {{plugin-outlet name="discovery-above"}}
-
-
-
-
-
-
- {{plugin-outlet name="discovery-list-container-top"
- args=(hash category=category listLoading=loading)}}
- {{outlet "list-container"}}
-
+
+
+
+
+
+ {{plugin-outlet name="discovery-list-container-top"
+ args=(hash category=category listLoading=loading)}}
+ {{outlet "list-container"}}
+
+
+
+
- {{plugin-outlet name="discovery-below"}}
-{{/if}}
+{{plugin-outlet name="discovery-below"}}
diff --git a/app/assets/javascripts/discourse/app/templates/full-page-search.hbs b/app/assets/javascripts/discourse/app/templates/full-page-search.hbs
index f95bc36dc7..fcbd8c506d 100644
--- a/app/assets/javascripts/discourse/app/templates/full-page-search.hbs
+++ b/app/assets/javascripts/discourse/app/templates/full-page-search.hbs
@@ -4,8 +4,8 @@
- {{format-age result.created_at}}
+ {{format-date result.created_at format="tiny"}}
{{#if result.blurb}}
-
{{/if}}
@@ -193,7 +193,7 @@
{{#if site.mobileView}}
{{search-text-field value=searchTerm class="full-page-search search no-blur search-query" enter=(action "search") hasAutofocus=hasAutofocus}}
- {{d-button action=(action "search") icon="search" class="btn-primary search-cta" disabled=searchButtonDisabled}}
+ {{d-button action=(action "search") icon="search" class="btn-primary search-cta" ariaLabel="search.search_button" disabled=searchButtonDisabled}}
{{/if}}
diff --git a/app/assets/javascripts/discourse/app/templates/group-activity-posts.hbs b/app/assets/javascripts/discourse/app/templates/group-activity-posts.hbs
index f134929e6c..8e833dc151 100644
--- a/app/assets/javascripts/discourse/app/templates/group-activity-posts.hbs
+++ b/app/assets/javascripts/discourse/app/templates/group-activity-posts.hbs
@@ -1,7 +1,7 @@
{{#load-more selector=".user-stream-item" action=(action "loadMore")}}
{{#each model as |post|}}
- {{group-post post=post class="user-stream-item item"}}
+ {{group-post post=post}}
{{else}}
{{i18n emptyText}}
{{/each}}
diff --git a/app/assets/javascripts/discourse/app/templates/group/manage/tags.hbs b/app/assets/javascripts/discourse/app/templates/group/manage/tags.hbs
index 604ac18524..8560c2f1ae 100644
--- a/app/assets/javascripts/discourse/app/templates/group/manage/tags.hbs
+++ b/app/assets/javascripts/discourse/app/templates/group/manage/tags.hbs
@@ -1,4 +1,7 @@
-
- {{radio-button id="gravatar" name="avatar" value="gravatar" selection=selected}}
-
-
- {{d-button action=(action "refreshGravatar")
- translatedTitle=(i18n "user.change_avatar.refresh_gravatar_title" gravatarName=gravatarName)
- disabled=gravatarRefreshDisabled
- icon="sync"
- class="btn-default avatar-selector-refresh-gravatar"}}
-
- {{#if gravatarFailed}}
- {{I18n "user.change_avatar.gravatar_failed" gravatarName=gravatarName}}
- {{/if}}
-
{{#if allowAvatarUpload}}
+
+ {{radio-button id="gravatar" name="avatar" value="gravatar" selection=selected}}
+
+
+ {{d-button action=(action "refreshGravatar")
+ translatedTitle=(i18n "user.change_avatar.refresh_gravatar_title" gravatarName=gravatarName)
+ disabled=gravatarRefreshDisabled
+ icon="sync"
+ class="btn-default avatar-selector-refresh-gravatar"}}
+
+ {{#if gravatarFailed}}
+ {{I18n "user.change_avatar.gravatar_failed" gravatarName=gravatarName}}
+ {{/if}}
+
{{radio-button id="uploaded-avatar" name="avatar" value="uploaded" selection=selected}}
|