diff --git a/.github/workflows/licenses.yml b/.github/workflows/licenses.yml index adefc3998c..18fa2b2f0e 100644 --- a/.github/workflows/licenses.yml +++ b/.github/workflows/licenses.yml @@ -48,10 +48,7 @@ jobs: - name: Setup licensed run: | - # gem install licensed - # Workaround for https://github.com/github/licensed/issues/521 - gem install specific_install - gem specific_install https://github.com/CvX/licensed.git -b bundler-compat + gem install licensed - name: Get yarn cache directory id: yarn-cache-dir diff --git a/.ruby-version.sample b/.ruby-version.sample index 37c2961c24..49cdd668e1 100644 --- a/.ruby-version.sample +++ b/.ruby-version.sample @@ -1 +1 @@ -2.7.2 +2.7.6 diff --git a/.template-lintrc.js b/.template-lintrc.js index e3fc07b48d..b50cdcb5fd 100644 --- a/.template-lintrc.js +++ b/.template-lintrc.js @@ -3,6 +3,9 @@ module.exports = { extends: "discourse:recommended", rules: { + "no-action-modifiers": true, + "no-args-paths": true, + "no-attrs-in-components": true, "no-capital-arguments": false, // TODO: we extensively use `args` argument name "no-curly-component-invocation": { allow: [ diff --git a/Gemfile b/Gemfile index e29c6737be..daf68be0cb 100644 --- a/Gemfile +++ b/Gemfile @@ -39,7 +39,7 @@ gem 'sprockets', '3.7.2' # allows us to precompile all our templates in the unicorn master gem 'actionview_precompiler', require: false -gem 'seed-fu' +gem 'discourse-seed-fu' gem 'mail', git: 'https://github.com/discourse/mail.git' gem 'mini_mime' @@ -134,13 +134,10 @@ gem 'cose', require: false gem 'addressable' gem 'json_schemer' -if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.1") - # net-smtp, net-imap and net-pop were removed from default gems in Ruby 3.1 - gem "net-smtp", "~> 0.2.1", require: false - gem "net-imap", "~> 0.2.1", require: false - gem "net-pop", "~> 0.1.1", require: false - gem "digest", "3.0.0", require: false -end +gem "net-smtp", require: false +gem "net-imap", require: false +gem "net-pop", require: false +gem "digest", require: false # Gems used only for assets and not required in production environments by default. # Allow everywhere for now cause we are allowing asset debugging in production @@ -272,6 +269,9 @@ gem 'maxminddb' gem 'rails_failover', require: false +gem 'faraday' +gem 'faraday-retry' + # workaround for faraday-net_http, see # https://github.com/ruby/net-imap/issues/16#issuecomment-803086765 gem 'net-http' diff --git a/Gemfile.lock b/Gemfile.lock index 1a47d48853..84fa798d48 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -106,7 +106,7 @@ GEM colored2 (3.1.2) concurrent-ruby (1.1.10) connection_pool (2.3.0) - cose (1.2.1) + cose (1.3.0) cbor (~> 0.5.9) openssl-signature_algorithm (~> 1.0) cppjieba_rb (0.4.2) @@ -118,6 +118,7 @@ GEM debug_inspector (1.1.0) diff-lcs (1.5.0) diffy (3.4.2) + digest (3.1.0) discourse-ember-rails (0.18.6) active_model_serializers ember-data-source (>= 1.0.0.beta.5) @@ -127,6 +128,9 @@ GEM railties (>= 3.1) discourse-ember-source (3.12.2.3) discourse-fonts (0.0.9) + discourse-seed-fu (2.3.12) + activerecord (>= 3.1) + activesupport (>= 3.1) discourse_dev_assets (0.0.4) faker (~> 2.16) literate_randomizer @@ -141,17 +145,19 @@ GEM sprockets (>= 3.3, < 4.1) ember-source (2.18.2) erubi (1.11.0) - excon (0.92.5) + excon (0.93.1) execjs (2.8.1) - exifr (1.3.9) + exifr (1.3.10) fabrication (2.30.0) faker (2.23.0) i18n (>= 1.8.11, < 2) fakeweb (1.3.0) - faraday (2.5.2) + faraday (2.6.0) faraday-net_http (>= 2.0, < 3.1) ruby2_keywords (>= 0.0.4) - faraday-net_http (3.0.0) + faraday-net_http (3.0.1) + faraday-retry (2.0.0) + faraday (~> 2.0) fast_blank (1.0.1) fast_xs (0.8.0) fastimage (2.2.6) @@ -184,9 +190,9 @@ GEM railties (>= 4.2.0) thor (>= 0.14, < 2.0) json (2.6.2) - json-schema (2.8.1) - addressable (>= 2.4) - json_schemer (0.2.21) + json-schema (3.0.0) + addressable (>= 2.8) + json_schemer (0.2.22) ecma-re-validator (~> 0.3) hana (~> 1.3) regexp_parser (~> 2.0) @@ -219,7 +225,7 @@ GEM lz4-ruby (0.3.3) matrix (0.4.2) maxminddb (0.1.22) - memory_profiler (1.0.0) + memory_profiler (1.0.1) message_bus (4.2.0) rack (>= 1.1.3) method_source (1.0.0) @@ -233,39 +239,39 @@ GEM mini_suffix (0.3.3) ffi (~> 1.9) minitest (5.16.3) - mocha (1.15.0) - msgpack (1.5.6) + mocha (1.16.0) + msgpack (1.6.0) multi_json (1.15.0) multi_xml (0.6.0) mustache (1.1.1) net-http (0.2.2) uri - net-imap (0.3.0) + net-imap (0.3.1) net-protocol net-pop (0.1.2) net-protocol net-protocol (0.1.3) timeout - net-smtp (0.3.2) + net-smtp (0.3.3) net-protocol nio4r (2.5.8) - nokogiri (1.13.8) + nokogiri (1.13.9) mini_portile2 (~> 2.8.0) racc (~> 1.4) - nokogiri (1.13.8-aarch64-linux) + nokogiri (1.13.9-aarch64-linux) racc (~> 1.4) - nokogiri (1.13.8-arm64-darwin) + nokogiri (1.13.9-arm64-darwin) racc (~> 1.4) - nokogiri (1.13.8-x86_64-darwin) + nokogiri (1.13.9-x86_64-darwin) racc (~> 1.4) - nokogiri (1.13.8-x86_64-linux) + nokogiri (1.13.9-x86_64-linux) racc (~> 1.4) oauth (1.1.0) oauth-tty (~> 1.0, >= 1.0.1) snaky_hash (~> 2.0) version_gem (~> 1.1) - oauth-tty (1.0.3) - version_gem (~> 1.1) + oauth-tty (1.0.5) + version_gem (~> 1.1, >= 1.1.1) oauth2 (1.4.11) faraday (>= 0.17.3, < 3.0) jwt (>= 1.0, < 3.0) @@ -304,7 +310,7 @@ GEM parallel parser (3.1.2.1) ast (~> 2.4.1) - pg (1.4.3) + pg (1.4.4) progress (3.6.0) pry (0.14.1) coderay (~> 1.1) @@ -322,7 +328,7 @@ GEM rack (2.2.4) rack-mini-profiler (3.0.0) rack (>= 1.2.0) - rack-protection (3.0.1) + rack-protection (3.0.2) rack rack-test (2.0.2) rack (>= 1.3) @@ -369,52 +375,53 @@ GEM chunky_png (~> 1.0) rqrcode_core (~> 1.0) rqrcode_core (1.2.0) - rspec (3.11.0) - rspec-core (~> 3.11.0) - rspec-expectations (~> 3.11.0) - rspec-mocks (~> 3.11.0) - rspec-core (3.11.0) - rspec-support (~> 3.11.0) - rspec-expectations (3.11.1) + rspec (3.12.0) + rspec-core (~> 3.12.0) + rspec-expectations (~> 3.12.0) + rspec-mocks (~> 3.12.0) + rspec-core (3.12.0) + rspec-support (~> 3.12.0) + rspec-expectations (3.12.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.11.0) + rspec-support (~> 3.12.0) rspec-html-matchers (0.10.0) nokogiri (~> 1) rspec (>= 3.0.0.a) - rspec-mocks (3.11.1) + rspec-mocks (3.12.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.11.0) - rspec-rails (5.1.2) - actionpack (>= 5.2) - activesupport (>= 5.2) - railties (>= 5.2) - rspec-core (~> 3.10) - rspec-expectations (~> 3.10) - rspec-mocks (~> 3.10) - rspec-support (~> 3.10) - rspec-support (3.11.1) + rspec-support (~> 3.12.0) + rspec-rails (6.0.1) + actionpack (>= 6.1) + activesupport (>= 6.1) + railties (>= 6.1) + rspec-core (~> 3.11) + rspec-expectations (~> 3.11) + rspec-mocks (~> 3.11) + rspec-support (~> 3.11) + rspec-support (3.12.0) rss (0.2.9) rexml - rswag-specs (2.6.0) + rswag-specs (2.7.0) activesupport (>= 3.1, < 7.1) - json-schema (~> 2.2) + json-schema (>= 2.2, < 4.0) railties (>= 3.1, < 7.1) - rubocop (1.36.0) + rspec-core (>= 2.14) + rubocop (1.37.1) json (~> 2.3) parallel (~> 1.10) parser (>= 3.1.2.1) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.20.1, < 2.0) + rubocop-ast (>= 1.23.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.21.0) + rubocop-ast (1.23.0) parser (>= 3.1.1.0) rubocop-discourse (3.0) rubocop (>= 1.1.0) rubocop-rspec (>= 2.0.0) - rubocop-rspec (2.13.2) + rubocop-rspec (2.14.2) rubocop (~> 1.33) ruby-prof (1.4.3) ruby-progressbar (1.11.0) @@ -435,9 +442,6 @@ GEM sprockets (> 3.0) sprockets-rails tilt - seed-fu (2.3.9) - activerecord (>= 3.1) - activesupport (>= 3.1) selenium-webdriver (4.5.0) childprocess (>= 0.5, < 5.0) rexml (~> 3.2, >= 3.2.5) @@ -455,9 +459,9 @@ GEM simplecov_json_formatter (~> 0.1) simplecov-html (0.12.3) simplecov_json_formatter (0.1.4) - snaky_hash (2.0.0) + snaky_hash (2.0.1) hashie - version_gem (~> 1.1) + version_gem (~> 1.1, >= 1.1.1) sprockets (3.7.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) @@ -466,8 +470,8 @@ GEM activesupport (>= 5.2) sprockets (>= 3.0.0) sshkey (2.0.0) - stackprof (0.2.21) - test-prof (1.0.10) + stackprof (0.2.22) + test-prof (1.0.11) thor (1.2.1) tilt (2.0.11) timeout (0.3.0) @@ -485,8 +489,8 @@ GEM uniform_notifier (1.16.0) uri (0.11.0) uri_template (0.7.0) - version_gem (1.1.0) - webdrivers (5.1.0) + version_gem (1.1.1) + webdrivers (5.2.0) nokogiri (~> 1.6) rubyzip (>= 1.3.0) selenium-webdriver (~> 4.0) @@ -502,7 +506,7 @@ GEM xpath (3.2.0) nokogiri (~> 1.8) yaml-lint (0.0.10) - zeitwerk (2.6.0) + zeitwerk (2.6.3) PLATFORMS aarch64-linux @@ -540,9 +544,11 @@ DEPENDENCIES cppjieba_rb css_parser diffy + digest discourse-ember-rails (= 0.18.6) discourse-ember-source (~> 3.12.2) discourse-fonts + discourse-seed-fu discourse_dev_assets email_reply_trimmer ember-handlebars-template (= 0.8.0) @@ -551,6 +557,8 @@ DEPENDENCIES fabrication faker (~> 2.16) fakeweb + faraday + faraday-retry fast_blank fast_xs fastimage @@ -583,6 +591,9 @@ DEPENDENCIES multi_json mustache net-http + net-imap + net-pop + net-smtp nokogiri oj (= 3.13.14) omniauth @@ -624,7 +635,6 @@ DEPENDENCIES sanitize sassc (= 2.0.1) sassc-rails - seed-fu selenium-webdriver shoulda-matchers sidekiq @@ -645,4 +655,4 @@ DEPENDENCIES yaml-lint BUNDLED WITH - 2.3.18 + 2.3.22 diff --git a/app/assets/javascripts/admin/addon/components/admin-editable-field.js b/app/assets/javascripts/admin/addon/components/admin-editable-field.js index 993a3ed675..892a3208e8 100644 --- a/app/assets/javascripts/admin/addon/components/admin-editable-field.js +++ b/app/assets/javascripts/admin/addon/components/admin-editable-field.js @@ -1,4 +1,6 @@ import Component from "@ember/component"; +import { action } from "@ember/object"; + export default Component.extend({ tagName: "", @@ -10,12 +12,14 @@ export default Component.extend({ this.set("editing", false); }, - actions: { - edit() { - this.set("buffer", this.value); - this.toggleProperty("editing"); - }, + @action + edit(event) { + event?.preventDefault(); + this.set("buffer", this.value); + this.toggleProperty("editing"); + }, + actions: { save() { // Action has to toggle 'editing' property. this.action(this.buffer); 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 014055c149..de8f063579 100644 --- a/app/assets/javascripts/admin/addon/components/admin-theme-editor.js +++ b/app/assets/javascripts/admin/addon/components/admin-theme-editor.js @@ -3,6 +3,7 @@ import I18n from "I18n"; import discourseComputed from "discourse-common/utils/decorators"; import { fmt } from "discourse/lib/computed"; import { isDocumentRTL } from "discourse/lib/text-direction"; +import { action } from "@ember/object"; import { next } from "@ember/runloop"; export default Component.extend({ @@ -91,15 +92,26 @@ export default Component.extend({ return this.theme.getError(target, fieldName); }, + @action + toggleShowAdvanced(event) { + event?.preventDefault(); + this.toggleProperty("showAdvanced"); + }, + + @action + toggleAddField(event) { + event?.preventDefault(); + this.toggleProperty("addingField"); + }, + + @action + toggleMaximize(event) { + event?.preventDefault(); + this.toggleProperty("maximized"); + next(() => this.appEvents.trigger("ace:resize")); + }, + actions: { - toggleShowAdvanced() { - this.toggleProperty("showAdvanced"); - }, - - toggleAddField() { - this.toggleProperty("addingField"); - }, - cancelAddField() { this.set("addingField", false); }, @@ -114,11 +126,6 @@ export default Component.extend({ this.fieldAdded(this.currentTargetName, name); }, - toggleMaximize() { - this.toggleProperty("maximized"); - next(() => this.appEvents.trigger("ace:resize")); - }, - onlyOverriddenChanged(value) { this.onlyOverriddenChanged(value); }, diff --git a/app/assets/javascripts/admin/addon/components/embeddable-host.js b/app/assets/javascripts/admin/addon/components/embeddable-host.js index 328ad06e1e..320b173bfb 100644 --- a/app/assets/javascripts/admin/addon/components/embeddable-host.js +++ b/app/assets/javascripts/admin/addon/components/embeddable-host.js @@ -1,9 +1,9 @@ import Category from "discourse/models/category"; import Component from "@ember/component"; import I18n from "I18n"; -import bootbox from "bootbox"; import { bufferedProperty } from "discourse/mixins/buffered-content"; import discourseComputed from "discourse-common/utils/decorators"; +import { inject as service } from "@ember/service"; import { isEmpty } from "@ember/utils"; import { or } from "@ember/object/computed"; import { popupAjaxError } from "discourse/lib/ajax-error"; @@ -13,6 +13,7 @@ export default Component.extend(bufferedProperty("host"), { tagName: "tr", categoryId: null, category: null, + dialog: service(), editing: or("host.isNew", "editToggled"), @@ -61,12 +62,13 @@ export default Component.extend(bufferedProperty("host"), { }, delete() { - bootbox.confirm(I18n.t("admin.embedding.confirm_delete"), (result) => { - if (result) { - this.host.destroyRecord().then(() => { + return this.dialog.confirm({ + message: I18n.t("admin.embedding.confirm_delete"), + didConfirm: () => { + return this.host.destroyRecord().then(() => { this.deleteHost(this.host); }); - } + }, }); }, diff --git a/app/assets/javascripts/admin/addon/components/ip-lookup.js b/app/assets/javascripts/admin/addon/components/ip-lookup.js index 222e04b9ab..02a5240564 100644 --- a/app/assets/javascripts/admin/addon/components/ip-lookup.js +++ b/app/assets/javascripts/admin/addon/components/ip-lookup.js @@ -1,6 +1,6 @@ import AdminUser from "admin/models/admin-user"; import Component from "@ember/component"; -import EmberObject from "@ember/object"; +import EmberObject, { action } from "@ember/object"; import I18n from "I18n"; import { ajax } from "discourse/lib/ajax"; import copyText from "discourse/lib/copy-text"; @@ -21,6 +21,12 @@ export default Component.extend({ return Math.max(visible, total); }, + @action + hide(event) { + event?.preventDefault(); + this.set("show", false); + }, + actions: { lookup() { this.set("show", true); @@ -55,10 +61,6 @@ export default Component.extend({ } }, - hide() { - this.set("show", false); - }, - copy() { let text = `IP: ${this.ip}\n`; const location = this.location; 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 e2237e249b..29158c4496 100644 --- a/app/assets/javascripts/admin/addon/components/themes-list-item.js +++ b/app/assets/javascripts/admin/addon/components/themes-list-item.js @@ -3,6 +3,7 @@ import discourseComputed from "discourse-common/utils/decorators"; import Component from "@ember/component"; import { escape } from "pretty-text/sanitizer"; import { iconHTML } from "discourse-common/lib/icon-library"; +import { action } from "@ember/object"; const MAX_COMPONENTS = 4; @@ -59,9 +60,9 @@ export default Component.extend({ return childrenCount - MAX_COMPONENTS; }, - actions: { - toggleChildrenExpanded() { - this.toggleProperty("childrenExpanded"); - }, + @action + toggleChildrenExpanded(event) { + event?.preventDefault(); + this.toggleProperty("childrenExpanded"); }, }); 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 2b38081826..5b098387ef 100644 --- a/app/assets/javascripts/admin/addon/controllers/admin-badges/show.js +++ b/app/assets/javascripts/admin/addon/controllers/admin-badges/show.js @@ -133,6 +133,12 @@ export default class AdminBadgesShowController extends Controller.extend( this.buffered.set("image_url", null); } + @action + showPreview(badge, explain, event) { + event?.preventDefault(); + this.send("preview", badge, explain); + } + @action save() { if (!this.saving) { 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 d20f812ca3..c784deb0ec 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,13 +1,14 @@ import Controller, { inject as controller } from "@ember/controller"; 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"; +import { inject as service } from "@ember/service"; export default Controller.extend(bufferedProperty("emailTemplate"), { adminCustomizeEmailTemplates: controller(), + dialog: service(), emailTemplate: null, saved: false, @@ -42,20 +43,19 @@ export default Controller.extend(bufferedProperty("emailTemplate"), { @action revertChanges() { this.set("saved", false); - bootbox.confirm( - I18n.t("admin.customize.email_templates.revert_confirm"), - (result) => { - if (result) { - this.emailTemplate - .revert() - .then((props) => { - const buffered = this.buffered; - buffered.setProperties(props); - this.commitBuffer(); - }) - .catch(popupAjaxError); - } - } - ); + + this.dialog.yesNoConfirm({ + title: I18n.t("admin.customize.email_templates.revert_confirm"), + didConfirm: () => { + return this.emailTemplate + .revert() + .then((props) => { + const buffered = this.buffered; + buffered.setProperties(props); + this.commitBuffer(); + }) + .catch(popupAjaxError); + }, + }); }, }); 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 61ffda925e..45d1973305 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 @@ -10,7 +10,6 @@ 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 { makeArray } from "discourse-common/lib/helpers"; import { popupAjaxError } from "discourse/lib/ajax-error"; @@ -306,14 +305,10 @@ export default Controller.extend({ editTheme() { if (this.get("model.remote_theme.is_git")) { - bootbox.confirm( - I18n.t("admin.customize.theme.edit_confirm"), - (result) => { - if (result) { - this.transitionToEditRoute(); - } - } - ); + this.dialog.confirm({ + message: I18n.t("admin.customize.theme.edit_confirm"), + didConfirm: () => this.transitionToEditRoute(), + }); } else { this.transitionToEditRoute(); } 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 1500549564..c7a8ec98a6 100644 --- a/app/assets/javascripts/admin/addon/controllers/admin-email-bounced.js +++ b/app/assets/javascripts/admin/addon/controllers/admin-email-bounced.js @@ -2,8 +2,15 @@ import AdminEmailLogsController from "admin/controllers/admin-email-logs"; import { INPUT_DELAY } from "discourse-common/config/environment"; import discourseDebounce from "discourse-common/lib/debounce"; import { observes } from "discourse-common/utils/decorators"; +import { action } from "@ember/object"; export default AdminEmailLogsController.extend({ + @action + handleShowIncomingEmail(id, event) { + event?.preventDefault(); + this.send("showIncomingEmail", id); + }, + @observes("filter.{status,user,address,type}") filterEmailLogs() { discourseDebounce(this, this.loadLogs, INPUT_DELAY); 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 50d74d35d8..84f85eea6d 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,7 +1,7 @@ import { empty, notEmpty, or } from "@ember/object/computed"; import Controller from "@ember/controller"; import EmailPreview from "admin/models/email-preview"; -import { get } from "@ember/object"; +import { action, get } from "@ember/object"; import { popupAjaxError } from "discourse/lib/ajax-error"; import { inject as service } from "@ember/service"; @@ -14,6 +14,12 @@ export default Controller.extend({ showSendEmailForm: notEmpty("model.html_content"), htmlEmpty: empty("model.html_content"), + @action + toggleShowHtml(event) { + event?.preventDefault(); + this.toggleProperty("showHtml"); + }, + actions: { updateUsername(selected) { this.set("username", get(selected, "firstObject")); @@ -39,10 +45,6 @@ export default Controller.extend({ }); }, - toggleShowHtml() { - this.toggleProperty("showHtml"); - }, - sendEmail() { this.set("sendingEmail", true); this.set("sentEmail", false); 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 89c67f3cf9..6e4ce78656 100644 --- a/app/assets/javascripts/admin/addon/controllers/admin-email-rejected.js +++ b/app/assets/javascripts/admin/addon/controllers/admin-email-rejected.js @@ -3,6 +3,7 @@ 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"; +import { action } from "@ember/object"; export default AdminEmailLogsController.extend({ @observes("filter.{status,from,to,subject,error}") @@ -10,6 +11,12 @@ export default AdminEmailLogsController.extend({ discourseDebounce(this, this.loadLogs, IncomingEmail, INPUT_DELAY); }, + @action + handleShowIncomingEmail(id, event) { + event?.preventDefault(); + this.send("showIncomingEmail", id); + }, + actions: { loadMore() { this.loadLogs(IncomingEmail, true); 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 0e8b43f9c1..bc11ec51f4 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 @@ -6,6 +6,7 @@ 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"; +import { action } from "@ember/object"; import { inject as service } from "@ember/service"; export default Controller.extend({ @@ -26,6 +27,15 @@ export default Controller.extend({ discourseDebounce(this, this._debouncedShow, INPUT_DELAY); }, + @action + edit(record, event) { + event?.preventDefault(); + if (!record.get("editing")) { + this.set("savedIpAddress", record.get("ip_address")); + } + record.set("editing", true); + }, + actions: { allow(record) { record.set("action_name", "do_nothing"); @@ -37,13 +47,6 @@ export default Controller.extend({ record.save(); }, - edit(record) { - if (!record.get("editing")) { - this.set("savedIpAddress", record.get("ip_address")); - } - record.set("editing", true); - }, - cancel(record) { const savedIpAddress = this.savedIpAddress; if (savedIpAddress && record.get("editing")) { 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 670d48c17b..11e5324bd6 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,11 @@ import Controller from "@ember/controller"; -import EmberObject from "@ember/object"; +import EmberObject, { action } from "@ember/object"; 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 { scheduleOnce } from "@ember/runloop"; +import showModal from "discourse/lib/show-modal"; export default Controller.extend({ queryParams: ["filters"], @@ -31,11 +32,13 @@ export default Controller.extend({ this.set( "userHistoryActions", result.extras.user_history_actions - .map((action) => ({ - id: action.id, - action_id: action.action_id, - name: I18n.t("admin.logs.staff_actions.actions." + action.id), - name_raw: action.id, + .map((historyAction) => ({ + id: historyAction.id, + action_id: historyAction.action_id, + name: I18n.t( + "admin.logs.staff_actions.actions." + historyAction.id + ), + name_raw: historyAction.id, })) .sort((a, b) => a.name.localeCompare(b.name)) ); @@ -75,61 +78,95 @@ export default Controller.extend({ this.scheduleRefresh(); }, - actions: { - filterActionIdChanged(filterActionId) { - if (filterActionId) { - this.changeFilters({ - action_name: filterActionId, - action_id: this.userHistoryActions.findBy("id", filterActionId) - .action_id, - }); - } - }, - - clearFilter(key) { - if (key === "actionFilter") { - this.set("filterActionId", null); - this.changeFilters({ - action_name: null, - action_id: null, - custom_type: null, - }); - } else { - this.changeFilters({ [key]: null }); - } - }, - - clearAllFilters() { - this.set("filterActionId", null); - this.resetFilters(); - }, - - filterByAction(logItem) { + @action + filterActionIdChanged(filterActionId) { + if (filterActionId) { this.changeFilters({ - action_name: logItem.get("action_name"), - action_id: logItem.get("action"), - custom_type: logItem.get("custom_type"), + action_name: filterActionId, + action_id: this.userHistoryActions.findBy("id", filterActionId) + .action_id, }); - }, + } + }, - filterByStaffUser(acting_user) { - this.changeFilters({ acting_user: acting_user.username }); - }, + @action + clearFilter(key, event) { + event?.preventDefault(); + if (key === "actionFilter") { + this.set("filterActionId", null); + this.changeFilters({ + action_name: null, + action_id: null, + custom_type: null, + }); + } else { + this.changeFilters({ [key]: null }); + } + }, - filterByTargetUser(target_user) { - this.changeFilters({ target_user: target_user.username }); - }, + @action + clearAllFilters(event) { + event?.preventDefault(); + this.set("filterActionId", null); + this.resetFilters(); + }, - filterBySubject(subject) { - this.changeFilters({ subject }); - }, + @action + filterByAction(logItem, event) { + event?.preventDefault(); + this.changeFilters({ + action_name: logItem.get("action_name"), + action_id: logItem.get("action"), + custom_type: logItem.get("custom_type"), + }); + }, - exportStaffActionLogs() { - exportEntity("staff_action").then(outputExportResult); - }, + @action + filterByStaffUser(acting_user, event) { + event?.preventDefault(); + this.changeFilters({ acting_user: acting_user.username }); + }, - loadMore() { - this.model.loadMore(); - }, + @action + filterByTargetUser(target_user, event) { + event?.preventDefault(); + this.changeFilters({ target_user: target_user.username }); + }, + + @action + filterBySubject(subject, event) { + event?.preventDefault(); + this.changeFilters({ subject }); + }, + + @action + exportStaffActionLogs() { + exportEntity("staff_action").then(outputExportResult); + }, + + @action + loadMore() { + this.model.loadMore(); + }, + + @action + showDetailsModal(model, event) { + event?.preventDefault(); + showModal("admin-staff-action-log-details", { + model, + admin: true, + modalClass: "log-details-modal", + }); + }, + + @action + showCustomDetailsModal(model, event) { + event?.preventDefault(); + let modal = showModal("admin-theme-change", { + model, + admin: true, + modalClass: "history-modal", + }); + modal.loadDiff(); }, }); 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 3dbcc3742c..4ee3b0fab9 100644 --- a/app/assets/javascripts/admin/addon/controllers/admin-site-settings.js +++ b/app/assets/javascripts/admin/addon/controllers/admin-site-settings.js @@ -2,9 +2,8 @@ import Controller from "@ember/controller"; 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"; +import { debounce, observes } from "discourse-common/utils/decorators"; import { action } from "@ember/object"; export default Controller.extend({ @@ -113,18 +112,13 @@ export default Controller.extend({ }, @observes("filter", "onlyOverridden", "model") + @debounce(INPUT_DELAY) filterContent() { - discourseDebounce( - this, - () => { - if (this._skipBounce) { - this.set("_skipBounce", false); - } else { - this.filterContentNow(this.categoryNameKey); - } - }, - INPUT_DELAY - ); + if (this._skipBounce) { + this.set("_skipBounce", false); + } else { + this.filterContentNow(this.categoryNameKey); + } }, @action 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 bafcc02937..619c1cf629 100644 --- a/app/assets/javascripts/admin/addon/controllers/admin-user-fields.js +++ b/app/assets/javascripts/admin/addon/controllers/admin-user-fields.js @@ -1,12 +1,13 @@ import { gte, sort } from "@ember/object/computed"; import Controller from "@ember/controller"; import I18n from "I18n"; -import bootbox from "bootbox"; import { popupAjaxError } from "discourse/lib/ajax-error"; +import { inject as service } from "@ember/service"; const MAX_FIELDS = 30; export default Controller.extend({ + dialog: service(), fieldTypes: null, createDisabled: gte("model.length", MAX_FIELDS), sortedFields: sort("model", "fieldSortOrder"), @@ -53,18 +54,17 @@ export default Controller.extend({ // Only confirm if we already been saved if (f.get("id")) { - bootbox.confirm( - I18n.t("admin.user_fields.delete_confirm"), - function (result) { - if (result) { - f.destroyRecord() - .then(function () { - model.removeObject(f); - }) - .catch(popupAjaxError); - } - } - ); + this.dialog.yesNoConfirm({ + message: I18n.t("admin.user_fields.delete_confirm"), + didConfirm: () => { + return f + .destroyRecord() + .then(function () { + model.removeObject(f); + }) + .catch(popupAjaxError); + }, + }); } else { model.removeObject(f); } 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 71990f47a3..84b7650ff1 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,5 +1,6 @@ import Controller from "@ember/controller"; import { ajax } from "discourse/lib/ajax"; +import { action } from "@ember/object"; import { alias } from "@ember/object/computed"; import discourseComputed from "discourse-common/utils/decorators"; import { popupAjaxError } from "discourse/lib/ajax-error"; @@ -43,6 +44,23 @@ export default Controller.extend({ } }, + @action + showInserted(event) { + event?.preventDefault(); + const webHookId = this.get("model.extras.web_hook_id"); + + ajax(`/admin/api/web_hooks/${webHookId}/events/bulk`, { + type: "GET", + data: { ids: this.incomingEventIds }, + }).then((data) => { + const objects = data.map((webHookEvent) => + this.store.createRecord("web-hook-event", webHookEvent) + ); + this.model.unshiftObjects(objects); + this.set("incomingEventIds", []); + }); + }, + actions: { loadMore() { this.model.loadMore(); @@ -61,20 +79,5 @@ export default Controller.extend({ popupAjaxError(error); }); }, - - showInserted() { - const webHookId = this.get("model.extras.web_hook_id"); - - ajax(`/admin/api/web_hooks/${webHookId}/events/bulk`, { - type: "GET", - data: { ids: this.incomingEventIds }, - }).then((data) => { - const objects = data.map((event) => - this.store.createRecord("web-hook-event", event) - ); - this.model.unshiftObjects(objects); - this.set("incomingEventIds", []); - }); - }, }, }); 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 ba75e29199..f1e8caadcf 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 @@ -3,8 +3,6 @@ import EmberObject from "@ember/object"; import I18n from "I18n"; import { alias } from "@ember/object/computed"; 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"; import { inject as service } from "@ember/service"; @@ -89,38 +87,20 @@ export default Controller.extend({ actions: { save() { this.set("saved", false); - const url = this.get("model.payload_url"); - const domain = extractDomainFromUrl(url); const model = this.model; const isNew = model.get("isNew"); - const saveWebHook = () => { - return model - .save() - .then(() => { - this.set("saved", true); - this.adminWebHooks.get("model").addObject(model); + return model + .save() + .then(() => { + this.set("saved", true); + this.adminWebHooks.get("model").addObject(model); - if (isNew) { - this.transitionToRoute("adminWebHooks.show", model.get("id")); - } - }) - .catch(popupAjaxError); - }; - - if ( - domain === "localhost" || - domain.match(/192\.168\.\d+\.\d+/) || - domain.match(/127\.\d+\.\d+\.\d+/) || - isAbsoluteURL(url) - ) { - return this.dialog.yesNoConfirm({ - message: I18n.t("admin.web_hooks.warn_local_payload_url"), - didConfirm: () => saveWebHook(), - }); - } - - return saveWebHook(); + if (isNew) { + this.transitionToRoute("adminWebHooks.show", model.get("id")); + } + }) + .catch(popupAjaxError); }, destroy() { 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 d42446ddbb..a3553d8f7c 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 @@ -31,6 +31,7 @@ export default Controller.extend(ModalFunctionality, { advancedVisible: false, selectedType: alias("themesController.currentTab"), component: equal("selectedType", COMPONENTS), + urlPlaceholder: "https://github.com/discourse/sample_theme", init() { this._super(...arguments); @@ -79,29 +80,6 @@ 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() { - const checked = this.privateChecked; - if (checked && !this._keyLoading) { - this._keyLoading = true; - ajax(this.keyGenUrl, { type: "POST" }) - .then((pair) => { - this.set("publicKey", pair.public_key); - }) - .catch(popupAjaxError) - .finally(() => { - this._keyLoading = false; - }); - } - }, - @discourseComputed("name") nameTooShort(name) { return !name || name.length < MIN_NAME_LENGTH; @@ -116,6 +94,22 @@ export default Controller.extend(ModalFunctionality, { } }, + @observes("checkPrivate") + privateWasChecked() { + const checked = this.checkPrivate; + if (checked && !this._keyLoading && !this.publicKey) { + this._keyLoading = true; + ajax(this.keyGenUrl, { type: "POST" }) + .then((pair) => { + this.set("publicKey", pair.public_key); + }) + .catch(popupAjaxError) + .finally(() => { + this._keyLoading = false; + }); + } + }, + @discourseComputed("selection", "themeCannotBeInstalled") submitLabel(selection, themeCannotBeInstalled) { if (themeCannotBeInstalled) { @@ -127,15 +121,14 @@ export default Controller.extend(ModalFunctionality, { }`; }, - @discourseComputed("privateChecked", "checkPrivate", "publicKey") - showPublicKey(privateChecked, checkPrivate, publicKey) { - return privateChecked && checkPrivate && publicKey; + @discourseComputed("checkPrivate", "publicKey") + showPublicKey(checkPrivate, publicKey) { + return checkPrivate && publicKey; }, onClose() { this.setProperties({ duplicateRemoteThemeWarning: null, - privateChecked: false, localFile: null, uploadUrl: null, publicKey: null, @@ -209,11 +202,8 @@ export default Controller.extend(ModalFunctionality, { options.data = { remote: this.uploadUrl, branch: this.branch, + public_key: this.publicKey, }; - - if (this.privateChecked) { - options.data.public_key = this.publicKey; - } } // User knows that theme cannot be installed, but they want to continue 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 7ab4cb6984..8a60037a5b 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,6 @@ import { observes, on } from "discourse-common/utils/decorators"; import Controller from "@ember/controller"; +import { action } from "@ember/object"; import ModalFunctionality from "discourse/mixins/modal-functionality"; export default Controller.extend(ModalFunctionality, { @@ -10,15 +11,17 @@ export default Controller.extend(ModalFunctionality, { this.set("images", value && value.length ? value.split("|") : []); }, + @action + remove(url, event) { + event?.preventDefault(); + this.images.removeObject(url); + }, + actions: { uploadDone({ url }) { this.images.addObject(url); }, - remove(url) { - this.images.removeObject(url); - }, - close() { this.save(this.images.join("|")); this.send("closeModal"); diff --git a/app/assets/javascripts/admin/addon/mixins/penalty-controller.js b/app/assets/javascripts/admin/addon/mixins/penalty-controller.js index 55514dfe48..eb5d56e8cf 100644 --- a/app/assets/javascripts/admin/addon/mixins/penalty-controller.js +++ b/app/assets/javascripts/admin/addon/mixins/penalty-controller.js @@ -2,11 +2,12 @@ import I18n from "I18n"; import Mixin from "@ember/object/mixin"; 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"; +import { inject as service } from "@ember/service"; export default Mixin.create(ModalFunctionality, { + dialog: service(), errorMessage: null, reason: null, message: null, @@ -40,15 +41,15 @@ export default Mixin.create(ModalFunctionality, { (this.message && this.message.length > 1)) ) { this.send("hideModal"); - bootbox.confirm(I18n.t("admin.user.confirm_cancel_penalty"), (result) => { - if (result) { + this.dialog.confirm({ + message: I18n.t("admin.user.confirm_cancel_penalty"), + didConfirm: () => { next(() => { this.set("confirmClose", true); this.send("closeModal"); }); - } else { - next(() => this.send("reopenModal")); - } + }, + didCancel: () => this.send("reopenModal"), }); return false; } diff --git a/app/assets/javascripts/admin/addon/mixins/setting-component.js b/app/assets/javascripts/admin/addon/mixins/setting-component.js index 3e2fd8f064..d651d1690c 100644 --- a/app/assets/javascripts/admin/addon/mixins/setting-component.js +++ b/app/assets/javascripts/admin/addon/mixins/setting-component.js @@ -157,7 +157,10 @@ export default Mixin.create({ "default_tags_watching_first_post", "default_text_size", "default_title_count_mode", + "default_sidebar_categories", + "default_sidebar_tags", ]; + const key = this.buffered.get("setting"); if (defaultUserPreferences.includes(key)) { diff --git a/app/assets/javascripts/admin/addon/routes/admin-customize-email-style-edit.js b/app/assets/javascripts/admin/addon/routes/admin-customize-email-style-edit.js index 4453dbe672..847b21a75c 100644 --- a/app/assets/javascripts/admin/addon/routes/admin-customize-email-style-edit.js +++ b/app/assets/javascripts/admin/addon/routes/admin-customize-email-style-edit.js @@ -1,8 +1,9 @@ import I18n from "I18n"; import Route from "@ember/routing/route"; -import bootbox from "bootbox"; +import { inject as service } from "@ember/service"; export default Route.extend({ + dialog: service(), model(params) { return { model: this.modelFor("adminCustomizeEmailStyle"), @@ -26,17 +27,15 @@ export default Route.extend({ transition.intent.name !== this.routeName ) { transition.abort(); - bootbox.confirm( - I18n.t("admin.customize.theme.unsaved_changes_alert"), - I18n.t("admin.customize.theme.discard"), - I18n.t("admin.customize.theme.stay"), - (result) => { - if (!result) { - this._shouldAlertUnsavedChanges = false; - transition.retry(); - } - } - ); + this.dialog.confirm({ + message: I18n.t("admin.customize.theme.unsaved_changes_alert"), + confirmButtonLabel: "admin.customize.theme.discard", + cancelButtonLabel: "admin.customize.theme.stay", + didConfirm: () => { + this._shouldAlertUnsavedChanges = false; + transition.retry(); + }, + }); } }, }, 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 0d55baa6ce..c72e9d0731 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 @@ -1,8 +1,10 @@ import I18n from "I18n"; import Route from "@ember/routing/route"; -import bootbox from "bootbox"; +import { inject as service } from "@ember/service"; export default Route.extend({ + dialog: service(), + model(params) { const all = this.modelFor("adminCustomizeThemes"); const model = all.findBy("id", parseInt(params.theme_id, 10)); @@ -56,17 +58,16 @@ export default Route.extend({ transition.intent.name !== this.routeName ) { transition.abort(); - bootbox.confirm( - I18n.t("admin.customize.theme.unsaved_changes_alert"), - I18n.t("admin.customize.theme.discard"), - I18n.t("admin.customize.theme.stay"), - (result) => { - if (!result) { - this.set("shouldAlertUnsavedChanges", false); - transition.retry(); - } - } - ); + + this.dialog.confirm({ + message: I18n.t("admin.customize.theme.unsaved_changes_alert"), + confirmButtonLabel: "admin.customize.theme.discard", + cancelButtonLabel: "admin.customize.theme.stay", + didConfirm: () => { + this.set("shouldAlertUnsavedChanges", false); + transition.retry(); + }, + }); } }, }, 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 6c23a36109..156dbf9dd0 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 @@ -2,23 +2,11 @@ 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 bootbox from "bootbox"; - -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); - } - ); -} +import { inject as service } from "@ember/service"; export default Route.extend({ + dialog: service(), + serialize(model) { return { theme_id: model.get("id") }; }, @@ -72,10 +60,14 @@ export default Route.extend({ const model = this.controller.model; if (model.warnUnassignedComponent) { transition.abort(); - showUnassignedComponentWarning(model, (result) => { - if (!result) { + + this.dialog.yesNoConfirm({ + message: I18n.t("admin.customize.theme.unsaved_parent_themes"), + didConfirm: () => { + model.set("recentlyInstalled", false); transition.retry(); - } + }, + didCancel: () => model.set("recentlyInstalled", false), }); } }, 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 8734675eff..22878ded22 100644 --- a/app/assets/javascripts/admin/addon/routes/admin-customize-themes.js +++ b/app/assets/javascripts/admin/addon/routes/admin-customize-themes.js @@ -1,9 +1,12 @@ import Route from "@ember/routing/route"; import showModal from "discourse/lib/show-modal"; +import I18n from "I18n"; import { next } from "@ember/runloop"; -import { showUnassignedComponentWarning } from "admin/routes/admin-customize-themes-show"; +import { inject as service } from "@ember/service"; export default Route.extend({ + dialog: service(), + queryParams: { repoUrl: null, repoName: null, @@ -35,11 +38,13 @@ export default Route.extend({ const currentTheme = this.controllerFor( "adminCustomizeThemes.show" ).model; - if (currentTheme && currentTheme.warnUnassignedComponent) { - showUnassignedComponentWarning(currentTheme, (result) => { - if (!result) { + if (currentTheme?.warnUnassignedComponent) { + this.dialog.yesNoConfirm({ + message: I18n.t("admin.customize.theme.unsaved_parent_themes"), + didConfirm: () => { + currentTheme.set("recentlyInstalled", false); showModal("admin-install-theme", { admin: true }); - } + }, }); } else { showModal("admin-install-theme", { admin: true }); 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 f643d41e18..c00f1e135c 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,5 @@ import DiscourseRoute from "discourse/routes/discourse"; import EmberObject from "@ember/object"; -import showModal from "discourse/lib/show-modal"; export default DiscourseRoute.extend({ queryParams: { @@ -43,17 +42,6 @@ export default DiscourseRoute.extend({ }, actions: { - showDetailsModal(model) { - showModal("admin-staff-action-log-details", { model, admin: true }); - this.controllerFor("modal").set("modalClass", "log-details-modal"); - }, - - showCustomDetailsModal(model) { - let modal = showModal("admin-theme-change", { model, admin: true }); - this.controllerFor("modal").set("modalClass", "history-modal"); - modal.loadDiff(); - }, - onFiltersChange(filters) { if (filters && Object.keys(filters) === 0) { this.transitionTo("adminLogs.staffActionLogs"); diff --git a/app/assets/javascripts/admin/addon/services/admin-tools.js b/app/assets/javascripts/admin/addon/services/admin-tools.js index 3d06845508..5fce78cb33 100644 --- a/app/assets/javascripts/admin/addon/services/admin-tools.js +++ b/app/assets/javascripts/admin/addon/services/admin-tools.js @@ -3,10 +3,9 @@ import I18n from "I18n"; import { Promise } from "rsvp"; import Service, { inject as 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"; +import { htmlSafe } from "@ember/template"; // 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 @@ -79,58 +78,50 @@ export default Service.extend({ : Promise.resolve(); return tryEmail.then(() => { - let message = I18n.messageFormat("flagging.delete_confirm_MF", { - POSTS: adminUser.get("post_count"), - TOPICS: adminUser.get("topic_count"), - email: - adminUser.get("email") || I18n.t("flagging.hidden_email_address"), - ip_address: - adminUser.get("ip_address") || I18n.t("flagging.ip_address_missing"), - }); + let message = htmlSafe( + I18n.messageFormat("flagging.delete_confirm_MF", { + POSTS: adminUser.get("post_count"), + TOPICS: adminUser.get("topic_count"), + email: + adminUser.get("email") || I18n.t("flagging.hidden_email_address"), + ip_address: + adminUser.get("ip_address") || + I18n.t("flagging.ip_address_missing"), + }) + ); let userId = adminUser.get("id"); return new Promise((resolve, reject) => { - const buttons = [ - { - label: I18n.t("composer.cancel"), - class: "d-modal-cancel", - link: true, - }, - { - label: - `${iconHTML("exclamation-triangle")} ` + - I18n.t("flagging.yes_delete_spammer"), - class: "btn btn-danger confirm-delete", - callback() { - return ajax(`/admin/users/${userId}.json`, { - type: "DELETE", - data: { - delete_posts: true, - block_email: true, - block_urls: true, - block_ip: true, - delete_as_spammer: true, - context: window.location.pathname, - }, + this.dialog.deleteConfirm({ + message, + class: "flagging-delete-spammer", + confirmButtonLabel: "flagging.yes_delete_spammer", + confirmButtonIcon: "exclamation-triangle", + didConfirm: () => { + return ajax(`/admin/users/${userId}.json`, { + type: "DELETE", + data: { + delete_posts: true, + block_email: true, + block_urls: true, + block_ip: true, + delete_as_spammer: true, + context: window.location.pathname, + }, + }) + .then((result) => { + if (result.deleted) { + resolve(); + } else { + throw new Error("failed to delete"); + } }) - .then((result) => { - if (result.deleted) { - resolve(); - } else { - throw new Error("failed to delete"); - } - }) - .catch(() => { - this.dialog.alert(I18n.t("admin.user.delete_failed")); - reject(); - }); - }, + .catch(() => { + this.dialog.alert(I18n.t("admin.user.delete_failed")); + reject(); + }); }, - ]; - - bootbox.dialog(message, buttons, { - classes: "flagging-delete-spammer", }); }); }); diff --git a/app/assets/javascripts/admin/addon/templates/admin-badges/show.hbs b/app/assets/javascripts/admin/addon/templates/admin-badges/show.hbs index 31b16af4cc..82492beecb 100644 --- a/app/assets/javascripts/admin/addon/templates/admin-badges/show.hbs +++ b/app/assets/javascripts/admin/addon/templates/admin-badges/show.hbs @@ -88,9 +88,9 @@ {{#if this.hasQuery}} - {{i18n "admin.badges.preview.link_text"}} + {{i18n "admin.badges.preview.link_text"}} | - {{i18n "admin.badges.preview.plan_text"}} + {{i18n "admin.badges.preview.plan_text"}} {{#if this.preview_loading}} {{i18n "loading"}} {{/if}} diff --git a/app/assets/javascripts/admin/addon/templates/components/admin-editable-field.hbs b/app/assets/javascripts/admin/addon/templates/components/admin-editable-field.hbs index d62cfdbd78..998174f20a 100644 --- a/app/assets/javascripts/admin/addon/templates/components/admin-editable-field.hbs +++ b/app/assets/javascripts/admin/addon/templates/components/admin-editable-field.hbs @@ -3,7 +3,7 @@ {{#if this.editing}} {{else}} - + {{this.value}} {{/if}} @@ -11,7 +11,7 @@
{{#if this.editing}} - {{i18n "cancel"}} + {{i18n "cancel"}} {{else}} {{/if}} diff --git a/app/assets/javascripts/admin/addon/templates/components/admin-theme-editor.hbs b/app/assets/javascripts/admin/addon/templates/components/admin-theme-editor.hbs index ec8ed70f30..a8c33e1da2 100644 --- a/app/assets/javascripts/admin/addon/templates/components/admin-theme-editor.hbs +++ b/app/assets/javascripts/admin/addon/templates/components/admin-theme-editor.hbs @@ -13,7 +13,7 @@ {{#if this.allowAdvanced}}
  • - @@ -52,7 +52,7 @@ {{else}} - + {{d-icon "plus"}} {{/if}} @@ -61,7 +61,7 @@
  • - + {{d-icon this.maximizeIcon}}
  • diff --git a/app/assets/javascripts/admin/addon/templates/components/ip-lookup.hbs b/app/assets/javascripts/admin/addon/templates/components/ip-lookup.hbs index f63ab16730..31ec7f35a7 100644 --- a/app/assets/javascripts/admin/addon/templates/components/ip-lookup.hbs +++ b/app/assets/javascripts/admin/addon/templates/components/ip-lookup.hbs @@ -3,7 +3,7 @@ {{/if}} {{#if this.show}}
    - {{d-icon "times"}} + {{d-icon "times"}} {{#if this.copied}} {{else}} diff --git a/app/assets/javascripts/admin/addon/templates/components/themes-list-item.hbs b/app/assets/javascripts/admin/addon/templates/components/themes-list-item.hbs index 1710a14454..21678c1a43 100644 --- a/app/assets/javascripts/admin/addon/templates/components/themes-list-item.hbs +++ b/app/assets/javascripts/admin/addon/templates/components/themes-list-item.hbs @@ -31,7 +31,7 @@ {{html-safe this.childrenString}} {{#if this.displayHasMore}} - + {{#if this.childrenExpanded}} {{i18n "admin.customize.theme.collapse"}} {{else}} diff --git a/app/assets/javascripts/admin/addon/templates/components/themes-list.hbs b/app/assets/javascripts/admin/addon/templates/components/themes-list.hbs index f71aa9dd52..e7055b7126 100644 --- a/app/assets/javascripts/admin/addon/templates/components/themes-list.hbs +++ b/app/assets/javascripts/admin/addon/templates/components/themes-list.hbs @@ -1,6 +1,6 @@
    - - + +
    diff --git a/app/assets/javascripts/admin/addon/templates/customize-themes-show.hbs b/app/assets/javascripts/admin/addon/templates/customize-themes-show.hbs index 4fe285d33e..4fa8ebe52d 100644 --- a/app/assets/javascripts/admin/addon/templates/customize-themes-show.hbs +++ b/app/assets/javascripts/admin/addon/templates/customize-themes-show.hbs @@ -282,6 +282,7 @@ {{#if this.hasSettings}}
    {{i18n "admin.customize.theme.theme_settings"}}
    +

    {{i18n "admin.customize.theme.overriden_settings_explanation"}}

    {{#each this.settings as |setting|}} diff --git a/app/assets/javascripts/admin/addon/templates/email-bounced.hbs b/app/assets/javascripts/admin/addon/templates/email-bounced.hbs index cf6ceb81bc..6a47751d00 100644 --- a/app/assets/javascripts/admin/addon/templates/email-bounced.hbs +++ b/app/assets/javascripts/admin/addon/templates/email-bounced.hbs @@ -30,7 +30,7 @@
    {{l.to_address}} {{#if l.has_bounce_key}} - + {{l.email_type}} {{else}} @@ -39,7 +39,7 @@ {{#if l.has_bounce_key}} - + {{d-icon "info-circle"}} {{/if}} diff --git a/app/assets/javascripts/admin/addon/templates/email-preview-digest.hbs b/app/assets/javascripts/admin/addon/templates/email-preview-digest.hbs index d2ee4cad4d..b00332840d 100644 --- a/app/assets/javascripts/admin/addon/templates/email-preview-digest.hbs +++ b/app/assets/javascripts/admin/addon/templates/email-preview-digest.hbs @@ -15,11 +15,11 @@ {{#if this.showHtml}} {{i18n "admin.email.html"}} | - + {{i18n "admin.email.text"}} {{else}} - {{i18n "admin.email.html"}} | + {{i18n "admin.email.html"}} | {{i18n "admin.email.text"}} {{/if}}
    diff --git a/app/assets/javascripts/admin/addon/templates/email-rejected.hbs b/app/assets/javascripts/admin/addon/templates/email-rejected.hbs index 21dcbba21d..19033f5f6f 100644 --- a/app/assets/javascripts/admin/addon/templates/email-rejected.hbs +++ b/app/assets/javascripts/admin/addon/templates/email-rejected.hbs @@ -48,10 +48,10 @@ {{email.subject}} - {{email.error}} + {{email.error}} - + {{d-icon "info-circle"}} diff --git a/app/assets/javascripts/admin/addon/templates/logs/screened-ip-addresses.hbs b/app/assets/javascripts/admin/addon/templates/logs/screened-ip-addresses.hbs index 63489dcdee..ab20b2316b 100644 --- a/app/assets/javascripts/admin/addon/templates/logs/screened-ip-addresses.hbs +++ b/app/assets/javascripts/admin/addon/templates/logs/screened-ip-addresses.hbs @@ -27,7 +27,7 @@ {{#if item.editing}} {{else}} - + {{#if item.isRange}} {{item.ip_address}} {{else}} diff --git a/app/assets/javascripts/admin/addon/templates/logs/staff-action-logs.hbs b/app/assets/javascripts/admin/addon/templates/logs/staff-action-logs.hbs index bcee25b439..d2e46867c9 100644 --- a/app/assets/javascripts/admin/addon/templates/logs/staff-action-logs.hbs +++ b/app/assets/javascripts/admin/addon/templates/logs/staff-action-logs.hbs @@ -1,29 +1,29 @@
    {{#if this.filtersExists}} - {{item.actionName}} + {{item.actionName}}
    {{#if item.target_user}} {{avatar item.target_user imageSize="tiny"}} - {{item.target_user.username}} + {{item.target_user.username}} {{/if}} {{#if item.subject}} - {{item.subject}} + {{item.subject}} {{/if}}
    @@ -89,10 +89,10 @@ diff --git a/app/assets/javascripts/admin/addon/templates/modal/admin-install-theme.hbs b/app/assets/javascripts/admin/addon/templates/modal/admin-install-theme.hbs index cebb9a6121..5f0f0c5413 100644 --- a/app/assets/javascripts/admin/addon/templates/modal/admin-install-theme.hbs +++ b/app/assets/javascripts/admin/addon/templates/modal/admin-install-theme.hbs @@ -61,25 +61,15 @@
    {{i18n "admin.customize.theme.remote_branch"}}
    + {{/if}} -
    - -
    - {{#if this.showPublicKey}} -
    -
    {{i18n "admin.customize.theme.public_key"}}
    -
    -