Merge master

This commit is contained in:
Neil Lalonde 2020-11-30 16:41:58 -05:00
commit fef0a0c429
No known key found for this signature in database
GPG Key ID: FF871CA9037D0A91
4826 changed files with 149014 additions and 154659 deletions
.eslintignore.eslintrc.git-blame-ignore-revs
.github
.gitignore.licensed.yml.prettierignore.prettierrc.template-lintrc.js
.tx
DangerfileGemfileGemfile.lockREADME.md
app/assets
images
javascripts

@ -8,10 +8,9 @@ lib/javascripts/locale/
lib/javascripts/messageformat.js
lib/highlight_js/
plugins/**/lib/javascripts/locale
public/javascripts/
public/
vendor/
test/javascripts/test_helper.js
test/javascripts/fixtures
test/javascripts/helpers/assertions.js
app/assets/javascripts/discourse/tests/test_helper.js
app/assets/javascripts/discourse/tests/fixtures
node_modules/
dist/

@ -1,7 +1,18 @@
{
"extends": "eslint-config-discourse",
"plugins": ["discourse-ember"],
"rules": {
"discourse-ember/global-ember": 2
"discourse-ember/global-ember": 2,
"no-duplicate-imports": 2
},
"globals": {
"moduleFor": "off",
"moduleForComponent": "off",
"testStart": "off",
"testDone": "off",
"sinon": "off",
"currentURL": "off",
"invisible": "off",
"visible": "off",
"count": "off",
}
}

@ -28,3 +28,27 @@ c4644c61d97c823b7dd940ffaf0967a104f4b58c
# DEV: Fix indentation for routes.rb
985900818ff985b04def6aa4c5d99c1aa6dbd45c
# Add rubocop to our build.
5012d46cbd3bcf79b7351f7d2d41003496a796c5
# Make rubocop happy again.
ad5082d969ab1f60b5c5b1e89a616117906289f8
# DEV: apply new coding standards (#10592)
52672b9eabccb1184d85dc7f08062d5a7c18cb73
# DEV: apply coding standards to plugins (#10594)
bf88410126f73aab47b7e694e3c5b46453cec1b6
# REFACTOR: Support bundling our `admin` section as an ember addon
ce3fe2f4c4ddf166949ee3cec3d9ecbf9108ab52
# REFACTOR: Move qunit tests to a different directory structure
bc97c79a35d8acd283d4d8b79aa079bce9d127c6
# REFACTOR: Move javascript tests inside discourse app
23f24bfb510edb25b18b6a0d5485270c88df9b24
# DEV: Tidy up imports. (#11364)
1c2358ba162eb9f9ba9095c9afe30cf51dd85e04

38
.github/dependabot.yml vendored Normal file

@ -0,0 +1,38 @@
version: 2
updates:
- package-ecosystem: bundler
directory: "/"
schedule:
interval: daily
time: "08:00"
timezone: Australia/Sydney
open-pull-requests-limit: 10
versioning-strategy: lockfile-only
allow:
- dependency-type: direct
- dependency-type: indirect
ignore:
- dependency-name: aws-partitions
versions:
- "> 1.329.0"
- "< 2"
- dependency-name: aws-sdk-core
versions:
- "> 3.99.1"
- "< 4"
- dependency-name: aws-sdk-kms
versions:
- "> 1.31.0"
- "< 2"
- dependency-name: aws-sdk-s3
versions:
- "> 1.66.0"
- "< 2"
- dependency-name: aws-sdk-sns
versions:
- "> 1.25.1"
- "< 2"
- dependency-name: aws-sigv4
versions:
- "> 1.2.0"
- "< 2"

1
.github/pull_request_template.md vendored Normal file

@ -0,0 +1 @@
<!-- NOTE: All pull requests should have tests (rspec in Ruby, qunit in Javascript). If your code does not include test coverage, please include an explanation of why it was omitted. -->

@ -65,7 +65,7 @@ jobs:
if: env.BUILD_TYPE != 'LINT'
run: |
sudo apt-get update
sudo apt-get -yqq install postgresql-client libpq-dev gifsicle jpegoptim optipng jhead
sudo apt-get -yqq install postgresql-client libpq-dev jpegoptim optipng jhead
wget -qO- https://raw.githubusercontent.com/discourse/discourse_docker/master/image/base/install-pngquant | sudo sh
- name: Update imagemagick
@ -91,9 +91,10 @@ jobs:
gem install bundler -v 2.1.4 --no-doc
bundle config deployment 'true'
bundle config without 'development'
bundle config path vendor/bundle
- name: Bundler cache
uses: actions/cache@v1
uses: actions/cache@v2
id: bundler-cache
with:
path: vendor/bundle
@ -109,7 +110,7 @@ jobs:
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Yarn cache
uses: actions/cache@v1
uses: actions/cache@v2
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir.outputs.dir }}
@ -136,21 +137,56 @@ jobs:
bin/rake parallel:create
bin/rake parallel:migrate
- name: Rubocop
if: env.BUILD_TYPE == 'LINT'
- name: Rubocop (core and core plugins)
if: env.BUILD_TYPE == 'LINT' && env.TARGET == 'CORE'
run: bundle exec rubocop .
- name: ESLint
if: env.BUILD_TYPE == 'LINT'
run: |
yarn eslint app/assets/javascripts test/javascripts
yarn eslint --global I18n --ext .es6 plugins
- name: Rubocop (all plugins)
if: env.BUILD_TYPE == 'LINT' && env.TARGET == 'PLUGINS'
run: bundle exec rubocop plugins
- name: Prettier
if: env.BUILD_TYPE == 'LINT'
- name: ESLint (core)
if: env.BUILD_TYPE == 'LINT' && env.TARGET == 'CORE'
run: yarn eslint --ext .js,.js.es6 --no-error-on-unmatched-pattern app/assets/javascripts
- name: ESLint (core plugins)
if: env.BUILD_TYPE == 'LINT' && env.TARGET == 'CORE'
run: yarn eslint --ext .js,.js.es6 --no-error-on-unmatched-pattern plugins/**/{test,assets}/javascripts
- name: ESLint (all plugins)
if: env.BUILD_TYPE == 'LINT' && env.TARGET == 'PLUGINS'
run: yarn eslint --ext .js,.js.es6 --no-error-on-unmatched-pattern plugins/**/{test,assets}/javascripts
- name: Prettier (core and core plugins)
if: env.BUILD_TYPE == 'LINT' && env.TARGET == 'CORE'
run: |
yarn prettier -v
yarn prettier --list-different "app/assets/stylesheets/**/*.scss" "app/assets/javascripts/**/*.js" "app/assets/javascripts/**/*.es6" "test/javascripts/**/*.es6" "plugins/**/*.scss" "plugins/**/*.es6"
yarn prettier --list-different \
"app/assets/stylesheets/**/*.scss" \
"app/assets/javascripts/**/*.{js,es6}" \
"plugins/**/assets/stylesheets/**/*.scss" \
"plugins/**/assets/javascripts/**/*.{js,es6}"
- name: Prettier (all plugins)
if: env.BUILD_TYPE == 'LINT' && env.TARGET == 'PLUGINS'
run: |
yarn prettier -v
yarn prettier --list-different \
"plugins/**/assets/stylesheets/**/*.scss" \
"plugins/**/assets/javascripts/**/*.{js,es6}"
- name: Ember template lint (core and core plugins)
if: env.BUILD_TYPE == 'LINT' && env.TARGET == 'CORE'
run: |
yarn ember-template-lint \
app/assets/javascripts \
plugins/**/assets/javascripts
- name: Ember template lint (all plugins)
if: env.BUILD_TYPE == 'LINT' && env.TARGET == 'PLUGINS'
run: |
yarn ember-template-lint \
plugins/**/assets/javascripts
- name: Core English locale
if: env.BUILD_TYPE == 'LINT' && env.TARGET == 'CORE'

11
.gitignore vendored

@ -53,8 +53,8 @@ bootsnap-compile-cache/
!/plugins/discourse-nginx-performance-report
!/plugins/discourse-narrative-bot
!/plugins/discourse-presence
!/plugins/styleguide
!/plugins/discourse-local-dates
!/plugins/discourse-unsupported-browser
/plugins/*/auto_generated/
/spec/fixtures/plugins/my_plugin/auto_generated
@ -88,6 +88,7 @@ config/multisite.yml
config/multisite1.yml
config/fog_credentials.yml
/public/fonts
/public/uploads
/public/backups
/public/stylesheet-cache/*
@ -136,8 +137,16 @@ node_modules
# ignore generated api documentation files
openapi/*
# ignore VSCode config files
.vscode
# ignore direnv
.envrc
# ember-cli generated
dist
# Copyright Deposits
copyright
yarn-error.log

12
.licensed.yml Normal file

@ -0,0 +1,12 @@
sources:
yarn: true
bundler: true
allowed:
- mit
- apache-2.0
- bsd-2-clause
- bsd-3-clause
- cc0-1.0
- isc
- other
- none

@ -1,6 +1,25 @@
app/assets/stylesheets/vendor/
plugins/**/assets/stylesheets/vendor/
plugins/**/assets/javascripts/vendor/
package.json
config/locales/**/*.yml
!config/locales/**/*.en*.yml
script/import_scripts/**/*.yml
app/assets/javascripts/env.js
app/assets/javascripts/main_include_admin.js
app/assets/javascripts/vendor.js
app/assets/javascripts/locales/i18n.js
app/assets/javascripts/ember-addons/
app/assets/javascripts/discourse/lib/autosize.js
lib/javascripts/locale/
lib/javascripts/messageformat.js
lib/highlight_js/
plugins/**/lib/javascripts/locale
public/
vendor/
app/assets/javascripts/discourse/tests/test_helper.js
app/assets/javascripts/discourse/tests/fixtures
node_modules/
dist/
**/*.rb

1
.prettierrc Normal file

@ -0,0 +1 @@
{}

@ -50,6 +50,6 @@ module.exports = {
"simple-unless": true,
"style-concatenation": true,
"table-groups": true,
"link-href-attributes": false
}
"link-href-attributes": false,
},
};

@ -1,99 +0,0 @@
[main]
host = https://www.transifex.com
lang_map = el_GR: el, es_ES: es, fr_FR: fr, hu_HU: hu, ko_KR: ko, pt_PT: pt, sk_SK: sk, vi_VN: vi
[discourse-org.core-client-yml]
file_filter = config/locales/client.<lang>.yml
source_file = config/locales/client.en.yml
source_lang = en
type = YML
[discourse-org.core-server-yml]
file_filter = config/locales/server.<lang>.yml
source_file = config/locales/server.en.yml
source_lang = en
type = YML
[discourse-org.pollclientenyml]
file_filter = plugins/poll/config/locales/client.<lang>.yml
source_file = plugins/poll/config/locales/client.en.yml
source_lang = en
type = YML
[discourse-org.pollserverenyml]
file_filter = plugins/poll/config/locales/server.<lang>.yml
source_file = plugins/poll/config/locales/server.en.yml
source_lang = en
type = YML
[discourse-org.narrativeclientenyml]
file_filter = plugins/discourse-narrative-bot/config/locales/client.<lang>.yml
source_file = plugins/discourse-narrative-bot/config/locales/client.en.yml
source_lang = en
type = YML
[discourse-org.narrativeserverenyml]
file_filter = plugins/discourse-narrative-bot/config/locales/server.<lang>.yml
source_file = plugins/discourse-narrative-bot/config/locales/server.en.yml
source_lang = en
type = YML
[discourse-org.discourse-presenceclientenyml]
file_filter = plugins/discourse-presence/config/locales/client.<lang>.yml
source_file = plugins/discourse-presence/config/locales/client.en.yml
source_lang = en
type = YML
[discourse-org.discourse-presenceserverenyml]
file_filter = plugins/discourse-presence/config/locales/server.<lang>.yml
source_file = plugins/discourse-presence/config/locales/server.en.yml
source_lang = en
type = YML
[discourse-org.coreplugindetailsclientyml]
file_filter = plugins/discourse-details/config/locales/client.<lang>.yml
source_file = plugins/discourse-details/config/locales/client.en.yml
source_lang = en
type = YML
[discourse-org.coreplugindetailsserveryml]
file_filter = plugins/discourse-details/config/locales/server.<lang>.yml
source_file = plugins/discourse-details/config/locales/server.en.yml
source_lang = en
type = YML
[discourse-org.core-plugin-local-dates-client-yml]
file_filter = plugins/discourse-local-dates/config/locales/client.<lang>.yml
source_file = plugins/discourse-local-dates/config/locales/client.en.yml
source_lang = en
type = YML
[discourse-org.core-plugin-local-dates-server-yml]
file_filter = plugins/discourse-local-dates/config/locales/server.<lang>.yml
source_file = plugins/discourse-local-dates/config/locales/server.en.yml
source_lang = en
type = YML
[discourse-org.403html]
file_filter = public/403.<lang>.html
source_file = public/403.html
source_lang = en
type = HTML
[discourse-org.422html]
file_filter = public/422.<lang>.html
source_file = public/422.html
source_lang = en
type = HTML
[discourse-org.500html]
file_filter = public/500.<lang>.html
source_file = public/500.html
source_lang = en
type = HTML
[discourse-org.503html]
file_filter = public/503.<lang>.html
source_file = public/503.html
source_lang = en
type = HTML

@ -17,7 +17,7 @@ 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 [Transifex](https://www.transifex.com/discourse/discourse-org/). You can read more on how to contribute translations [here](https://meta.discourse.org/t/contribute-a-translation-to-discourse/14882).")
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)

39
Gemfile

@ -18,13 +18,13 @@ else
# this allows us to include the bits of rails we use without pieces we do not.
#
# To issue a rails update bump the version number here
gem 'actionmailer', '6.0.3.1'
gem 'actionpack', '6.0.3.1'
gem 'actionview', '6.0.3.1'
gem 'activemodel', '6.0.3.1'
gem 'activerecord', '6.0.3.1'
gem 'activesupport', '6.0.3.1'
gem 'railties', '6.0.3.1'
gem 'actionmailer', '6.0.3.3'
gem 'actionpack', '6.0.3.3'
gem 'actionview', '6.0.3.3'
gem 'activemodel', '6.0.3.3'
gem 'activerecord', '6.0.3.3'
gem 'activesupport', '6.0.3.3'
gem 'railties', '6.0.3.3'
gem 'sprockets-rails'
end
@ -66,9 +66,10 @@ gem 'http_accept_language', require: false
# Ember related gems need to be pinned cause they control client side
# behavior, we will push these versions up when upgrading ember
gem 'ember-rails', '0.18.5'
gem 'discourse-ember-rails', '0.18.6', require: 'ember-rails'
gem 'discourse-ember-source', '~> 3.12.2'
gem 'ember-handlebars-template', '0.8.0'
gem 'discourse-fonts'
gem 'barber'
@ -76,10 +77,9 @@ gem 'message_bus'
gem 'rails_multisite'
gem 'fast_xs', platform: :mri
gem 'fast_xs', platform: :ruby
# may move to xorcist post: https://github.com/fny/xorcist/issues/4
gem 'fast_xor', platform: :mri
gem 'xorcist'
gem 'fastimage'
@ -101,7 +101,6 @@ gem 'css_parser', require: false
gem 'omniauth'
gem 'omniauth-facebook'
gem 'omniauth-twitter'
gem 'omniauth-instagram'
gem 'omniauth-github'
gem 'omniauth-oauth2', require: false
@ -125,10 +124,9 @@ gem 'mini_scheduler'
gem 'execjs', require: false
gem 'mini_racer'
# TODO: determine why highline is being held back and upgrade to latest
gem 'highline', '~> 1.7.0', require: false
gem 'highline', require: false
gem 'rack', '2.2.2'
gem 'rack'
gem 'rack-protection' # security
gem 'cbor', require: false
@ -160,10 +158,6 @@ group :test, :development do
gem 'rb-fsevent', require: RUBY_PLATFORM =~ /darwin/i ? 'rb-fsevent' : false
# TODO determine if we can update this to 0.10, API changes happened
# we would like to upgrade it if possible
gem 'rb-inotify', '~> 0.9', require: RUBY_PLATFORM =~ /linux/i ? 'rb-inotify' : false
gem 'rspec-rails'
gem 'shoulda-matchers', require: false
@ -187,7 +181,7 @@ end
# this is an optional gem, it provides a high performance replacement
# to String#blank? a method that is called quite frequently in current
# ActiveRecord, this may change in the future
gem 'fast_blank', platform: :mri
gem 'fast_blank', platform: :ruby
# this provides a very efficient lru cache
gem 'lru_redux'
@ -201,7 +195,7 @@ gem 'htmlentities', require: false
gem 'flamegraph', require: false
gem 'rack-mini-profiler', require: ['enable_rails_patches']
gem 'unicorn', require: false, platform: :mri
gem 'unicorn', require: false, platform: :ruby
gem 'puma', require: false
gem 'rbtrace', require: false, platform: :mri
gem 'gc_tracer', require: false, platform: :mri
@ -225,6 +219,7 @@ gem 'sassc', '2.0.1', require: false
gem "sassc-rails"
gem 'rotp', require: false
gem 'rqrcode'
gem 'rubyzip', require: false
@ -232,7 +227,7 @@ gem 'rubyzip', require: false
gem 'sshkey', require: false
gem 'rchardet', require: false
gem 'lz4-ruby', require: false, platform: :mri
gem 'lz4-ruby', require: false, platform: :ruby
if ENV["IMPORT"] == "1"
gem 'mysql2'

@ -1,38 +1,38 @@
GEM
remote: https://rubygems.org/
specs:
actionmailer (6.0.3.1)
actionpack (= 6.0.3.1)
actionview (= 6.0.3.1)
activejob (= 6.0.3.1)
actionmailer (6.0.3.3)
actionpack (= 6.0.3.3)
actionview (= 6.0.3.3)
activejob (= 6.0.3.3)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (6.0.3.1)
actionview (= 6.0.3.1)
activesupport (= 6.0.3.1)
actionpack (6.0.3.3)
actionview (= 6.0.3.3)
activesupport (= 6.0.3.3)
rack (~> 2.0, >= 2.0.8)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actionview (6.0.3.1)
activesupport (= 6.0.3.1)
actionview (6.0.3.3)
activesupport (= 6.0.3.3)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
actionview_precompiler (0.2.2)
actionview_precompiler (0.2.3)
actionview (>= 6.0.a)
active_model_serializers (0.8.4)
activemodel (>= 3.0)
activejob (6.0.3.1)
activesupport (= 6.0.3.1)
activejob (6.0.3.3)
activesupport (= 6.0.3.3)
globalid (>= 0.3.6)
activemodel (6.0.3.1)
activesupport (= 6.0.3.1)
activerecord (6.0.3.1)
activemodel (= 6.0.3.1)
activesupport (= 6.0.3.1)
activesupport (6.0.3.1)
activemodel (6.0.3.3)
activesupport (= 6.0.3.3)
activerecord (6.0.3.3)
activemodel (= 6.0.3.3)
activesupport (= 6.0.3.3)
activesupport (6.0.3.3)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
@ -45,34 +45,34 @@ GEM
rake (>= 10.4, < 14.0)
ast (2.4.1)
aws-eventstream (1.1.0)
aws-partitions (1.329.0)
aws-sdk-core (3.99.1)
aws-partitions (1.390.0)
aws-sdk-core (3.109.2)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.239.0)
aws-sigv4 (~> 1.1)
jmespath (~> 1.0)
aws-sdk-kms (1.31.0)
aws-sdk-core (~> 3, >= 3.71.0)
aws-sdk-kms (1.39.0)
aws-sdk-core (~> 3, >= 3.109.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.66.0)
aws-sdk-core (~> 3, >= 3.96.1)
aws-sdk-s3 (1.83.2)
aws-sdk-core (~> 3, >= 3.109.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.1)
aws-sdk-sns (1.25.1)
aws-sdk-core (~> 3, >= 3.99.0)
aws-sdk-sns (1.35.0)
aws-sdk-core (~> 3, >= 3.109.0)
aws-sigv4 (~> 1.1)
aws-sigv4 (1.2.0)
aws-sigv4 (1.2.2)
aws-eventstream (~> 1, >= 1.0.2)
barber (0.12.2)
ember-source (>= 1.0, < 3.1)
execjs (>= 1.2, < 3)
better_errors (2.7.1)
better_errors (2.9.1)
coderay (>= 1.0.0)
erubi (>= 1.0.0)
rack (>= 0.9.0)
binding_of_caller (0.8.0)
debug_inspector (>= 0.0.1)
bootsnap (1.4.6)
bootsnap (1.5.1)
msgpack (~> 1.0)
builder (3.2.4)
bullet (6.1.0)
@ -81,24 +81,31 @@ GEM
byebug (11.1.3)
cbor (0.5.9.6)
certified (1.0.0)
chunky_png (1.3.11)
chunky_png (1.3.14)
coderay (1.1.3)
colored2 (3.1.2)
concurrent-ruby (1.1.6)
concurrent-ruby (1.1.7)
connection_pool (2.2.3)
cose (1.0.0)
cose (1.2.0)
cbor (~> 0.5.9)
openssl-signature_algorithm (~> 0.4.0)
openssl-signature_algorithm (~> 1.0)
cppjieba_rb (0.3.3)
crack (0.4.3)
safe_yaml (~> 1.0.0)
crack (0.4.4)
crass (1.0.6)
css_parser (1.7.1)
addressable
debug_inspector (0.0.3)
diff-lcs (1.4.1)
diffy (3.3.0)
discourse-ember-source (3.12.2.0)
diff-lcs (1.4.4)
diffy (3.4.0)
discourse-ember-rails (0.18.6)
active_model_serializers
ember-data-source (>= 1.0.0.beta.5)
ember-handlebars-template (>= 0.1.1, < 1.0)
ember-source (>= 1.1.0)
jquery-rails (>= 1.0.17)
railties (>= 3.1)
discourse-ember-source (3.12.2.2)
discourse-fonts (0.0.5)
discourse_image_optim (0.26.2)
exifr (~> 1.2, >= 1.2.2)
fspath (~> 3.0)
@ -112,28 +119,19 @@ GEM
ember-handlebars-template (0.8.0)
barber (>= 0.11.0)
sprockets (>= 3.3, < 4.1)
ember-rails (0.18.5)
active_model_serializers
ember-data-source (>= 1.0.0.beta.5)
ember-handlebars-template (>= 0.1.1, < 1.0)
ember-source (>= 1.1.0)
jquery-rails (>= 1.0.17)
railties (>= 3.1)
ember-source (2.18.2)
erubi (1.9.0)
excon (0.75.0)
erubi (1.10.0)
excon (0.78.0)
execjs (2.7.0)
exifr (1.3.6)
exifr (1.3.9)
fabrication (2.21.1)
fakeweb (1.3.0)
faraday (1.0.1)
faraday (1.1.0)
multipart-post (>= 1.2, < 3)
ruby2_keywords
fast_blank (1.0.0)
fast_xor (1.1.3)
rake
rake-compiler
fast_xs (0.8.0)
fastimage (2.1.7)
fastimage (2.2.0)
ffi (1.13.1)
flamegraph (0.9.5)
fspath (3.1.2)
@ -143,11 +141,11 @@ GEM
guess_html_encoding (0.0.11)
hashdiff (1.0.1)
hashie (4.1.0)
highline (1.7.10)
highline (2.0.3)
hkdf (0.3.0)
htmlentities (4.3.4)
http_accept_language (2.1.1)
i18n (1.8.3)
i18n (1.8.5)
concurrent-ruby (~> 1.0)
image_size (1.5.0)
in_threads (1.5.4)
@ -156,13 +154,13 @@ GEM
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.3.0)
json (2.3.1)
json-schema (2.8.1)
addressable (>= 2.4)
jwt (2.2.1)
jwt (2.2.2)
kgio (2.11.3)
libv8 (8.4.255.0)
listen (3.2.1)
listen (3.3.1)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
lograge (0.11.2)
@ -173,8 +171,8 @@ GEM
logstash-event (1.2.02)
logstash-logger (0.26.1)
logstash-event (~> 1.2)
logster (2.9.0)
loofah (2.6.0)
logster (2.9.4)
loofah (2.8.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
lru_redux (1.1.0)
@ -183,28 +181,28 @@ GEM
mini_mime (>= 0.1.1)
maxminddb (0.1.22)
memory_profiler (0.9.14)
message_bus (3.3.1)
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_racer (0.3.1)
libv8 (~> 8.4.255)
mini_scheduler (0.12.2)
mini_scheduler (0.12.3)
sidekiq
mini_sql (0.2.5)
mini_sql (0.3)
mini_suffix (0.3.0)
ffi (~> 1.9)
minitest (5.14.1)
minitest (5.14.2)
mocha (1.11.2)
mock_redis (0.24.0)
mock_redis (0.26.0)
msgpack (1.3.3)
multi_json (1.14.1)
multi_json (1.15.0)
multi_xml (0.6.0)
multipart-post (2.1.1)
mustache (1.1.1)
nio4r (2.5.2)
nokogiri (1.10.9)
nio4r (2.5.4)
nokogiri (1.10.10)
mini_portile2 (~> 2.4.0)
nokogumbo (2.0.2)
nokogiri (~> 1.8, >= 1.8.4)
@ -215,11 +213,11 @@ GEM
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
oj (3.10.6)
oj (3.10.16)
omniauth (1.9.1)
hashie (>= 3.4.6)
rack (>= 1.6.2, < 3)
omniauth-facebook (6.0.0)
omniauth-facebook (8.0.0)
omniauth-oauth2 (~> 1.2)
omniauth-github (1.4.0)
omniauth (~> 1.5)
@ -228,31 +226,28 @@ GEM
jwt (>= 2.0)
omniauth (>= 1.1.1)
omniauth-oauth2 (>= 1.6)
omniauth-instagram (1.3.0)
omniauth (~> 1)
omniauth-oauth2 (~> 1)
omniauth-oauth (1.1.0)
oauth
omniauth (~> 1.0)
omniauth-oauth2 (1.6.0)
oauth2 (~> 1.1)
omniauth-oauth2 (1.7.0)
oauth2 (~> 1.4)
omniauth (~> 1.9)
omniauth-twitter (1.4.0)
omniauth-oauth (~> 1.1)
rack
onebox (1.9.29)
onebox (2.1.7)
addressable (~> 2.7.0)
htmlentities (~> 4.3)
multi_json (~> 1.11)
mustache
nokogiri (~> 1.7)
sanitize
openssl-signature_algorithm (0.4.0)
openssl-signature_algorithm (1.0.0)
optimist (3.0.1)
parallel (1.19.2)
parallel_tests (3.0.0)
parallel (1.20.1)
parallel_tests (3.4.0)
parallel
parser (2.7.1.4)
parser (2.7.2.0)
ast (~> 2.4.1)
pg (1.2.3)
progress (3.5.2)
@ -264,14 +259,14 @@ GEM
pry (~> 0.13.0)
pry-rails (0.3.9)
pry (>= 0.10.4)
public_suffix (4.0.5)
puma (4.3.5)
public_suffix (4.0.6)
puma (5.0.4)
nio4r (~> 2.0)
r2 (0.2.7)
rack (2.2.2)
rack-mini-profiler (2.0.2)
rack (2.2.3)
rack-mini-profiler (2.2.0)
rack (>= 1.2.0)
rack-protection (2.0.8.1)
rack-protection (2.1.0)
rack
rack-test (1.1.0)
rack (>= 1.0, < 3)
@ -280,60 +275,58 @@ GEM
nokogiri (>= 1.6)
rails-html-sanitizer (1.3.0)
loofah (~> 2.3)
rails_failover (0.5.5)
rails_failover (0.6.2)
activerecord (~> 6.0)
concurrent-ruby
railties (~> 6.0)
rails_multisite (2.3.0)
rails_multisite (2.5.0)
activerecord (> 5.0, < 7)
railties (> 5.0, < 7)
railties (6.0.3.1)
actionpack (= 6.0.3.1)
activesupport (= 6.0.3.1)
railties (6.0.3.3)
actionpack (= 6.0.3.3)
activesupport (= 6.0.3.3)
method_source
rake (>= 0.8.7)
thor (>= 0.20.3, < 2.0)
rainbow (3.0.0)
raindrops (0.19.1)
rake (13.0.1)
rake-compiler (1.1.0)
rake
rb-fsevent (0.10.4)
rb-inotify (0.10.1)
ffi (~> 1.0)
rbtrace (0.4.13)
rbtrace (0.4.14)
ffi (>= 1.0.6)
msgpack (>= 0.4.3)
optimist (>= 3.0.0)
rchardet (1.8.0)
redis (4.2.1)
redis-namespace (1.7.0)
redis (4.2.5)
redis-namespace (1.8.0)
redis (>= 3.0.4)
regexp_parser (1.7.1)
regexp_parser (2.0.0)
request_store (1.5.0)
rack (>= 1.4)
rexml (3.2.4)
rinku (2.0.6)
rotp (5.1.0)
addressable (~> 2.5)
rotp (6.2.0)
rqrcode (1.1.2)
chunky_png (~> 1.0)
rqrcode_core (~> 0.1)
rqrcode_core (0.1.2)
rspec (3.9.0)
rspec-core (~> 3.9.0)
rspec-expectations (~> 3.9.0)
rspec-mocks (~> 3.9.0)
rspec-core (3.9.2)
rspec-support (~> 3.9.3)
rspec-expectations (3.9.2)
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-support (~> 3.10.0)
rspec-expectations (3.10.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
rspec-html-matchers (0.9.2)
rspec-support (~> 3.10.0)
rspec-html-matchers (0.9.4)
nokogiri (~> 1)
rspec (>= 3.0.0.a, < 4)
rspec-mocks (3.9.1)
rspec-mocks (3.10.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
rspec-support (~> 3.10.0)
rspec-rails (4.0.1)
actionpack (>= 4.2)
activesupport (>= 4.2)
@ -342,35 +335,36 @@ GEM
rspec-expectations (~> 3.9)
rspec-mocks (~> 3.9)
rspec-support (~> 3.9)
rspec-support (3.9.3)
rspec-support (3.10.0)
rswag-specs (2.3.1)
activesupport (>= 3.1, < 7.0)
json-schema (~> 2.2)
railties (>= 3.1, < 7.0)
rtlit (0.0.5)
rubocop (0.86.0)
rubocop (1.4.2)
parallel (~> 1.10)
parser (>= 2.7.0.1)
parser (>= 2.7.1.5)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.7)
regexp_parser (>= 1.8)
rexml
rubocop-ast (>= 0.0.3, < 1.0)
rubocop-ast (>= 1.1.1)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 2.0)
rubocop-ast (0.0.3)
parser (>= 2.7.0.1)
rubocop-discourse (2.2.0)
rubocop (>= 0.69.0)
rubocop-rspec (>= 1.39.0)
rubocop-rspec (1.40.0)
rubocop (>= 0.68.1)
ruby-prof (1.4.1)
rubocop-ast (1.2.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 (~> 1.0)
rubocop-ast (>= 1.1.0)
ruby-prof (1.4.2)
ruby-progressbar (1.10.1)
ruby-readability (0.7.0)
guess_html_encoding (>= 0.0.4)
nokogiri (>= 1.6.0)
ruby2_keywords (0.0.2)
rubyzip (2.3.0)
safe_yaml (1.0.5)
sanitize (5.2.1)
crass (~> 1.0.2)
nokogiri (>= 1.8.0)
@ -387,31 +381,32 @@ GEM
seed-fu (2.3.9)
activerecord (>= 3.1)
activesupport (>= 3.1)
shoulda-matchers (4.3.0)
shoulda-matchers (4.4.1)
activesupport (>= 4.2.0)
sidekiq (6.0.7)
sidekiq (6.1.2)
connection_pool (>= 2.2.2)
rack (~> 2.0)
rack-protection (>= 2.0.0)
redis (>= 4.1.0)
simplecov (0.18.5)
redis (>= 4.2.0)
simplecov (0.20.0)
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov-html (0.12.2)
simplecov_json_formatter (~> 0.1)
simplecov-html (0.12.3)
simplecov_json_formatter (0.1.2)
sprockets (3.7.2)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.2.1)
sprockets-rails (3.2.2)
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sshkey (2.0.0)
stackprof (0.2.15)
test-prof (0.11.3)
stackprof (0.2.16)
test-prof (0.12.2)
thor (1.0.1)
thread_safe (0.3.6)
tilt (2.0.10)
tzinfo (1.2.7)
tzinfo (1.2.8)
thread_safe (~> 0.1)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
@ -419,32 +414,33 @@ GEM
unf_ext
unf_ext (0.0.7.7)
unicode-display_width (1.7.0)
unicorn (5.5.5)
unicorn (5.7.0)
kgio (~> 2.6)
raindrops (~> 0.7)
uniform_notifier (1.13.0)
webmock (3.8.3)
webmock (3.10.0)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
webpush (1.0.0)
webpush (1.1.0)
hkdf (~> 0.2)
jwt (~> 2.0)
xorcist (1.1.2)
yaml-lint (0.0.10)
zeitwerk (2.3.0)
zeitwerk (2.4.1)
PLATFORMS
ruby
DEPENDENCIES
actionmailer (= 6.0.3.1)
actionpack (= 6.0.3.1)
actionview (= 6.0.3.1)
actionmailer (= 6.0.3.3)
actionpack (= 6.0.3.3)
actionview (= 6.0.3.3)
actionview_precompiler
active_model_serializers (~> 0.8.3)
activemodel (= 6.0.3.1)
activerecord (= 6.0.3.1)
activesupport (= 6.0.3.1)
activemodel (= 6.0.3.3)
activerecord (= 6.0.3.3)
activesupport (= 6.0.3.3)
addressable
annotate
aws-sdk-s3
@ -462,22 +458,22 @@ DEPENDENCIES
cppjieba_rb
css_parser
diffy
discourse-ember-rails (= 0.18.6)
discourse-ember-source (~> 3.12.2)
discourse-fonts
discourse_image_optim
email_reply_trimmer
ember-handlebars-template (= 0.8.0)
ember-rails (= 0.18.5)
excon
execjs
fabrication
fakeweb
fast_blank
fast_xor
fast_xs
fastimage
flamegraph
gc_tracer
highline (~> 1.7.0)
highline
htmlentities
http_accept_language
json
@ -508,7 +504,6 @@ DEPENDENCIES
omniauth-facebook
omniauth-github
omniauth-google-oauth2
omniauth-instagram
omniauth-oauth2
omniauth-twitter
onebox
@ -518,15 +513,14 @@ DEPENDENCIES
pry-rails
puma
r2
rack (= 2.2.2)
rack
rack-mini-profiler
rack-protection
rails_failover
rails_multisite
railties (= 6.0.3.1)
railties (= 6.0.3.3)
rake
rb-fsevent
rb-inotify (~> 0.9)
rbtrace
rchardet
redis
@ -560,6 +554,7 @@ DEPENDENCIES
unicorn
webmock
webpush
xorcist
yaml-lint
BUNDLED WITH

@ -17,8 +17,9 @@ To learn more about the philosophy and goals of the project, [visit **discourse.
<a href="https://bbs.boingboing.net"><img alt="Boing Boing" src="https://user-images.githubusercontent.com/1681963/52239245-04ad8280-289c-11e9-9c88-8c173d4a0422.png" width="720px"></a>
<a href="https://twittercommunity.com/"><img src="https://user-images.githubusercontent.com/1681963/52239250-04ad8280-289c-11e9-9e42-574f6eaab9d7.png" width="720px"></a>
<a href="https://discuss.howtogeek.com"><img src="https://user-images.githubusercontent.com/1681963/52239247-04ad8280-289c-11e9-9706-fd66bc0749dc.png" width="720px"></a>
<a href="https://talk.turtlerockstudios.com/"><img src="https://user-images.githubusercontent.com/1681963/52239249-04ad8280-289c-11e9-9155-f0ccc5decc50.png" width="720px"></a>
<a href="https://discuss.atom.io/"><img src="https://user-images.githubusercontent.com/1681963/89088039-6735f080-d364-11ea-93a6-5629ea8738fe.png" width="720px"></a>
<a href="https://forums.gearboxsoftware.com/"><img src="https://user-images.githubusercontent.com/1681963/89088042-68ffb400-d364-11ea-93be-161ea04d8b29.png" width="720px"></a>
<img src="https://user-images.githubusercontent.com/1681963/52239118-b304f800-289b-11e9-9904-16450680d9ec.jpg" alt="Mobile" width="414">
@ -61,6 +62,7 @@ Discourse supports the **latest, stable releases** of all major browsers and pla
- [Ember.js](https://github.com/emberjs/ember.js) &mdash; Our front end is an Ember.js app that communicates with the Rails API.
- [PostgreSQL](https://www.postgresql.org/) &mdash; Our main data store is in Postgres.
- [Redis](https://redis.io/) &mdash; We use Redis as a cache and for transient data.
- [BrowserStack](https://www.browserstack.com/) &mdash; We use BrowserStack to test on real devices and browsers.
Plus *lots* of Ruby Gems, a complete list of which is at [/master/Gemfile](https://github.com/discourse/discourse/blob/master/Gemfile).
@ -90,7 +92,6 @@ We take security very seriously at Discourse; all our code is 100% open source a
The original Discourse code contributors can be found in [**AUTHORS.MD**](docs/AUTHORS.md). For a complete list of the many individuals that contributed to the design and implementation of Discourse, please refer to [the official Discourse blog](https://blog.discourse.org/2013/02/the-discourse-team/) and [GitHub's list of contributors](https://github.com/discourse/discourse/contributors).
## Copyright / License
Copyright 2014 - 2020 Civilized Discourse Construction Kit, Inc.

Binary file not shown.

Before

(image error) Size: 2.9 KiB

After

(image error) Size: 2.4 KiB

Binary file not shown.

Before

(image error) Size: 1.5 KiB

After

(image error) Size: 1.5 KiB

Binary file not shown.

Before

(image error) Size: 4.4 KiB

After

(image error) Size: 2.8 KiB

Binary file not shown.

Before

(image error) Size: 3.5 KiB

After

(image error) Size: 3.1 KiB

Binary file not shown.

Before

(image error) Size: 3.7 KiB

After

(image error) Size: 3.0 KiB

Binary file not shown.

Before

(image error) Size: 1.4 KiB

After

(image error) Size: 1.4 KiB

Binary file not shown.

Before

(image error) Size: 882 B

After

(image error) Size: 810 B

Binary file not shown.

Before

(image error) Size: 1.8 KiB

After

(image error) Size: 1.6 KiB

Binary file not shown.

Before

(image error) Size: 1.0 KiB

After

(image error) Size: 937 B

Binary file not shown.

Before

(image error) Size: 984 B

After

(image error) Size: 898 B

Binary file not shown.

Before

(image error) Size: 895 B

After

(image error) Size: 822 B

Binary file not shown.

Before

(image error) Size: 4.7 KiB

After

(image error) Size: 2.5 KiB

Binary file not shown.

Before

(image error) Size: 24 KiB

After

(image error) Size: 22 KiB

Binary file not shown.

Before

(image error) Size: 3.5 KiB

After

(image error) Size: 2.2 KiB

Binary file not shown.

Before

(image error) Size: 4.9 KiB

After

(image error) Size: 2.7 KiB

Binary file not shown.

Before

(image error) Size: 4.1 KiB

After

(image error) Size: 2.4 KiB

Binary file not shown.

Before

(image error) Size: 1.8 KiB

After

(image error) Size: 1.6 KiB

Binary file not shown.

Before

(image error) Size: 2.2 KiB

After

(image error) Size: 2.0 KiB

Binary file not shown.

Before

(image error) Size: 3.2 KiB

After

(image error) Size: 3.2 KiB

Binary file not shown.

Before

(image error) Size: 2.8 KiB

After

(image error) Size: 2.7 KiB

Binary file not shown.

Before

(image error) Size: 1.4 KiB

After

(image error) Size: 947 B

Binary file not shown.

Before

(image error) Size: 4.5 KiB

After

(image error) Size: 4.1 KiB

Binary file not shown.

Before

(image error) Size: 3.1 KiB

After

(image error) Size: 2.7 KiB

Binary file not shown.

Before

(image error) Size: 2.8 KiB

After

(image error) Size: 2.2 KiB

Binary file not shown.

Before

(image error) Size: 3.1 KiB

After

(image error) Size: 2.7 KiB

Binary file not shown.

Before

(image error) Size: 1.8 KiB

After

(image error) Size: 1.3 KiB

Binary file not shown.

Before

(image error) Size: 1.7 KiB

After

(image error) Size: 1.3 KiB

Binary file not shown.

Before

(image error) Size: 1.6 KiB

After

(image error) Size: 1.3 KiB

Binary file not shown.

Before

(image error) Size: 1.8 KiB

After

(image error) Size: 1.3 KiB

Binary file not shown.

Before

(image error) Size: 1.8 KiB

After

(image error) Size: 1.4 KiB

Binary file not shown.

Before

(image error) Size: 613 B

After

(image error) Size: 525 B

Binary file not shown.

Before

(image error) Size: 845 B

After

(image error) Size: 759 B

@ -1,23 +1,18 @@
// discourse-skip-module
(function() {
setTimeout(function() {
(function () {
setTimeout(function () {
const $activateButton = $("#activate-account-button");
$activateButton.on("click", function() {
$activateButton.on("click", function () {
$activateButton.prop("disabled", true);
const hpPath = document.getElementById("data-activate-account").dataset
.path;
$.ajax(hpPath)
.then(function(hp) {
.then(function (hp) {
$("#password_confirmation").val(hp.value);
$("#challenge").val(
hp.challenge
.split("")
.reverse()
.join("")
);
$("#challenge").val(hp.challenge.split("").reverse().join(""));
$("#activate-account-form").submit();
})
.fail(function() {
.fail(function () {
$activateButton.prop("disabled", false);
});
});

@ -1,11 +1,13 @@
import RESTAdapter from "discourse/adapters/rest";
export default RESTAdapter.extend({
jsonMode: true,
basePath() {
return "/admin/api/";
},
apiNameFor() {
return "key";
}
},
});

@ -6,6 +6,6 @@ export default function buildPluginAdapter(pluginName) {
return (
"/admin/plugins/" + pluginName + this._super(store, type, findArgs)
);
}
},
});
}

@ -3,5 +3,5 @@ import RestAdapter from "discourse/adapters/rest";
export default RestAdapter.extend({
basePath() {
return "/admin/customize/";
}
},
});

@ -3,5 +3,5 @@ import RestAdapter from "discourse/adapters/rest";
export default RestAdapter.extend({
pathFor() {
return "/admin/customize/email_style";
}
},
});

@ -3,5 +3,5 @@ import RestAdapter from "discourse/adapters/rest";
export default RestAdapter.extend({
pathFor() {
return "/admin/customize/embedding";
}
},
});

@ -3,5 +3,5 @@ import RestAdapter from "discourse/adapters/rest";
export default RestAdapter.extend({
basePath() {
return "/admin/logs/";
}
},
});

@ -1,5 +1,5 @@
import RestAdapter from "discourse/adapters/rest";
export default RestAdapter.extend({
jsonMode: true
jsonMode: true,
});

@ -7,20 +7,20 @@ export default RestAdapter.extend({
afterFindAll(results) {
let map = {};
results.forEach(theme => {
results.forEach((theme) => {
map[theme.id] = theme;
});
results.forEach(theme => {
results.forEach((theme) => {
let mapped = theme.get("child_themes") || [];
mapped = mapped.map(t => map[t.id]);
mapped = mapped.map((t) => map[t.id]);
theme.set("childThemes", mapped);
let mappedParents = theme.get("parent_themes") || [];
mappedParents = mappedParents.map(t => map[t.id]);
mappedParents = mappedParents.map((t) => map[t.id]);
theme.set("parentThemes", mappedParents);
});
return results;
},
jsonMode: true
jsonMode: true,
});

@ -3,5 +3,5 @@ import RESTAdapter from "discourse/adapters/rest";
export default RESTAdapter.extend({
basePath() {
return "/admin/api/";
}
},
});

@ -3,5 +3,5 @@ import RESTAdapter from "discourse/adapters/rest";
export default RESTAdapter.extend({
basePath() {
return "/admin/api/";
}
},
});

@ -1,5 +1,6 @@
import Component from "@ember/component";
import loadScript from "discourse/lib/load-script";
import getURL from "discourse-common/lib/get-url";
import { observes } from "discourse-common/utils/decorators";
import { on } from "@ember/object/evented";
@ -32,6 +33,15 @@ export default Component.extend({
}
},
@observes("placeholder")
placeholderChanged() {
if (this._editor) {
this._editor.setOptions({
placeholder: this.placeholder,
});
}
},
@observes("disabled")
disabledStateChanged() {
this.changeDisabledState();
@ -44,13 +54,13 @@ export default Component.extend({
editor.setOptions({
readOnly: disabled,
highlightActiveLine: !disabled,
highlightGutterLine: !disabled
highlightGutterLine: !disabled,
});
editor.container.parentNode.setAttribute("data-disabled", disabled);
}
},
_destroyEditor: on("willDestroyElement", function() {
_destroyEditor: on("willDestroyElement", function () {
if (this._editor) {
this._editor.destroy();
this._editor = null;
@ -71,9 +81,11 @@ export default Component.extend({
didInsertElement() {
this._super(...arguments);
loadScript("/javascripts/ace/ace.js").then(() => {
window.ace.require(["ace/ace"], loadedAce => {
window.ace.require(["ace/ace"], (loadedAce) => {
loadedAce.config.set("loadWorkerFromBlob", false);
loadedAce.config.set("workerPath", getURL("/javascripts/ace")); // Do not use CDN for workers
if (!this.element || this.isDestroying || this.isDestroyed) {
return;
}
@ -81,7 +93,7 @@ export default Component.extend({
editor.setTheme("ace/theme/chrome");
editor.setShowPrintMargin(false);
editor.setOptions({ fontSize: "14px" });
editor.setOptions({ fontSize: "14px", placeholder: this.placeholder });
editor.getSession().setMode("ace/mode/" + this.mode);
editor.on("change", () => {
this._skipContentChangeEvent = true;
@ -117,6 +129,6 @@ export default Component.extend({
this._editor.focus();
this._editor.navigateFileEnd();
}
}
}
},
},
});

@ -35,9 +35,11 @@ export default Component.extend({
@on("init")
@observes("logs.[]")
_updateFormattedLogs: discourseDebounce(function() {
_updateFormattedLogs: discourseDebounce(function () {
const logs = this.logs;
if (logs.length === 0) return;
if (logs.length === 0) {
return;
}
// do the log formatting only once for HELLish performance
let formattedLogs = this.formattedLogs;
@ -49,7 +51,7 @@ export default Component.extend({
// update the formatted logs & cache index
this.setProperties({
formattedLogs: formattedLogs,
index: logs.length
index: logs.length,
});
// force rerender
this.renderLogs();
@ -70,5 +72,5 @@ export default Component.extend({
} else {
this.set("showLoadingSpinner", false);
}
}
},
});

@ -19,6 +19,6 @@ export default Component.extend({
save() {
// Action has to toggle 'editing' property.
this.action(this.buffer);
}
}
},
},
});

@ -1,4 +1,4 @@
import Component from "@ember/component";
export default Component.extend({
classNames: ["row"]
classNames: ["row"],
});

@ -11,15 +11,15 @@ export default Component.extend({
const rawData = this.get("model.data");
var data = {
labels: rawData.map(r => r.x),
labels: rawData.map((r) => r.x),
datasets: [
{
data: rawData.map(r => r.y),
data: rawData.map((r) => r.y),
label: model.get("title"),
backgroundColor: `rgba(200,220,240,${this.type === "bar" ? 1 : 0.3})`,
borderColor: "#08C"
}
]
borderColor: "#08C",
},
],
};
const config = {
@ -29,21 +29,21 @@ export default Component.extend({
responsive: true,
tooltips: {
callbacks: {
title: context =>
moment(context[0].xLabel, "YYYY-MM-DD").format("LL")
}
title: (context) =>
moment(context[0].xLabel, "YYYY-MM-DD").format("LL"),
},
},
scales: {
yAxes: [
{
display: true,
ticks: {
stepSize: 1
}
}
]
}
}
stepSize: 1,
},
},
],
},
},
};
this._chart = new window.Chart(ctx, config);
@ -53,5 +53,5 @@ export default Component.extend({
loadScript("/javascripts/Chart.min.js").then(() =>
this.refreshChart.apply(this)
);
}
},
});

@ -1,4 +1,4 @@
import Component from "@ember/component";
export default Component.extend({
tagName: ""
tagName: "",
});

@ -8,6 +8,7 @@ export default Component.extend({
classNames: ["admin-report-chart"],
limit: 8,
total: 0,
options: null,
init() {
this._super(...arguments);
@ -46,21 +47,27 @@ export default Component.extend({
},
_renderChart(model, chartCanvas) {
if (!chartCanvas) return;
if (!chartCanvas) {
return;
}
const context = chartCanvas.getContext("2d");
const chartData = makeArray(model.get("chartData") || model.get("data"));
const chartData = this._applyChartGrouping(
model,
makeArray(model.get("chartData") || model.get("data"), "weekly"),
this.options
);
const prevChartData = makeArray(
model.get("prevChartData") || model.get("prev_data")
);
const labels = chartData.map(d => d.x);
const labels = chartData.map((d) => d.x);
const data = {
labels,
datasets: [
{
data: chartData.map(d => Math.round(parseFloat(d.y))),
data: chartData.map((d) => Math.round(parseFloat(d.y))),
backgroundColor: prevChartData.length
? "transparent"
: model.secondary_color,
@ -68,19 +75,19 @@ export default Component.extend({
pointRadius: 3,
borderWidth: 1,
pointBackgroundColor: model.primary_color,
pointBorderColor: model.primary_color
}
]
pointBorderColor: model.primary_color,
},
],
};
if (prevChartData.length) {
data.datasets.push({
data: prevChartData.map(d => Math.round(parseFloat(d.y))),
data: prevChartData.map((d) => Math.round(parseFloat(d.y))),
borderColor: model.primary_color,
borderDash: [5, 5],
backgroundColor: "transparent",
borderWidth: 1,
pointRadius: 0
pointRadius: 0,
});
}
@ -91,52 +98,57 @@ export default Component.extend({
return;
}
this._chart = new window.Chart(context, this._buildChartConfig(data));
this._chart = new window.Chart(
context,
this._buildChartConfig(data, this.options)
);
});
},
_buildChartConfig(data) {
_buildChartConfig(data, options) {
return {
type: "line",
data,
options: {
tooltips: {
callbacks: {
title: tooltipItem =>
moment(tooltipItem[0].xLabel, "YYYY-MM-DD").format("LL")
}
title: (tooltipItem) =>
moment(tooltipItem[0].xLabel, "YYYY-MM-DD").format("LL"),
},
},
legend: {
display: false
display: false,
},
responsive: true,
maintainAspectRatio: false,
responsiveAnimationDuration: 0,
animation: {
duration: 0
duration: 0,
},
layout: {
padding: {
left: 0,
top: 0,
right: 0,
bottom: 0
}
bottom: 0,
},
},
scales: {
yAxes: [
{
display: true,
ticks: {
userCallback: label => {
if (Math.floor(label) === label) return label;
userCallback: (label) => {
if (Math.floor(label) === label) {
return label;
}
},
callback: label => number(label),
callback: (label) => number(label),
sampleSize: 5,
maxRotation: 25,
minRotation: 25
}
}
minRotation: 25,
},
},
],
xAxes: [
{
@ -144,17 +156,17 @@ export default Component.extend({
gridLines: { display: false },
type: "time",
time: {
parser: "YYYY-MM-DD"
unit: this._unitForGrouping(options),
},
ticks: {
sampleSize: 5,
maxRotation: 50,
minRotation: 50
}
}
]
}
}
minRotation: 50,
},
},
],
},
},
};
},
@ -163,5 +175,65 @@ export default Component.extend({
this._chart.destroy();
this._chart = null;
}
}
},
_applyChartGrouping(model, data, options) {
if (!options.chartGrouping || options.chartGrouping === "daily") {
return data;
}
if (
options.chartGrouping === "weekly" ||
options.chartGrouping === "monthly"
) {
const isoKind = options.chartGrouping === "weekly" ? "isoWeek" : "month";
const kind = options.chartGrouping === "weekly" ? "week" : "month";
const startMoment = moment(model.start_date, "YYYY-MM-DD");
let currentIndex = 0;
let currentStart = startMoment.clone().startOf(isoKind);
let currentEnd = startMoment.clone().endOf(isoKind);
const transformedData = [
{
x: currentStart.format("YYYY-MM-DD"),
y: 0,
},
];
data.forEach((d) => {
let date = moment(d.x, "YYYY-MM-DD");
if (!date.isBetween(currentStart, currentEnd)) {
currentIndex += 1;
currentStart = currentStart.add(1, kind).startOf(isoKind);
currentEnd = currentEnd.add(1, kind).endOf(isoKind);
}
if (transformedData[currentIndex]) {
transformedData[currentIndex].y += d.y;
} else {
transformedData[currentIndex] = {
x: d.x,
y: d.y,
};
}
});
return transformedData;
}
// ensure we return something if grouping is unknown
return data;
},
_unitForGrouping(options) {
switch (options.chartGrouping) {
case "monthly":
return "month";
case "weekly":
return "week";
default:
return "day";
}
},
});

@ -2,5 +2,5 @@ import Component from "@ember/component";
export default Component.extend({
classNames: ["admin-report-counters"],
attributeBindings: ["model.description:title"]
attributeBindings: ["model.description:title"],
});

@ -7,5 +7,5 @@ export default Component.extend({
"report.type",
/^(time_to_first_response|topics_with_no_response)$/
),
classNameBindings: ["reverseColors"]
classNameBindings: ["reverseColors"],
});

@ -1,4 +1,4 @@
import Component from "@ember/component";
export default Component.extend({
classNames: ["admin-report-inline-table"]
classNames: ["admin-report-inline-table"],
});

@ -1,4 +1,4 @@
import Component from "@ember/component";
export default Component.extend({
tagName: "tr"
tagName: "tr",
});

@ -48,7 +48,9 @@ export default Component.extend({
},
_renderChart(model, chartCanvas) {
if (!chartCanvas) return;
if (!chartCanvas) {
return;
}
const context = chartCanvas.getContext("2d");
@ -56,14 +58,14 @@ export default Component.extend({
const data = {
labels: chartData[0].data.mapBy("x"),
datasets: chartData.map(cd => {
datasets: chartData.map((cd) => {
return {
label: cd.label,
stack: "pageviews-stack",
data: cd.data.map(d => Math.round(parseFloat(d.y))),
backgroundColor: cd.color
data: cd.data.map((d) => Math.round(parseFloat(d.y))),
backgroundColor: cd.color,
};
})
}),
};
loadScript("/javascripts/Chart.min.js").then(() => {
@ -83,30 +85,30 @@ export default Component.extend({
responsiveAnimationDuration: 0,
hover: { mode: "index" },
animation: {
duration: 0
duration: 0,
},
tooltips: {
mode: "index",
intersect: false,
callbacks: {
beforeFooter: tooltipItem => {
beforeFooter: (tooltipItem) => {
let total = 0;
tooltipItem.forEach(
item => (total += parseInt(item.yLabel || 0, 10))
(item) => (total += parseInt(item.yLabel || 0, 10))
);
return `= ${total}`;
},
title: tooltipItem =>
moment(tooltipItem[0].xLabel, "YYYY-MM-DD").format("LL")
}
title: (tooltipItem) =>
moment(tooltipItem[0].xLabel, "YYYY-MM-DD").format("LL"),
},
},
layout: {
padding: {
left: 0,
top: 0,
right: 0,
bottom: 0
}
bottom: 0,
},
},
scales: {
yAxes: [
@ -114,15 +116,17 @@ export default Component.extend({
stacked: true,
display: true,
ticks: {
userCallback: label => {
if (Math.floor(label) === label) return label;
userCallback: (label) => {
if (Math.floor(label) === label) {
return label;
}
},
callback: label => number(label),
callback: (label) => number(label),
sampleSize: 5,
maxRotation: 25,
minRotation: 25
}
}
minRotation: 25,
},
},
],
xAxes: [
{
@ -132,17 +136,17 @@ export default Component.extend({
offset: true,
time: {
parser: "YYYY-MM-DD",
minUnit: "day"
minUnit: "day",
},
ticks: {
sampleSize: 5,
maxRotation: 50,
minRotation: 50
}
}
]
}
}
minRotation: 50,
},
},
],
},
},
};
},
@ -151,5 +155,5 @@ export default Component.extend({
this._chart.destroy();
this._chart = null;
}
}
},
});

@ -39,5 +39,5 @@ export default Component.extend({
@discourseComputed("uploadStats.free_bytes")
freeUploadSpace(bytes) {
return I18n.toHumanSize(bytes);
}
},
});

@ -16,5 +16,5 @@ export default Component.extend({
type: alias("label.type"),
property: alias("label.mainProperty"),
formatedValue: alias("computedLabel.formatedValue"),
value: alias("computedLabel.value")
value: alias("computedLabel.value"),
});

@ -15,5 +15,5 @@ export default Component.extend({
@discourseComputed("currentSortDirection")
sortIcon(currentSortDirection) {
return currentSortDirection === 1 ? "caret-up" : "caret-down";
}
},
});

@ -2,5 +2,5 @@ import Component from "@ember/component";
export default Component.extend({
tagName: "tr",
classNames: ["admin-report-table-row"],
options: null
options: null,
});

@ -26,7 +26,7 @@ export default Component.extend({
showTotalForSample(totalsForSample, total, datesFiltering) {
// check if we have at least one cell which contains a value
const sum = totalsForSample
.map(t => t.value)
.map((t) => t.value)
.compact()
.reduce((s, v) => s + v, 0);
@ -64,7 +64,7 @@ export default Component.extend({
@discourseComputed("totalsForSampleRow", "model.computedLabels")
totalsForSample(row, labels) {
return labels.map(label => {
return labels.map((label) => {
const computedLabel = label.compute(row);
computedLabel.type = label.type;
computedLabel.property = label.mainProperty;
@ -74,11 +74,13 @@ export default Component.extend({
@discourseComputed("model.data", "model.computedLabels")
totalsForSampleRow(rows, labels) {
if (!rows || !rows.length) return {};
if (!rows || !rows.length) {
return {};
}
let totalsRow = {};
labels.forEach(label => {
labels.forEach((label) => {
const reducer = (sum, row) => {
const computedLabel = label.compute(row);
const value = computedLabel.value;
@ -130,18 +132,20 @@ export default Component.extend({
@discourseComputed("model.data", "perPage", "page")
pages(data, perPage, page) {
if (!data || data.length <= perPage) return [];
if (!data || data.length <= perPage) {
return [];
}
const pagesIndexes = [];
for (let i = 0; i < Math.ceil(data.length / perPage); i++) {
pagesIndexes.push(i);
}
let pages = pagesIndexes.map(v => {
let pages = pagesIndexes.map((v) => {
return {
page: v + 1,
index: v,
class: v === page ? "is-current" : null
class: v === page ? "is-current" : null,
};
});
@ -165,6 +169,6 @@ export default Component.extend({
} else {
this.set("sortLabel", label);
}
}
}
},
},
});

@ -1,4 +1,4 @@
import Component from "@ember/component";
export default Component.extend({
tagName: "tr"
tagName: "tr",
});

@ -1,7 +1,7 @@
import I18n from "I18n";
import discourseComputed from "discourse-common/utils/decorators";
import { makeArray } from "discourse-common/lib/helpers";
import { alias, or, and, equal, notEmpty, not } from "@ember/object/computed";
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";
@ -16,7 +16,7 @@ const TABLE_OPTIONS = {
perPage: 8,
total: true,
limit: 20,
formatNumbers: true
formatNumbers: true,
};
const CHART_OPTIONS = {};
@ -43,10 +43,11 @@ function collapseWeekly(data, average) {
export default Component.extend({
classNameBindings: [
"isVisible",
"isHidden:hidden",
"isHidden::is-visible",
"isEnabled",
"isLoading",
"dasherizedDataSourceName"
"dasherizedDataSourceName",
],
classNames: ["admin-report"],
isEnabled: true,
@ -67,7 +68,6 @@ export default Component.extend({
showDatesOptions: alias("model.dates_filtering"),
showRefresh: or("showDatesOptions", "model.available_filters.length"),
shouldDisplayTrend: and("showTrend", "model.prev_period"),
isVisible: not("isHidden"),
init() {
this._super(...arguments);
@ -75,14 +75,14 @@ export default Component.extend({
this._reports = [];
},
isHidden: computed("siteSettings.dashboard_hidden_reports", function() {
isHidden: computed("siteSettings.dashboard_hidden_reports", function () {
return (this.siteSettings.dashboard_hidden_reports || "")
.split("|")
.filter(Boolean)
.includes(this.dataSourceName);
}),
startDate: computed("filters.startDate", function() {
startDate: computed("filters.startDate", function () {
if (this.filters && isPresent(this.filters.startDate)) {
return moment(this.filters.startDate, "YYYY-MM-DD");
} else {
@ -90,7 +90,7 @@ export default Component.extend({
}
}),
endDate: computed("filters.endDate", function() {
endDate: computed("filters.endDate", function () {
if (this.filters && isPresent(this.filters.endDate)) {
return moment(this.filters.endDate, "YYYY-MM-DD");
} else {
@ -131,18 +131,30 @@ export default Component.extend({
return displayedModesLength > 1;
},
@discourseComputed("currentMode")
isChartMode(currentMode) {
return currentMode === "chart";
},
@action
changeGrouping(grouping) {
this.send("refreshReport", {
chartGrouping: grouping,
});
},
@discourseComputed("currentMode", "model.modes", "forcedModes")
displayedModes(currentMode, reportModes, forcedModes) {
const modes = forcedModes ? forcedModes.split(",") : reportModes;
return makeArray(modes).map(mode => {
return makeArray(modes).map((mode) => {
const base = `btn-default mode-btn ${mode}`;
const cssClass = currentMode === mode ? `${base} is-current` : base;
return {
mode,
cssClass,
icon: mode === "table" ? "table" : "signal"
icon: mode === "table" ? "table" : "signal",
};
});
},
@ -159,7 +171,9 @@ export default Component.extend({
"filters.customFilters"
)
reportKey(dataSourceName, startDate, endDate, customFilters) {
if (!dataSourceName || !startDate || !endDate) return null;
if (!dataSourceName || !startDate || !endDate) {
return null;
}
startDate = startDate.toISOString(true).split("T")[0];
endDate = endDate.toISOString(true).split("T")[0];
@ -175,20 +189,33 @@ export default Component.extend({
customFilters
? JSON.stringify(customFilters, (k, v) => (k ? `${v}` : v))
: null,
SCHEMA_VERSION
SCHEMA_VERSION,
]
.filter(x => x)
.map(x => x.toString())
.filter((x) => x)
.map((x) => x.toString())
.join(":");
return reportKey;
},
@discourseComputed("reportOptions.chartGrouping")
chartGroupings(chartGrouping) {
chartGrouping = chartGrouping || "daily";
return ["daily", "weekly", "monthly"].map((id) => {
return {
id,
label: `admin.dashboard.reports.${id}`,
class: `chart-grouping ${chartGrouping === id ? "active" : "inactive"}`,
};
});
},
@action
onChangeDateRange(range) {
this.send("refreshReport", {
startDate: range.from,
endDate: range.to
endDate: range.to,
});
},
@ -203,14 +230,19 @@ export default Component.extend({
}
this.send("refreshReport", {
filters: customFilters
filters: customFilters,
});
},
@action
refreshReport(options = {}) {
if (!this.attrs.onRefresh) {
return;
}
this.attrs.onRefresh({
type: this.get("model.type"),
chartGrouping: options.chartGrouping,
startDate:
typeof options.startDate === "undefined"
? this.startDate
@ -220,7 +252,7 @@ export default Component.extend({
filters:
typeof options.filters === "undefined"
? this.get("filters.customFilters")
: options.filters
: options.filters,
});
},
@ -229,7 +261,7 @@ export default Component.extend({
const args = {
name: this.get("model.type"),
start_date: this.startDate.toISOString(true).split("T")[0],
end_date: this.endDate.toISOString(true).split("T")[0]
end_date: this.endDate.toISOString(true).split("T")[0],
};
const customFilters = this.get("filters.customFilters");
@ -243,6 +275,10 @@ export default Component.extend({
@action
changeMode(mode) {
this.set("currentMode", mode);
this.send("refreshReport", {
chartGrouping: null,
});
},
_computeReport() {
@ -261,7 +297,7 @@ export default Component.extend({
let filteredReports = this._reports.uniqBy("report_key");
let report;
const sort = r => {
const sort = (r) => {
if (r.length > 1) {
return r.findBy("type", this.dataSourceName);
} else {
@ -273,10 +309,12 @@ export default Component.extend({
report = sort(filteredReports)[0];
} else {
report = sort(
filteredReports.filter(r => r.report_key.includes(this.reportKey))
filteredReports.filter((r) => r.report_key.includes(this.reportKey))
)[0];
if (!report) return;
if (!report) {
return;
}
}
if (report.error === "not_found") {
@ -293,7 +331,7 @@ export default Component.extend({
this.setProperties({
model: report,
currentMode,
options: this._buildOptions(currentMode)
options: this._buildOptions(currentMode),
});
},
@ -305,7 +343,7 @@ export default Component.extend({
next(() => {
let payload = this._buildPayload(["prev_period"]);
const callback = response => {
const callback = (response) => {
if (!this.element || this.isDestroying || this.isDestroyed) {
return;
}
@ -364,7 +402,9 @@ export default Component.extend({
} else {
const chartOptions = JSON.parse(JSON.stringify(CHART_OPTIONS));
return EmberObject.create(
Object.assign(chartOptions, this.get("reportOptions.chart") || {})
Object.assign(chartOptions, this.get("reportOptions.chart") || {}, {
chartGrouping: this.get("reportOptions.chartGrouping"),
})
);
}
},
@ -373,13 +413,13 @@ export default Component.extend({
Report.fillMissingDates(jsonReport, { filledField: "chartData" });
if (jsonReport.chartData && jsonReport.modes[0] === "stacked_chart") {
jsonReport.chartData = jsonReport.chartData.map(chartData => {
jsonReport.chartData = jsonReport.chartData.map((chartData) => {
if (chartData.length > 40) {
return {
data: collapseWeekly(chartData.data),
req: chartData.req,
label: chartData.label,
color: chartData.color
color: chartData.color,
};
} else {
return chartData;
@ -397,7 +437,7 @@ export default Component.extend({
filledField: "prevChartData",
dataField: "prev_data",
starDate: jsonReport.prev_startDate,
endDate: jsonReport.prev_endDate
endDate: jsonReport.prev_endDate,
});
if (jsonReport.prevChartData && jsonReport.prevChartData.length > 40) {
@ -409,5 +449,5 @@ export default Component.extend({
}
return Report.create(jsonReport);
}
},
});

@ -1,3 +1,4 @@
import I18n from "I18n";
import { next } from "@ember/runloop";
import Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators";
@ -6,7 +7,7 @@ import { fmt } from "discourse/lib/computed";
export default Component.extend({
@discourseComputed("theme.targets", "onlyOverridden", "showAdvanced")
visibleTargets(targets, onlyOverridden, showAdvanced) {
return targets.filter(target => {
return targets.filter((target) => {
if (target.advanced && !showAdvanced) {
return false;
}
@ -21,18 +22,32 @@ export default Component.extend({
visibleFields(targetName, onlyOverridden, fields) {
fields = fields[targetName];
if (onlyOverridden) {
fields = fields.filter(field => field.edited);
fields = fields.filter((field) => field.edited);
}
return fields;
},
@discourseComputed("currentTargetName", "fieldName")
activeSectionMode(targetName, fieldName) {
if (["settings", "translations"].includes(targetName)) return "yaml";
if (["extra_scss"].includes(targetName)) return "scss";
if (["settings", "translations"].includes(targetName)) {
return "yaml";
}
if (["extra_scss"].includes(targetName)) {
return "scss";
}
if (["color_definitions"].includes(fieldName)) {
return "scss";
}
return fieldName && fieldName.indexOf("scss") > -1 ? "scss" : "html";
},
@discourseComputed("currentTargetName", "fieldName")
placeholder(targetName, fieldName) {
return fieldName && fieldName === "color_definitions"
? I18n.t("admin.customize.theme.color_definitions.placeholder")
: "";
},
@discourseComputed("fieldName", "currentTargetName", "theme")
activeSection: {
get(fieldName, target, model) {
@ -41,7 +56,7 @@ export default Component.extend({
set(value, fieldName, target, model) {
model.setField(target, fieldName, value);
return value;
}
},
},
editorId: fmt("fieldName", "currentTargetName", "%@|%@"),
@ -53,7 +68,7 @@ export default Component.extend({
@discourseComputed("currentTargetName", "theme.targets")
showAddField(currentTargetName, targets) {
return targets.find(t => t.name === currentTargetName).customNames;
return targets.find((t) => t.name === currentTargetName).customNames;
},
@discourseComputed(
@ -79,20 +94,22 @@ export default Component.extend({
},
addField(name) {
if (!name) return;
if (!name) {
return;
}
name = name.replace(/[^a-zA-Z0-9-_/]/g, "");
this.theme.setField(this.currentTargetName, name, "");
this.setProperties({ newFieldName: "", addingField: false });
this.fieldAdded(this.currentTargetName, name);
},
toggleMaximize: function() {
toggleMaximize: function () {
this.toggleProperty("maximized");
next(() => this.appEvents.trigger("ace:resize"));
},
onlyOverriddenChanged(value) {
this.onlyOverriddenChanged(value);
}
}
},
},
});

@ -6,11 +6,10 @@ 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 } from "discourse/lib/computed";
import { i18n } from "discourse/lib/computed";
import { propertyEqual, i18n } from "discourse/lib/computed";
import discourseComputed, {
observes,
on
on,
} from "discourse-common/utils/decorators";
export default Component.extend(bufferedProperty("userField"), {
@ -103,6 +102,6 @@ export default Component.extend(bufferedProperty("userField"), {
this.rollbackBuffer();
this.set("editing", false);
}
}
}
},
},
});

@ -1,6 +1,7 @@
import I18n from "I18n";
import Component from "@ember/component";
import { iconHTML } from "discourse-common/lib/icon-library";
import bootbox from "bootbox";
export default Component.extend({
classNames: ["watched-word"],
@ -18,12 +19,12 @@ export default Component.extend({
.then(() => {
this.action(this.word);
})
.catch(e => {
.catch((e) => {
bootbox.alert(
I18n.t("generic_error_with_reason", {
error: `http: ${e.status} - ${e.body}`
error: `http: ${e.status} - ${e.body}`,
})
);
});
}
},
});

@ -19,7 +19,7 @@ export default Component.extend({
@discourseComputed("model.[]", "typeName")
eventTypeExists(eventTypes, typeName) {
return eventTypes.any(event => event.name === typeName);
return eventTypes.any((event) => event.name === typeName);
},
@discourseComputed("eventTypeExists")
@ -36,12 +36,12 @@ export default Component.extend({
model.addObject(type);
} else {
model.removeObjects(
model.filter(eventType => eventType.name === type.name)
model.filter((eventType) => eventType.name === type.name)
);
}
}
return value;
}
}
},
},
});

@ -4,6 +4,7 @@ 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 bootbox from "bootbox";
export default Component.extend({
tagName: "li",
@ -13,7 +14,9 @@ export default Component.extend({
@discourseComputed("model.status")
statusColorClasses(status) {
if (!status) return "";
if (!status) {
return "";
}
if (status >= 200 && status <= 299) {
return "text-successful";
@ -53,7 +56,7 @@ export default Component.extend({
I18n.t("admin.web_hooks.events.redeliver_confirm"),
I18n.t("no_value"),
I18n.t("yes_value"),
result => {
(result) => {
if (result) {
ajax(
`/admin/api/web_hooks/${this.get(
@ -61,7 +64,7 @@ export default Component.extend({
)}/events/${this.get("model.id")}/redeliver`,
{ type: "POST" }
)
.then(json => {
.then((json) => {
this.set("model", json.web_hook_event);
})
.catch(popupAjaxError);
@ -74,10 +77,10 @@ export default Component.extend({
const expandDetailsKey = this.expandDetailsRequestKey;
if (this.expandDetails !== expandDetailsKey) {
let headers = _.extend(
let headers = Object.assign(
{
"Request URL": this.get("model.request_url"),
"Request method": "POST"
"Request method": "POST",
},
ensureJSON(this.get("model.headers"))
);
@ -85,7 +88,7 @@ export default Component.extend({
headers: plainJSON(headers),
body: prettyJSON(this.get("model.payload")),
expandDetails: expandDetailsKey,
bodyLabel: I18n.t("admin.web_hooks.events.payload")
bodyLabel: I18n.t("admin.web_hooks.events.payload"),
});
} else {
this.set("expandDetails", null);
@ -100,11 +103,11 @@ export default Component.extend({
headers: plainJSON(this.get("model.response_headers")),
body: this.get("model.response_body"),
expandDetails: expandDetailsKey,
bodyLabel: I18n.t("admin.web_hooks.events.body")
bodyLabel: I18n.t("admin.web_hooks.events.body"),
});
} else {
this.set("expandDetails", null);
}
}
}
},
},
});

@ -11,7 +11,7 @@ export default Component.extend({
@discourseComputed("deliveryStatuses", "model.last_delivery_status")
status(deliveryStatuses, lastDeliveryStatus) {
return deliveryStatuses.find(s => s.id === lastDeliveryStatus);
return deliveryStatuses.find((s) => s.id === lastDeliveryStatus);
},
@discourseComputed("status.id", "icons")
@ -34,5 +34,5 @@ export default Component.extend({
"deliveryStatus",
I18n.t(`admin.web_hooks.delivery_status.${this.get("status.name")}`)
);
}
},
});

@ -8,5 +8,5 @@ export default Component.extend({
willDestroyElement() {
this._super(...arguments);
$("body").removeClass("admin-interface");
}
},
});

@ -1,4 +1,4 @@
import Component from "@ember/component";
export default Component.extend({
tagName: ""
tagName: "",
});

@ -18,7 +18,7 @@ export default Component.extend({
styleSelection: true,
maxlength: computed("onlyHex", function() {
maxlength: computed("onlyHex", function () {
return this.onlyHex ? 6 : null;
}),
@ -28,7 +28,7 @@ export default Component.extend({
},
@observes("hexValue", "brightnessValue", "valid")
hexValueChanged: function() {
hexValueChanged: function () {
const hex = this.hexValue;
let text = this.element.querySelector("input.hex-input");
@ -47,7 +47,7 @@ export default Component.extend({
if (this.pickerLoaded) {
$(this.element.querySelector(".picker")).spectrum({
color: "#" + hex
color: "#" + hex,
});
}
} else {
@ -69,5 +69,5 @@ export default Component.extend({
});
});
schedule("afterRender", () => this.hexValueChanged());
}
},
});

@ -2,6 +2,7 @@ import I18n from "I18n";
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"),
@ -27,18 +28,18 @@ export default Component.extend({
set(value, styles, fieldName) {
styles.setField(fieldName, value);
return value;
}
},
},
actions: {
reset() {
bootbox.confirm(
I18n.t("admin.customize.email_style.reset_confirm", {
fieldName: I18n.t(`admin.customize.email_style.${this.fieldName}`)
fieldName: I18n.t(`admin.customize.email_style.${this.fieldName}`),
}),
I18n.t("no_value"),
I18n.t("yes_value"),
result => {
(result) => {
if (result) {
this.styles.setField(
this.fieldName,
@ -48,6 +49,6 @@ export default Component.extend({
}
}
);
}
}
},
},
});

@ -1,13 +1,16 @@
import I18n from "I18n";
import discourseComputed from "discourse-common/utils/decorators";
import discourseComputed, {
on,
observes,
} 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 { on, observes } from "discourse-common/utils/decorators";
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,
@ -42,7 +45,7 @@ export default Component.extend(bufferedProperty("host"), {
const props = this.buffered.getProperties(
"host",
"path_whitelist",
"allowed_paths",
"class_name"
);
props.category_id = this.categoryId;
@ -59,7 +62,7 @@ export default Component.extend(bufferedProperty("host"), {
},
delete() {
bootbox.confirm(I18n.t("admin.embedding.confirm_delete"), result => {
bootbox.confirm(I18n.t("admin.embedding.confirm_delete"), (result) => {
if (result) {
this.host.destroyRecord().then(() => {
this.deleteHost(this.host);
@ -76,6 +79,6 @@ export default Component.extend(bufferedProperty("host"), {
this.rollbackBuffer();
this.set("editToggled", false);
}
}
}
},
},
});

@ -27,6 +27,6 @@ export default Component.extend({
set(value) {
this.set("value", value);
return value;
}
}
},
},
});

@ -1,4 +1,4 @@
import Component from "@ember/component";
export default Component.extend({
classNames: ["flag-user-lists"]
classNames: ["flag-user-lists"],
});

@ -5,7 +5,7 @@ import highlightSyntax from "discourse/lib/highlight-syntax";
export default Component.extend({
@on("didInsertElement")
@observes("code")
_refresh: function() {
highlightSyntax($(this.element));
}
_refresh() {
highlightSyntax(this.element, this.siteSettings, this.session);
},
});

@ -0,0 +1,44 @@
import Component from "@ember/component";
import { action } from "@ember/object";
import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({
classNames: ["inline-edit"],
buffer: null,
bufferModelId: null,
didReceiveAttrs() {
this._super(...arguments);
if (this.modelId !== this.bufferModelId) {
// HACK: The condition above ensures this method is called only when its
// attributes are changed (i.e. only when `checked` changes).
//
// Reproduction steps: navigate to theme #1, switch to theme #2 from the
// left-side panel, then switch back to theme #1 and click on the <input>
// element wrapped by this component. It will call `didReceiveAttrs` even
// though none of the attributes have changed (only `buffer` does).
this.setProperties({
buffer: this.checked,
bufferModelId: this.modelId,
});
}
},
@discourseComputed("checked", "buffer")
changed(checked, buffer) {
return !!checked !== !!buffer;
},
@action
apply() {
this.set("checked", this.buffer);
this.action();
},
@action
cancel() {
this.set("buffer", this.checked);
},
});

@ -1,4 +1,4 @@
import Component from "@ember/component";
export default Component.extend({
classNames: ["install-theme-item"]
classNames: ["install-theme-item"],
});

@ -6,6 +6,7 @@ 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 bootbox from "bootbox";
export default Component.extend({
classNames: ["ip-lookup"],
@ -23,7 +24,9 @@ export default Component.extend({
this.set("show", true);
if (!this.location) {
ajax("/admin/users/ip-info", { data: { ip: this.ip } }).then(location =>
ajax("/admin/users/ip-info", {
data: { ip: this.ip },
}).then((location) =>
this.set("location", EmberObject.create(location))
);
}
@ -34,17 +37,17 @@ export default Component.extend({
const data = {
ip: this.ip,
exclude: this.userId,
order: "trust_level DESC"
order: "trust_level DESC",
};
ajax("/admin/users/total-others-with-same-ip", { data }).then(result =>
this.set("totalOthersWithSameIP", result.total)
);
ajax("/admin/users/total-others-with-same-ip", {
data,
}).then((result) => this.set("totalOthersWithSameIP", result.total));
AdminUser.findAll("active", data).then(users => {
AdminUser.findAll("active", data).then((users) => {
this.setProperties({
other_accounts: users,
otherAccountsLoading: false
otherAccountsLoading: false,
});
});
}
@ -90,12 +93,12 @@ export default Component.extend({
I18n.t("ip_lookup.confirm_delete_other_accounts"),
I18n.t("no_value"),
I18n.t("yes_value"),
confirmed => {
(confirmed) => {
if (confirmed) {
this.setProperties({
other_accounts: null,
otherAccountsLoading: true,
totalOthersWithSameIP: null
totalOthersWithSameIP: null,
});
ajax("/admin/users/delete-others-with-same-ip.json", {
@ -103,12 +106,12 @@ export default Component.extend({
data: {
ip: this.ip,
exclude: this.userId,
order: "trust_level DESC"
}
order: "trust_level DESC",
},
}).then(() => this.send("lookup"));
}
}
);
}
}
},
},
});

@ -1,4 +1,4 @@
import Component from "@ember/component";
export default Component.extend({
tagName: "tr"
tagName: "tr",
});

@ -1,8 +1,9 @@
import I18n from "I18n";
import discourseComputed from "discourse-common/utils/decorators";
import discourseComputed, {
afterRender,
} from "discourse-common/utils/decorators";
import { equal } from "@ember/object/computed";
import Component from "@ember/component";
import { afterRender } from "discourse-common/utils/decorators";
const ACTIONS = ["delete", "delete_replies", "edit", "none"];
@ -13,7 +14,7 @@ export default Component.extend({
@discourseComputed
penaltyActions() {
return ACTIONS.map(id => {
return ACTIONS.map((id) => {
return { id, name: I18n.t(`admin.user.penalty_post_${id}`) };
});
},
@ -28,7 +29,7 @@ export default Component.extend({
if (postAction === "edit") {
this._focusEditTextarea();
}
}
},
},
@afterRender
@ -37,5 +38,5 @@ export default Component.extend({
const body = elem.closest(".modal-body");
body.scrollTo(0, body.clientHeight);
elem.querySelector(".post-editor").focus();
}
},
});

@ -4,6 +4,7 @@ import Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators";
import { fmt } from "discourse/lib/computed";
import Permalink from "admin/models/permalink";
import bootbox from "bootbox";
export default Component.extend({
classNames: ["permalink-form"],
@ -18,7 +19,7 @@ export default Component.extend({
{ id: "post_id", name: I18n.t("admin.permalink.post_id") },
{ id: "category_id", name: I18n.t("admin.permalink.category_id") },
{ id: "tag_name", name: I18n.t("admin.permalink.tag_name") },
{ id: "external_url", name: I18n.t("admin.permalink.external_url") }
{ id: "external_url", name: I18n.t("admin.permalink.external_url") },
];
},
@ -26,7 +27,7 @@ export default Component.extend({
this._super(...arguments);
schedule("afterRender", () => {
$(this.element.querySelector(".external-url")).keydown(e => {
$(this.element.querySelector(".external-url")).keydown((e) => {
// enter key
if (e.keyCode === 13) {
this.send("submit");
@ -49,28 +50,28 @@ export default Component.extend({
Permalink.create({
url: this.url,
permalink_type: this.permalinkType,
permalink_type_value: this.permalink_type_value
permalink_type_value: this.permalink_type_value,
})
.save()
.then(
result => {
(result) => {
this.setProperties({
url: "",
permalink_type_value: "",
formSubmitted: false
formSubmitted: false,
});
this.action(Permalink.create(result.permalink));
this.focusPermalink();
},
e => {
(e) => {
this.set("formSubmitted", false);
let error;
if (e.responseJSON && e.responseJSON.errors) {
error = I18n.t("generic_error_with_reason", {
error: e.responseJSON.errors.join(". ")
error: e.responseJSON.errors.join(". "),
});
} else {
error = I18n.t("generic_error");
@ -83,6 +84,6 @@ export default Component.extend({
onChangePermalinkType(type) {
this.set("permalinkType", type);
}
}
},
},
});

Some files were not shown because too many files have changed in this diff Show More