merge master

This commit is contained in:
Neil Lalonde 2016-03-31 17:33:25 -04:00
parent 95f2ac6535
commit 01d0aeb5a9
6371 changed files with 86540 additions and 60860 deletions

View File

@ -6,7 +6,6 @@ languages:
exclude_paths:
- "app/assets/javascripts/defer/*"
- "app/assets/javascripts/discourse/lib/Markdown.Editor.js"
- "app/assets/javascripts/ember-addons/*"
- "lib/autospec/*"
- "lib/es6_module_transpiler/*"

View File

@ -6,9 +6,8 @@ app/assets/javascripts/pagedown_custom.js
app/assets/javascripts/vendor.js
app/assets/javascripts/locales/i18n.js
app/assets/javascripts/defer/html-sanitizer-bundle.js
app/assets/javascripts/discourse/lib/Markdown.Editor.js
app/assets/javascripts/ember-addons/
jsapp/lib/Markdown.Editor.js
app/assets/javascripts/discourse/lib/autosize.js.es6
lib/javascripts/locale/
lib/javascripts/messageformat.js
lib/javascripts/moment.js
@ -18,8 +17,8 @@ lib/es6_module_transpiler/support/es6-module-transpiler.js
public/javascripts/
spec/phantom_js/smoke_test.js
vendor/
test/javascripts/helpers/
test/javascripts/test_helper.js
test/javascripts/test_helper.js
test/javascripts/fixtures
test/javascripts/helpers/assertions.js
app/assets/javascripts/ember-addons/

View File

@ -90,6 +90,7 @@
"no-undef": 2,
"no-unused-vars": 2,
"no-with": 2,
"no-this-before-super": 2,
"semi": 2,
"strict": 0,
"valid-typeof": 2,

4
.gitignore vendored
View File

@ -47,6 +47,7 @@ log/
!/plugins/emoji/
!/plugins/lazyYT/
!/plugins/poll/
!/plugins/discourse-details/
/plugins/*/auto_generated/
/spec/fixtures/plugins/my_plugin/auto_generated
@ -57,6 +58,9 @@ log/
# Ignore Eclipse .buildpath file
/.buildpath
# Ignore byebug history
/.byebug_history
# Ignore RubyMine settings
/.idea

View File

@ -6,7 +6,6 @@ env:
- RUBY_GC_MALLOC_LIMIT=50000000
matrix:
- "RAILS_MASTER=0"
- "RAILS42=1"
- "RAILS_MASTER=1"
addons:
@ -21,7 +20,6 @@ addons:
matrix:
allow_failures:
- env: "RAILS_MASTER=1"
- env: "RAILS42=1"
- rvm: rbx-2
fast_finish: true
@ -29,6 +27,7 @@ rvm:
- 2.0.0
- 2.1
- 2.2
- 2.3.0
services:
- redis-server
@ -41,7 +40,7 @@ cache:
before_install:
- gem install bundler
- npm i -g eslint babel-eslint
- npm i -g eslint@2.2 babel-eslint
- eslint app/assets/javascripts
- eslint --ext .es6 app/assets/javascripts
- eslint --ext .es6 test/javascripts
@ -51,7 +50,6 @@ before_script:
- bundle exec rake db:create db:migrate
install:
- bash -c "if [ '$RAILS42' == '1' ]; then bundle update --retry=3 --jobs=3 rails rails-observers; fi"
- bash -c "if [ '$RAILS_MASTER' == '1' ]; then bundle update --retry=3 --jobs=3 arel rails rails-observers seed-fu; fi"
- bash -c "if [ '$RAILS_MASTER' == '0' ]; then bundle install --without development --deployment --retry=3 --jobs=3; fi"

View File

@ -1,6 +1,6 @@
[main]
host = https://www.transifex.com
lang_map = es_ES: es, fr_FR: fr, ko_KR: ko, pt_PT: pt
lang_map = es_ES: es, fr_FR: fr, ko_KR: ko, pt_PT: pt, sk_SK: sk, vi_VN: vi
[discourse-org.clientenyml]
file_filter = config/locales/client.<lang>.yml

70
Gemfile
View File

@ -6,48 +6,56 @@ def rails_master?
ENV["RAILS_MASTER"] == '1'
end
def rails_42?
ENV["RAILS42"] == '1'
end
if rails_master?
gem 'arel', git: 'https://github.com/rails/arel.git'
gem 'rails', git: 'https://github.com/rails/rails.git'
gem 'rails-observers', git: 'https://github.com/rails/rails-observers.git'
gem 'seed-fu', git: 'https://github.com/SamSaffron/seed-fu.git', branch: 'discourse'
elsif rails_42?
gem 'rails', '~> 4.2.1'
gem 'rails-observers', git: 'https://github.com/rails/rails-observers.git'
gem 'seed-fu', '~> 2.3.5'
else
gem 'rails', '~> 4.1.10'
# Rails 5 is going to ship with Action Cable, we have no use for it as
# we already ship MessageBus, AC introduces dependencies on Event Machine,
# Celluloid and Faye Web Sockets.
#
# Note this means upgrading Rails is more annoying, to do so, comment out the
# explicit dependencies, and add gem 'rails', bundle update rails and then
# comment back the explicit dependencies. Leaving this in a comment till we
# upgrade to Rails 5
#
# gem 'activesupport'
# gem 'actionpack'
# gem 'activerecord'
# gem 'actionmailer'
# gem 'activejob'
# gem 'railties'
# gem 'sprockets-rails'
gem 'rails', '~> 4.2'
gem 'rails-observers'
gem 'seed-fu', '~> 2.3.3'
gem 'seed-fu', '~> 2.3.5'
end
# Rails 4.1.6+ will relax the mail gem version requirement to `~> 2.5, >= 2.5.4`.
# However, mail gem 2.6.x currently does not work with discourse because of the
# reference to `Mail::RFC2822Parser` in `lib/email.rb`. This ensure discourse
# would continue to work with Rails 4.1.6+ when it is released.
gem 'mail', '~> 2.5.4'
gem 'mail'
gem 'mime-types', require: 'mime/types/columnar'
#gem 'redis-rails'
gem 'hiredis'
gem 'redis', require: ["redis", "redis/connection/hiredis"]
gem 'redis-namespace'
gem 'active_model_serializers', '~> 0.8.3'
gem 'onebox'
gem 'http_accept_language', '~>2.0.5', require: false
gem 'ember-rails'
gem 'ember-source', '1.12.2'
gem 'barber'
gem 'babel-transpiler'
gem 'message_bus'
gem 'rails_multisite', path: 'vendor/gems/rails_multisite'
gem 'message_bus', '2.0.0.beta.5'
gem 'rails_multisite'
gem 'redcarpet', require: false
gem 'fast_xs'
gem 'fast_xor'
@ -58,7 +66,7 @@ gem 'aws-sdk', require: false
gem 'excon', require: false
gem 'unf', require: false
gem 'email_reply_parser'
gem 'email_reply_trimmer', '0.1.3'
# note: for image_optim to correctly work you need to follow
# https://github.com/toy/image_optim
@ -72,11 +80,13 @@ gem 'omniauth-openid'
gem 'openid-redis-store'
gem 'omniauth-facebook'
gem 'omniauth-twitter'
gem 'omniauth-instagram'
# forked while https://github.com/intridea/omniauth-github/pull/41 is being upstreamd
gem 'omniauth-github-discourse', require: 'omniauth-github'
gem 'omniauth-oauth2', require: false
gem 'omniauth-google-oauth2'
gem 'oj'
gem 'pg'
@ -130,9 +140,10 @@ group :test, :development do
gem 'simplecov', require: false
gem 'timecop'
gem 'rspec-given'
gem 'pry-nav'
gem 'rspec-html-matchers'
gem 'spork-rails'
gem 'byebug'
gem 'pry-nav'
gem 'byebug', require: ENV['RM_INFO'].nil?
end
group :development do
@ -173,12 +184,17 @@ gem 'simple-rss', require: false
gem 'gctools', require: false, platform: :mri_21
begin
gem 'stackprof', require: false, platform: [:mri_21, :mri_22]
gem 'memory_profiler', require: false, platform: [:mri_21, :mri_22]
gem 'stackprof', require: false, platform: [:mri_21, :mri_22, :mri_23]
gem 'memory_profiler', require: false, platform: [:mri_21, :mri_22, :mri_23]
rescue Bundler::GemfileError
STDERR.puts "You are running an old version of bundler, please upgrade bundler ASAP, if you are using Discourse docker, rebuild your container."
gem 'stackprof', require: false, platform: [:mri_21]
gem 'memory_profiler', require: false, platform: [:mri_21]
begin
STDERR.puts "You are running an old version of bundler, please upgrade bundler ASAP, if you are using Discourse docker, rebuild your container."
gem 'stackprof', require: false, platform: [:mri_21, :mri_22]
gem 'memory_profiler', require: false, platform: [:mri_21, :mri_22]
rescue Bundler::GemfileError
gem 'stackprof', require: false, platform: [:mri_21]
gem 'memory_profiler', require: false, platform: [:mri_21]
end
end
gem 'rmmseg-cpp', require: false

View File

@ -1,52 +1,54 @@
PATH
remote: vendor/gems/rails_multisite
specs:
rails_multisite (0.0.1)
GEM
remote: https://rubygems.org/
specs:
actionmailer (4.1.10)
actionpack (= 4.1.10)
actionview (= 4.1.10)
actionmailer (4.2.6)
actionpack (= 4.2.6)
actionview (= 4.2.6)
activejob (= 4.2.6)
mail (~> 2.5, >= 2.5.4)
actionpack (4.1.10)
actionview (= 4.1.10)
activesupport (= 4.1.10)
rack (~> 1.5.2)
rails-dom-testing (~> 1.0, >= 1.0.5)
actionpack (4.2.6)
actionview (= 4.2.6)
activesupport (= 4.2.6)
rack (~> 1.6)
rack-test (~> 0.6.2)
actionview (4.1.10)
activesupport (= 4.1.10)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (4.2.6)
activesupport (= 4.2.6)
builder (~> 3.1)
erubis (~> 2.7.0)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
active_model_serializers (0.8.3)
activemodel (>= 3.0)
activemodel (4.1.10)
activesupport (= 4.1.10)
activejob (4.2.6)
activesupport (= 4.2.6)
globalid (>= 0.3.0)
activemodel (4.2.6)
activesupport (= 4.2.6)
builder (~> 3.1)
activerecord (4.1.10)
activemodel (= 4.1.10)
activesupport (= 4.1.10)
arel (~> 5.0.0)
activesupport (4.1.10)
i18n (~> 0.6, >= 0.6.9)
activerecord (4.2.6)
activemodel (= 4.2.6)
activesupport (= 4.2.6)
arel (~> 6.0)
activesupport (4.2.6)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
thread_safe (~> 0.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
annotate (2.6.6)
activerecord (>= 2.3.0)
rake (~> 10.4.2, >= 10.4.2)
arel (5.0.1.20140414130214)
aws-sdk (2.0.45)
aws-sdk-resources (= 2.0.45)
aws-sdk-core (2.0.45)
builder (~> 3.0)
annotate (2.7.0)
activerecord (>= 3.2, < 6.0)
rake (~> 10.4)
arel (6.0.3)
aws-sdk (2.2.9)
aws-sdk-resources (= 2.2.9)
aws-sdk-core (2.2.9)
jmespath (~> 1.0)
multi_json (~> 1.0)
aws-sdk-resources (2.0.45)
aws-sdk-core (= 2.0.45)
babel-source (5.8.19)
aws-sdk-resources (2.2.9)
aws-sdk-core (= 2.2.9)
babel-source (5.8.34)
babel-transpiler (0.7.0)
babel-source (>= 4.0, < 6)
execjs (~> 2.0)
@ -60,23 +62,21 @@ GEM
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
builder (3.2.2)
byebug (5.0.0)
columnize (= 0.9.0)
celluloid (0.16.0)
timers (~> 4.0.0)
byebug (8.2.1)
certified (1.0.0)
coderay (1.1.0)
columnize (0.9.0)
concurrent-ruby (1.0.0)
connection_pool (2.2.0)
crass (1.0.1)
daemons (1.2.2)
crass (1.0.2)
daemons (1.2.3)
debug_inspector (0.0.2)
diff-lcs (1.2.5)
discourse-qunit-rails (0.0.8)
railties
docile (1.1.5)
dotenv (1.0.2)
email_reply_parser (0.5.8)
domain_name (0.5.25)
unf (>= 0.0.5, < 1.0.0)
email_reply_trimmer (0.1.3)
ember-data-source (1.0.0.beta.16.1)
ember-source (~> 1.8)
ember-handlebars-template (0.1.5)
@ -91,15 +91,15 @@ GEM
railties (>= 3.1)
ember-source (1.12.2)
erubis (2.7.0)
eventmachine (1.0.7)
excon (0.45.3)
execjs (2.5.2)
exifr (1.2.2)
eventmachine (1.0.8)
excon (0.45.4)
execjs (2.6.0)
exifr (1.2.4)
fabrication (2.9.8)
fakeweb (1.3.0)
faraday (0.9.1)
faraday (0.9.2)
multipart-post (>= 1.2, < 3)
fast_blank (0.0.2)
fast_blank (1.0.0)
fast_stack (0.1.0)
rake
rake-compiler
@ -108,23 +108,26 @@ GEM
rake-compiler
fast_xs (0.8.0)
fastimage_discourse (1.6.6)
ffi (1.9.6)
ffi (1.9.10)
flamegraph (0.1.0)
fast_stack
foreman (0.77.0)
dotenv (~> 1.0.2)
foreman (0.78.0)
thor (~> 0.19.1)
fspath (2.1.1)
gctools (0.2.3)
given_core (3.5.4)
given_core (3.7.1)
sorcerer (>= 0.3.7)
globalid (0.3.6)
activesupport (>= 4.1.0)
guess_html_encoding (0.0.11)
hashie (3.4.0)
highline (1.7.1)
hashie (3.4.3)
highline (1.7.8)
hike (1.2.3)
hiredis (0.6.0)
hitimes (1.2.2)
htmlentities (4.3.3)
hiredis (0.6.1)
htmlentities (4.3.4)
http-cookie (1.0.2)
domain_name (~> 0.5)
http_accept_language (2.0.5)
i18n (0.7.0)
image_optim (0.20.2)
exifr (~> 1.1, >= 1.1.3)
@ -134,46 +137,46 @@ GEM
progress (~> 3.0, >= 3.0.1)
image_size (1.4.1)
in_threads (1.3.1)
jmespath (1.0.2)
multi_json (~> 1.0)
jquery-rails (3.1.2)
railties (>= 3.0, < 5.0)
jmespath (1.1.3)
jquery-rails (4.0.5)
rails-dom-testing (~> 1.0)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (1.8.3)
jwt (1.3.0)
kgio (2.9.3)
jwt (1.5.2)
kgio (2.10.0)
librarian (0.1.2)
highline
thor (~> 0.15)
libv8 (3.16.14.7)
libv8 (3.16.14.13)
listen (0.7.3)
logster (1.0.0.3.pre)
logster (1.2.2)
loofah (2.0.3)
nokogiri (>= 1.5.9)
lru_redux (1.1.0)
mail (2.5.4)
mime-types (~> 1.16)
treetop (~> 1.4.8)
memory_profiler (0.9.3)
message_bus (1.0.16)
mail (2.6.4)
mime-types (>= 1.16, < 4)
memory_profiler (0.9.6)
message_bus (2.0.0.beta.5)
rack (>= 1.1.3)
redis
metaclass (0.0.4)
method_source (0.8.2)
mime-types (1.25.1)
mini_portile (0.6.2)
minitest (5.6.1)
mime-types (2.99.1)
mini_portile2 (2.0.0)
minitest (5.8.4)
mocha (1.1.0)
metaclass (~> 0.0.1)
mock_redis (0.14.0)
mock_redis (0.15.4)
moneta (0.8.0)
msgpack (0.5.11)
msgpack (0.7.4)
multi_json (1.11.2)
multi_xml (0.5.5)
multipart-post (2.0.0)
mustache (1.0.2)
netrc (0.10.3)
nokogiri (1.6.6.2)
mini_portile (~> 0.6.0)
nokogumbo (1.2.0)
mustache (1.0.3)
netrc (0.11.0)
nokogiri (1.6.7.2)
mini_portile2 (~> 2.0.0.rc2)
nokogumbo (1.4.7)
nokogiri
oauth (0.4.7)
oauth2 (1.0.0)
@ -182,33 +185,37 @@ GEM
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (~> 1.2)
oj (2.12.9)
omniauth (1.2.2)
oj (2.14.3)
omniauth (1.3.1)
hashie (>= 1.2, < 4)
rack (~> 1.0)
omniauth-facebook (2.0.0)
rack (>= 1.0, < 3)
omniauth-facebook (3.0.0)
omniauth-oauth2 (~> 1.2)
omniauth-github-discourse (1.1.2)
omniauth (~> 1.0)
omniauth-oauth2 (~> 1.1)
omniauth-google-oauth2 (0.2.5)
omniauth (> 1.0)
omniauth-oauth2 (~> 1.1)
omniauth-oauth (1.0.1)
omniauth-google-oauth2 (0.3.1)
jwt (~> 1.0)
multi_json (~> 1.3)
omniauth (>= 1.1.1)
omniauth-oauth2 (>= 1.3.1)
omniauth-instagram (1.0.2)
omniauth (~> 1)
omniauth-oauth2 (~> 1)
omniauth-oauth (1.1.0)
oauth
omniauth (~> 1.0)
omniauth-oauth2 (1.2.0)
faraday (>= 0.8, < 0.10)
multi_json (~> 1.3)
omniauth-oauth2 (1.3.1)
oauth2 (~> 1.0)
omniauth (~> 1.2)
omniauth-openid (1.0.1)
omniauth (~> 1.0)
rack-openid (~> 1.3.1)
omniauth-twitter (1.0.1)
multi_json (~> 1.3)
omniauth-oauth (~> 1.0)
onebox (1.5.26)
omniauth-twitter (1.2.1)
json (~> 1.3)
omniauth-oauth (~> 1.1)
onebox (1.5.38)
htmlentities (~> 4.3.4)
moneta (~> 0.8)
multi_json (~> 1.11)
mustache
@ -216,23 +223,21 @@ GEM
openid-redis-store (0.0.2)
redis
ruby-openid
pg (0.18.1)
polyglot (0.3.5)
progress (3.1.0)
pry (0.10.1)
pg (0.18.4)
progress (3.1.1)
pry (0.10.3)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
pry-nav (0.2.4)
pry (>= 0.9.10, < 0.11.0)
pry-rails (0.3.3)
pry-rails (0.3.4)
pry (>= 0.9.10)
puma (2.11.1)
rack (>= 1.1, < 2.0)
r2 (0.2.5)
rack (1.5.5)
rack-mini-profiler (0.9.6)
rack (>= 1.1.3)
puma (3.2.0)
r2 (0.2.6)
rack (1.6.4)
rack-mini-profiler (0.9.9.2)
rack (>= 1.2.0)
rack-openid (1.3.1)
rack (>= 1.1.0)
ruby-openid (>= 2.1.8)
@ -240,40 +245,50 @@ GEM
rack
rack-test (0.6.3)
rack (>= 1.0)
rails (4.1.10)
actionmailer (= 4.1.10)
actionpack (= 4.1.10)
actionview (= 4.1.10)
activemodel (= 4.1.10)
activerecord (= 4.1.10)
activesupport (= 4.1.10)
rails (4.2.6)
actionmailer (= 4.2.6)
actionpack (= 4.2.6)
actionview (= 4.2.6)
activejob (= 4.2.6)
activemodel (= 4.2.6)
activerecord (= 4.2.6)
activesupport (= 4.2.6)
bundler (>= 1.3.0, < 2.0)
railties (= 4.1.10)
sprockets-rails (~> 2.0)
railties (= 4.2.6)
sprockets-rails
rails-deprecated_sanitizer (1.0.3)
activesupport (>= 4.2.0.alpha)
rails-dom-testing (1.0.7)
activesupport (>= 4.2.0.beta, < 5.0)
nokogiri (~> 1.6.0)
rails-deprecated_sanitizer (>= 1.0.1)
rails-html-sanitizer (1.0.3)
loofah (~> 2.0)
rails-observers (0.1.2)
activemodel (~> 4.0)
railties (4.1.10)
actionpack (= 4.1.10)
activesupport (= 4.1.10)
rails_multisite (1.0.3)
railties (4.2.6)
actionpack (= 4.2.6)
activesupport (= 4.2.6)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
raindrops (0.13.0)
rake (10.4.2)
rake-compiler (0.9.4)
raindrops (0.15.0)
rake (10.5.0)
rake-compiler (0.9.5)
rake
rb-fsevent (0.9.4)
rb-fsevent (0.9.7)
rb-inotify (0.9.5)
ffi (>= 0.5.0)
rbtrace (0.4.7)
ffi (>= 1.0.6)
msgpack (>= 0.4.3)
trollop (>= 1.16.2)
redcarpet (3.2.2)
redis (3.2.1)
redis (3.2.2)
redis-namespace (1.5.2)
redis (~> 3.0, >= 3.0.4)
ref (1.0.5)
rest-client (1.7.2)
ref (2.0.0)
rest-client (1.8.0)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 3.0)
netrc (~> 0.7)
rinku (1.7.3)
@ -287,13 +302,16 @@ GEM
rspec-expectations (3.2.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.2.0)
rspec-given (3.5.4)
given_core (= 3.5.4)
rspec (>= 2.12)
rspec-given (3.7.1)
given_core (= 3.7.1)
rspec (>= 2.14.0)
rspec-html-matchers (0.7.0)
nokogiri (~> 1)
rspec (~> 3)
rspec-mocks (3.2.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.2.0)
rspec-rails (3.2.1)
rspec-rails (3.2.3)
actionpack (>= 3.0, < 4.3)
activesupport (>= 3.0, < 4.3)
railties (>= 3.0, < 4.3)
@ -303,14 +321,14 @@ GEM
rspec-support (~> 3.2.0)
rspec-support (3.2.2)
rtlit (0.0.5)
ruby-openid (2.5.0)
ruby-openid (2.7.0)
ruby-readability (0.7.0)
guess_html_encoding (>= 0.0.4)
nokogiri (>= 1.6.0)
sanitize (3.1.2)
crass (~> 1.0.1)
sanitize (4.0.1)
crass (~> 1.0.2)
nokogiri (>= 1.4.4)
nokogumbo (= 1.2.0)
nokogumbo (~> 1.4.1)
sass (3.2.19)
sass-rails (4.0.5)
railties (>= 4.0.0, < 5.0)
@ -324,26 +342,24 @@ GEM
shoulda-context (~> 1.0, >= 1.0.1)
shoulda-matchers (>= 1.4.1, < 3.0)
shoulda-context (1.2.1)
shoulda-matchers (2.7.0)
shoulda-matchers (2.8.0)
activesupport (>= 3.0.0)
sidekiq (3.4.2)
celluloid (~> 0.16.0)
sidekiq (4.0.2)
concurrent-ruby (~> 1.0)
connection_pool (~> 2.2, >= 2.2.0)
json (~> 1.0)
redis (~> 3.2, >= 3.2.1)
redis-namespace (~> 1.5, >= 1.5.2)
sidekiq-statistic (1.1.0)
sidekiq (~> 3.3, >= 3.3.4)
sidekiq-statistic (1.2.0)
sidekiq (>= 3.3.4, < 5)
simple-rss (1.3.1)
simplecov (0.9.1)
simplecov (0.11.1)
docile (~> 1.1.0)
multi_json (~> 1.0)
simplecov-html (~> 0.8.0)
simplecov-html (0.8.0)
sinatra (1.4.5)
json (~> 1.8)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.0)
sinatra (1.4.6)
rack (~> 1.4)
rack-protection (~> 1.4)
tilt (~> 1.3, >= 1.3.4)
tilt (>= 1.3, < 3)
slop (3.6.0)
sorcerer (1.0.2)
spork (1.0.0rc4)
@ -363,29 +379,24 @@ GEM
therubyracer (0.12.2)
libv8 (~> 3.16.14.0)
ref
thin (1.6.3)
thin (1.6.4)
daemons (~> 1.0, >= 1.0.9)
eventmachine (~> 1.0)
eventmachine (~> 1.0, >= 1.0.4)
rack (~> 1.0)
thor (0.19.1)
thread_safe (0.3.5)
tilt (1.4.1)
timecop (0.7.3)
timers (4.0.1)
hitimes
treetop (1.4.15)
polyglot
polyglot (>= 0.3.1)
trollop (2.1.1)
timecop (0.8.0)
trollop (2.1.2)
tzinfo (1.2.2)
thread_safe (~> 0.1)
uglifier (2.7.1)
uglifier (2.7.2)
execjs (>= 0.3.0)
json (>= 1.8.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.6)
unicorn (4.8.3)
unf_ext (0.0.7.1)
unicorn (5.0.1)
kgio (~> 2.6)
rack
raindrops (~> 0.7)
@ -404,7 +415,7 @@ DEPENDENCIES
byebug
certified
discourse-qunit-rails
email_reply_parser
email_reply_trimmer (= 0.1.3)
ember-rails
ember-source (= 1.12.2)
excon
@ -420,14 +431,16 @@ DEPENDENCIES
highline
hiredis
htmlentities
http_accept_language (~> 2.0.5)
image_optim (= 0.20.2)
librarian (>= 0.0.25)
listen (= 0.7.3)
logster
lru_redux
mail (~> 2.5.4)
mail
memory_profiler
message_bus
message_bus (= 2.0.0.beta.5)
mime-types
minitest
mocha
mock_redis
@ -439,6 +452,7 @@ DEPENDENCIES
omniauth-facebook
omniauth-github-discourse
omniauth-google-oauth2
omniauth-instagram
omniauth-oauth2
omniauth-openid
omniauth-twitter
@ -451,27 +465,28 @@ DEPENDENCIES
r2 (~> 0.2.5)
rack-mini-profiler
rack-protection
rails (~> 4.1.10)
rails (~> 4.2)
rails-observers
rails_multisite!
rails_multisite
rake
rb-fsevent
rb-inotify (~> 0.9)
rbtrace
redcarpet
redis
redis-namespace
rest-client
rinku
rmmseg-cpp
rspec (~> 3.2.0)
rspec-given
rspec-html-matchers
rspec-rails
rtlit
ruby-readability
sanitize
sass
sass-rails (~> 4.0.5)
seed-fu (~> 2.3.3)
seed-fu (~> 2.3.5)
shoulda
sidekiq
sidekiq-statistic
@ -488,4 +503,4 @@ DEPENDENCIES
unicorn
BUNDLED WITH
1.10.6
1.11.2

View File

@ -11,8 +11,8 @@ To learn more about the philosophy and goals of the project, [visit **discourse.
## Screenshots
<a href="https://bbs.boingboing.net"><img src="https://www.discourse.org/faq/14/boing-boing-discourse.png" width="720px"></a>
<a href="http://discuss.howtogeek.com"><img src="https://www.discourse.org/faq/14/new-relic-discourse.png" width="720px"></a>
<a href="https://discuss.newrelic.com/"><img src="https://www.discourse.org/faq/14/how-to-geek-discourse.png" width="720px"></a>
<a href="https://discuss.newrelic.com/"><img src="https://www.discourse.org/faq/14/new-relic-discourse.png" width="720px"></a>
<a href="http://discuss.howtogeek.com"><img src="https://www.discourse.org/faq/14/how-to-geek-discourse.png" width="720px"></a>
<a href="https://talk.turtlerockstudios.com/"><img src="https://www.discourse.org/faq/14/turtle-rock-discourse.jpg" width="720px"></a>
<a href="https://discuss.atom.io"><img src="https://www.discourse.org/faq/14/nexus-7-mobile-discourse.png" alt="Atom" width="410px"></a> &nbsp;
@ -22,9 +22,9 @@ Browse [lots more notable Discourse instances](http://www.discourse.org/faq/cust
## Development
1. If you're **brand new to Ruby and Rails**, please see [**Discourse as Your First Rails App**](http://blog.discourse.org/2013/04/discourse-as-your-first-rails-app/) or our [**Discourse Vagrant Developer Guide**](docs/VAGRANT.md), which includes a development environment in a virtual machine.
1. If you're **brand new to Ruby and Rails**, please see [**Discourse as Your First Rails App**](http://blog.discourse.org/2013/04/discourse-as-your-first-rails-app/) or our [**Discourse Vagrant Developer Guide**](docs/VAGRANT.md), which includes a development environment in a virtual machine.
2. If you're familiar with how Rails works and are comfortable setting up your own environment, use our [**Discourse Advanced Developer Guide**](docs/DEVELOPER-ADVANCED.md).
2. If you're familiar with how Rails works and are comfortable setting up your own environment, use our [**Discourse Advanced Developer Guide**](docs/DEVELOPER-ADVANCED.md).
Before you get started, ensure you have the following minimum versions: [Ruby 2.0.0+](http://www.ruby-lang.org/en/downloads/), [PostgreSQL 9.3+](http://www.postgresql.org/download/), [Redis 2.6+](http://redis.io/download). If you're having trouble, please see our [**TROUBLESHOOTING GUIDE**](docs/TROUBLESHOOTING.md) first!
@ -40,13 +40,11 @@ Discourse is built for the *next* 10 years of the Internet, so our requirements
| Browsers | Tablets | Smartphones |
| -------- | ------- | ----------- |
| Safari 5.1+| iPad 2+ | iOS 7+ |
| Google Chrome 23+ | Android 4.1+ | Android 4.1+ |
| Safari 5.1+| iPad 2+ | iOS 7+ |
| Google Chrome 23+ | Android 4.3+ | Android 4.3+ |
| Internet Explorer 10+ | Windows 8 | Windows Phone 8 |
| Firefox 16+ | |
Internet Explorer 9.0 will no longer be supported in 2016.
## Built With
- [Ruby on Rails](https://github.com/rails/rails) &mdash; Our back end API is a Rails app. It responds to requests RESTfully in JSON.
@ -58,7 +56,7 @@ Plus *lots* of Ruby Gems, a complete list of which is at [/master/Gemfile](https
## Contributing
[![Build Status](https://travis-ci.org/discourse/discourse.svg)](https://travis-ci.org/discourse/discourse)
[![Build Status](https://api.travis-ci.org/discourse/discourse.svg?branch=master)](https://travis-ci.org/discourse/discourse)
[![Code Climate](https://codeclimate.com/github/discourse/discourse.svg)](https://codeclimate.com/github/discourse/discourse)
Discourse is **100% free** and **open source**. We encourage and support an active, healthy community that
@ -69,7 +67,9 @@ Before contributing to Discourse:
1. Please read the complete mission statements on [**discourse.org**](http://www.discourse.org). Yes we actually believe this stuff; you should too.
2. Read and sign the [**Electronic Discourse Forums Contribution License Agreement**](http://discourse.org/cla).
3. Dig into [**CONTRIBUTING.MD**](CONTRIBUTING.md), which covers submitting bugs, requesting new features, preparing your code for a pull request, etc.
4. Not sure what to work on? [**We've got some ideas.**](http://meta.discourse.org/t/so-you-want-to-help-out-with-discourse/3823)
4. Always strive to collaborate [with mutual respect](https://github.com/discourse/discourse/blob/master/docs/code-of-conduct.md).
5. Not sure what to work on? [**We've got some ideas.**](http://meta.discourse.org/t/so-you-want-to-help-out-with-discourse/3823)
We look forward to seeing your pull requests!

Binary file not shown.

View File

@ -1,6 +1,6 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<svg xmlns="http://www.w3.org/2000/svg">
<metadata></metadata>
<defs>
<font id="fontawesomeregular" horiz-adv-x="1536" >
@ -219,8 +219,8 @@
<glyph unicode="&#xf0d1;" horiz-adv-x="1792" d="M640 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM256 640h384v256h-158q-13 0 -22 -9l-195 -195q-9 -9 -9 -22v-30zM1536 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1792 1216v-1024q0 -15 -4 -26.5t-13.5 -18.5 t-16.5 -11.5t-23.5 -6t-22.5 -2t-25.5 0t-22.5 0.5q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-64q-3 0 -22.5 -0.5t-25.5 0t-22.5 2t-23.5 6t-16.5 11.5t-13.5 18.5t-4 26.5q0 26 19 45t45 19v320q0 8 -0.5 35t0 38 t2.5 34.5t6.5 37t14 30.5t22.5 30l198 198q19 19 50.5 32t58.5 13h160v192q0 26 19 45t45 19h1024q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0d2;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103q-111 0 -218 32q59 93 78 164q9 34 54 211q20 -39 73 -67.5t114 -28.5q121 0 216 68.5t147 188.5t52 270q0 114 -59.5 214t-172.5 163t-255 63q-105 0 -196 -29t-154.5 -77t-109 -110.5t-67 -129.5t-21.5 -134 q0 -104 40 -183t117 -111q30 -12 38 20q2 7 8 31t8 30q6 23 -11 43q-51 61 -51 151q0 151 104.5 259.5t273.5 108.5q151 0 235.5 -82t84.5 -213q0 -170 -68.5 -289t-175.5 -119q-61 0 -98 43.5t-23 104.5q8 35 26.5 93.5t30 103t11.5 75.5q0 50 -27 83t-77 33 q-62 0 -105 -57t-43 -142q0 -73 25 -122l-99 -418q-17 -70 -13 -177q-206 91 -333 281t-127 423q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf0d3;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-725q85 122 108 210q9 34 53 209q21 -39 73.5 -67t112.5 -28q181 0 295.5 147.5t114.5 373.5q0 84 -35 162.5t-96.5 139t-152.5 97t-197 36.5q-104 0 -194.5 -28.5t-153 -76.5 t-107.5 -109.5t-66.5 -128t-21.5 -132.5q0 -102 39.5 -180t116.5 -110q13 -5 23.5 0t14.5 19q10 44 15 61q6 23 -11 42q-50 62 -50 150q0 150 103.5 256.5t270.5 106.5q149 0 232.5 -81t83.5 -210q0 -168 -67.5 -286t-173.5 -118q-60 0 -97 43.5t-23 103.5q8 34 26.5 92.5 t29.5 102t11 74.5q0 49 -26.5 81.5t-75.5 32.5q-61 0 -103.5 -56.5t-42.5 -139.5q0 -72 24 -121l-98 -414q-24 -100 -7 -254h-183q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" />
<glyph unicode="&#xf0d4;" d="M829 318q0 -76 -58.5 -112.5t-139.5 -36.5q-41 0 -80.5 9.5t-75.5 28.5t-58 53t-22 78q0 46 25 80t65.5 51.5t82 25t84.5 7.5q20 0 31 -2q2 -1 23 -16.5t26 -19t23 -18t24.5 -22t19 -22.5t17 -26t9 -26.5t4.5 -31.5zM755 863q0 -60 -33 -99.5t-92 -39.5q-53 0 -93 42.5 t-57.5 96.5t-17.5 106q0 61 32 104t92 43q53 0 93.5 -45t58 -101t17.5 -107zM861 1120l88 64h-265q-85 0 -161 -32t-127.5 -98t-51.5 -153q0 -93 64.5 -154.5t158.5 -61.5q22 0 43 3q-13 -29 -13 -54q0 -44 40 -94q-175 -12 -257 -63q-47 -29 -75.5 -73t-28.5 -95 q0 -43 18.5 -77.5t48.5 -56.5t69 -37t77.5 -21t76.5 -6q60 0 120.5 15.5t113.5 46t86 82.5t33 117q0 49 -20 89.5t-49 66.5t-58 47.5t-49 44t-20 44.5t15.5 42.5t37.5 39.5t44 42t37.5 59.5t15.5 82.5q0 60 -22.5 99.5t-72.5 90.5h83zM1152 672h128v64h-128v128h-64v-128 h-128v-64h128v-160h64v160zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf0d5;" horiz-adv-x="1664" d="M735 740q0 -36 32 -70.5t77.5 -68t90.5 -73.5t77 -104t32 -142q0 -90 -48 -173q-72 -122 -211 -179.5t-298 -57.5q-132 0 -246.5 41.5t-171.5 137.5q-37 60 -37 131q0 81 44.5 150t118.5 115q131 82 404 100q-32 42 -47.5 74t-15.5 73q0 36 21 85q-46 -4 -68 -4 q-148 0 -249.5 96.5t-101.5 244.5q0 82 36 159t99 131q77 66 182.5 98t217.5 32h418l-138 -88h-131q74 -63 112 -133t38 -160q0 -72 -24.5 -129.5t-59 -93t-69.5 -65t-59.5 -61.5t-24.5 -66zM589 836q38 0 78 16.5t66 43.5q53 57 53 159q0 58 -17 125t-48.5 129.5 t-84.5 103.5t-117 41q-42 0 -82.5 -19.5t-65.5 -52.5q-47 -59 -47 -160q0 -46 10 -97.5t31.5 -103t52 -92.5t75 -67t96.5 -26zM591 -37q58 0 111.5 13t99 39t73 73t27.5 109q0 25 -7 49t-14.5 42t-27 41.5t-29.5 35t-38.5 34.5t-36.5 29t-41.5 30t-36.5 26q-16 2 -48 2 q-53 0 -105 -7t-107.5 -25t-97 -46t-68.5 -74.5t-27 -105.5q0 -70 35 -123.5t91.5 -83t119 -44t127.5 -14.5zM1401 839h213v-108h-213v-219h-105v219h-212v108h212v217h105v-217z" />
<glyph unicode="&#xf0d4;" d="M917 631q0 26 -6 64h-362v-132h217q-3 -24 -16.5 -50t-37.5 -53t-66.5 -44.5t-96.5 -17.5q-99 0 -169 71t-70 171t70 171t169 71q92 0 153 -59l104 101q-108 100 -257 100q-160 0 -272 -112.5t-112 -271.5t112 -271.5t272 -112.5q165 0 266.5 105t101.5 270zM1262 585 h109v110h-109v110h-110v-110h-110v-110h110v-110h110v110zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf0d5;" horiz-adv-x="2304" d="M1437 623q0 -208 -87 -370.5t-248 -254t-369 -91.5q-149 0 -285 58t-234 156t-156 234t-58 285t58 285t156 234t234 156t285 58q286 0 491 -192l-199 -191q-117 113 -292 113q-123 0 -227.5 -62t-165.5 -168.5t-61 -232.5t61 -232.5t165.5 -168.5t227.5 -62 q83 0 152.5 23t114.5 57.5t78.5 78.5t49 83t21.5 74h-416v252h692q12 -63 12 -122zM2304 745v-210h-209v-209h-210v209h-209v210h209v209h210v-209h209z" />
<glyph unicode="&#xf0d6;" horiz-adv-x="1920" d="M768 384h384v96h-128v448h-114l-148 -137l77 -80q42 37 55 57h2v-288h-128v-96zM1280 640q0 -70 -21 -142t-59.5 -134t-101.5 -101t-138 -39t-138 39t-101.5 101t-59.5 134t-21 142t21 142t59.5 134t101.5 101t138 39t138 -39t101.5 -101t59.5 -134t21 -142zM1792 384 v512q-106 0 -181 75t-75 181h-1152q0 -106 -75 -181t-181 -75v-512q106 0 181 -75t75 -181h1152q0 106 75 181t181 75zM1920 1216v-1152q0 -26 -19 -45t-45 -19h-1792q-26 0 -45 19t-19 45v1152q0 26 19 45t45 19h1792q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0d7;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0d8;" horiz-adv-x="1024" d="M1024 320q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
@ -362,7 +362,7 @@
<glyph unicode="&#xf169;" d="M685 771q0 1 -126 222q-21 34 -52 34h-184q-18 0 -26 -11q-7 -12 1 -29l125 -216v-1l-196 -346q-9 -14 0 -28q8 -13 24 -13h185q31 0 50 36zM1309 1268q-7 12 -24 12h-187q-30 0 -49 -35l-411 -729q1 -2 262 -481q20 -35 52 -35h184q18 0 25 12q8 13 -1 28l-260 476v1 l409 723q8 16 0 28zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf16a;" horiz-adv-x="1792" d="M1280 640q0 37 -30 54l-512 320q-31 20 -65 2q-33 -18 -33 -56v-640q0 -38 33 -56q16 -8 31 -8q20 0 34 10l512 320q30 17 30 54zM1792 640q0 -96 -1 -150t-8.5 -136.5t-22.5 -147.5q-16 -73 -69 -123t-124 -58q-222 -25 -671 -25t-671 25q-71 8 -124.5 58t-69.5 123 q-14 65 -21.5 147.5t-8.5 136.5t-1 150t1 150t8.5 136.5t22.5 147.5q16 73 69 123t124 58q222 25 671 25t671 -25q71 -8 124.5 -58t69.5 -123q14 -65 21.5 -147.5t8.5 -136.5t1 -150z" />
<glyph unicode="&#xf16b;" horiz-adv-x="1792" d="M402 829l494 -305l-342 -285l-490 319zM1388 274v-108l-490 -293v-1l-1 1l-1 -1v1l-489 293v108l147 -96l342 284v2l1 -1l1 1v-2l343 -284zM554 1418l342 -285l-494 -304l-338 270zM1390 829l338 -271l-489 -319l-343 285zM1239 1418l489 -319l-338 -270l-494 304z" />
<glyph unicode="&#xf16c;" horiz-adv-x="1408" d="M928 135v-151l-707 -1v151zM1169 481v-701l-1 -35v-1h-1132l-35 1h-1v736h121v-618h928v618h120zM241 393l704 -65l-13 -150l-705 65zM309 709l683 -183l-39 -146l-683 183zM472 1058l609 -360l-77 -130l-609 360zM832 1389l398 -585l-124 -85l-399 584zM1285 1536 l121 -697l-149 -26l-121 697z" />
<glyph unicode="&#xf16c;" d="M1289 -96h-1118v480h-160v-640h1438v640h-160v-480zM347 428l33 157l783 -165l-33 -156zM450 802l67 146l725 -339l-67 -145zM651 1158l102 123l614 -513l-102 -123zM1048 1536l477 -641l-128 -96l-477 641zM330 65v159h800v-159h-800z" />
<glyph unicode="&#xf16d;" d="M1362 110v648h-135q20 -63 20 -131q0 -126 -64 -232.5t-174 -168.5t-240 -62q-197 0 -337 135.5t-140 327.5q0 68 20 131h-141v-648q0 -26 17.5 -43.5t43.5 -17.5h1069q25 0 43 17.5t18 43.5zM1078 643q0 124 -90.5 211.5t-218.5 87.5q-127 0 -217.5 -87.5t-90.5 -211.5 t90.5 -211.5t217.5 -87.5q128 0 218.5 87.5t90.5 211.5zM1362 1003v165q0 28 -20 48.5t-49 20.5h-174q-29 0 -49 -20.5t-20 -48.5v-165q0 -29 20 -49t49 -20h174q29 0 49 20t20 49zM1536 1211v-1142q0 -81 -58 -139t-139 -58h-1142q-81 0 -139 58t-58 139v1142q0 81 58 139 t139 58h1142q81 0 139 -58t58 -139z" />
<glyph unicode="&#xf16e;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM698 640q0 88 -62 150t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150zM1262 640q0 88 -62 150 t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150z" />
<glyph unicode="&#xf170;" d="M768 914l201 -306h-402zM1133 384h94l-459 691l-459 -691h94l104 160h522zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
@ -410,7 +410,7 @@
<glyph unicode="&#xf19c;" horiz-adv-x="2048" d="M960 1536l960 -384v-128h-128q0 -26 -20.5 -45t-48.5 -19h-1526q-28 0 -48.5 19t-20.5 45h-128v128zM256 896h256v-768h128v768h256v-768h128v768h256v-768h128v768h256v-768h59q28 0 48.5 -19t20.5 -45v-64h-1664v64q0 26 20.5 45t48.5 19h59v768zM1851 -64 q28 0 48.5 -19t20.5 -45v-128h-1920v128q0 26 20.5 45t48.5 19h1782z" />
<glyph unicode="&#xf19d;" horiz-adv-x="2304" d="M1774 700l18 -316q4 -69 -82 -128t-235 -93.5t-323 -34.5t-323 34.5t-235 93.5t-82 128l18 316l574 -181q22 -7 48 -7t48 7zM2304 1024q0 -23 -22 -31l-1120 -352q-4 -1 -10 -1t-10 1l-652 206q-43 -34 -71 -111.5t-34 -178.5q63 -36 63 -109q0 -69 -58 -107l58 -433 q2 -14 -8 -25q-9 -11 -24 -11h-192q-15 0 -24 11q-10 11 -8 25l58 433q-58 38 -58 107q0 73 65 111q11 207 98 330l-333 104q-22 8 -22 31t22 31l1120 352q4 1 10 1t10 -1l1120 -352q22 -8 22 -31z" />
<glyph unicode="&#xf19e;" d="M859 579l13 -707q-62 11 -105 11q-41 0 -105 -11l13 707q-40 69 -168.5 295.5t-216.5 374.5t-181 287q58 -15 108 -15q43 0 111 15q63 -111 133.5 -229.5t167 -276.5t138.5 -227q37 61 109.5 177.5t117.5 190t105 176t107 189.5q54 -14 107 -14q56 0 114 14v0 q-28 -39 -60 -88.5t-49.5 -78.5t-56.5 -96t-49 -84q-146 -248 -353 -610z" />
<glyph unicode="&#xf1a0;" horiz-adv-x="1280" d="M981 197q0 25 -7 49t-14.5 42t-27 41.5t-29.5 35t-38.5 34.5t-36.5 29t-41.5 30t-36.5 26q-16 2 -49 2q-53 0 -104.5 -7t-107 -25t-97 -46t-68.5 -74.5t-27 -105.5q0 -56 23.5 -102t61 -75.5t87 -50t100 -29t101.5 -8.5q58 0 111.5 13t99 39t73 73t27.5 109zM864 1055 q0 59 -17 125.5t-48 129t-84 103.5t-117 41q-42 0 -82.5 -19.5t-66.5 -52.5q-46 -59 -46 -160q0 -46 10 -97.5t31.5 -103t52 -92.5t75 -67t96.5 -26q37 0 77.5 16.5t65.5 43.5q53 56 53 159zM752 1536h417l-137 -88h-132q75 -63 113 -133t38 -160q0 -72 -24.5 -129.5 t-59.5 -93t-69.5 -65t-59 -61.5t-24.5 -66q0 -36 32 -70.5t77 -68t90.5 -73.5t77.5 -104t32 -142q0 -91 -49 -173q-71 -122 -209.5 -179.5t-298.5 -57.5q-132 0 -246.5 41.5t-172.5 137.5q-36 59 -36 131q0 81 44.5 150t118.5 115q131 82 404 100q-32 41 -47.5 73.5 t-15.5 73.5q0 40 21 85q-46 -4 -68 -4q-148 0 -249.5 96.5t-101.5 244.5q0 82 36 159t99 131q76 66 182 98t218 32z" />
<glyph unicode="&#xf1a0;" d="M768 750h725q12 -67 12 -128q0 -217 -91 -387.5t-259.5 -266.5t-386.5 -96q-157 0 -299 60.5t-245 163.5t-163.5 245t-60.5 299t60.5 299t163.5 245t245 163.5t299 60.5q300 0 515 -201l-209 -201q-123 119 -306 119q-129 0 -238.5 -65t-173.5 -176.5t-64 -243.5 t64 -243.5t173.5 -176.5t238.5 -65q87 0 160 24t120 60t82 82t51.5 87t22.5 78h-436v264z" />
<glyph unicode="&#xf1a1;" horiz-adv-x="1792" d="M1095 369q16 -16 0 -31q-62 -62 -199 -62t-199 62q-16 15 0 31q6 6 15 6t15 -6q48 -49 169 -49q120 0 169 49q6 6 15 6t15 -6zM788 550q0 -37 -26 -63t-63 -26t-63.5 26t-26.5 63q0 38 26.5 64t63.5 26t63 -26.5t26 -63.5zM1183 550q0 -37 -26.5 -63t-63.5 -26t-63 26 t-26 63t26 63.5t63 26.5t63.5 -26t26.5 -64zM1434 670q0 49 -35 84t-85 35t-86 -36q-130 90 -311 96l63 283l200 -45q0 -37 26 -63t63 -26t63.5 26.5t26.5 63.5t-26.5 63.5t-63.5 26.5q-54 0 -80 -50l-221 49q-19 5 -25 -16l-69 -312q-180 -7 -309 -97q-35 37 -87 37 q-50 0 -85 -35t-35 -84q0 -35 18.5 -64t49.5 -44q-6 -27 -6 -56q0 -142 140 -243t337 -101q198 0 338 101t140 243q0 32 -7 57q30 15 48 43.5t18 63.5zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191 t348 71t348 -71t286 -191t191 -286t71 -348z" />
<glyph unicode="&#xf1a2;" d="M939 407q13 -13 0 -26q-53 -53 -171 -53t-171 53q-13 13 0 26q5 6 13 6t13 -6q42 -42 145 -42t145 42q5 6 13 6t13 -6zM676 563q0 -31 -23 -54t-54 -23t-54 23t-23 54q0 32 22.5 54.5t54.5 22.5t54.5 -22.5t22.5 -54.5zM1014 563q0 -31 -23 -54t-54 -23t-54 23t-23 54 q0 32 22.5 54.5t54.5 22.5t54.5 -22.5t22.5 -54.5zM1229 666q0 42 -30 72t-73 30q-42 0 -73 -31q-113 78 -267 82l54 243l171 -39q1 -32 23.5 -54t53.5 -22q32 0 54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5q-48 0 -69 -43l-189 42q-17 5 -21 -13l-60 -268q-154 -6 -265 -83 q-30 32 -74 32q-43 0 -73 -30t-30 -72q0 -30 16 -55t42 -38q-5 -25 -5 -48q0 -122 120 -208.5t289 -86.5q170 0 290 86.5t120 208.5q0 25 -6 49q25 13 40.5 37.5t15.5 54.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960 q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf1a3;" d="M866 697l90 27v62q0 79 -58 135t-138 56t-138 -55.5t-58 -134.5v-283q0 -20 -14 -33.5t-33 -13.5t-32.5 13.5t-13.5 33.5v120h-151v-122q0 -82 57.5 -139t139.5 -57q81 0 138.5 56.5t57.5 136.5v280q0 19 13.5 33t33.5 14q19 0 32.5 -14t13.5 -33v-54zM1199 502v122h-150 v-126q0 -20 -13.5 -33.5t-33.5 -13.5q-19 0 -32.5 14t-13.5 33v123l-90 -26l-60 28v-123q0 -80 58 -137t139 -57t138.5 57t57.5 139zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103 t385.5 -103t279.5 -279.5t103 -385.5z" />
@ -454,7 +454,7 @@
<glyph unicode="&#xf1cb;" horiz-adv-x="1792" d="M216 367l603 -402v359l-334 223zM154 511l193 129l-193 129v-258zM973 -35l603 402l-269 180l-334 -223v-359zM896 458l272 182l-272 182l-272 -182zM485 733l334 223v359l-603 -402zM1445 640l193 -129v258zM1307 733l269 180l-603 402v-359zM1792 913v-546 q0 -41 -34 -64l-819 -546q-21 -13 -43 -13t-43 13l-819 546q-34 23 -34 64v546q0 41 34 64l819 546q21 13 43 13t43 -13l819 -546q34 -23 34 -64z" />
<glyph unicode="&#xf1cc;" horiz-adv-x="2048" d="M1800 764q111 -46 179.5 -145.5t68.5 -221.5q0 -164 -118 -280.5t-285 -116.5q-4 0 -11.5 0.5t-10.5 0.5h-1209h-1h-2h-5q-170 10 -288 125.5t-118 280.5q0 110 55 203t147 147q-12 39 -12 82q0 115 82 196t199 81q95 0 172 -58q75 154 222.5 248t326.5 94 q166 0 306 -80.5t221.5 -218.5t81.5 -301q0 -6 -0.5 -18t-0.5 -18zM468 498q0 -122 84 -193t208 -71q137 0 240 99q-16 20 -47.5 56.5t-43.5 50.5q-67 -65 -144 -65q-55 0 -93.5 33.5t-38.5 87.5q0 53 38.5 87t91.5 34q44 0 84.5 -21t73 -55t65 -75t69 -82t77 -75t97 -55 t121.5 -21q121 0 204.5 71.5t83.5 190.5q0 121 -84 192t-207 71q-143 0 -241 -97q14 -16 29.5 -34t34.5 -40t29 -34q66 64 142 64q52 0 92 -33t40 -84q0 -57 -37 -91.5t-94 -34.5q-43 0 -82.5 21t-72 55t-65.5 75t-69.5 82t-77.5 75t-96.5 55t-118.5 21q-122 0 -207 -70.5 t-85 -189.5z" />
<glyph unicode="&#xf1cd;" horiz-adv-x="1792" d="M896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM896 1408q-190 0 -361 -90l194 -194q82 28 167 28t167 -28l194 194q-171 90 -361 90zM218 279l194 194 q-28 82 -28 167t28 167l-194 194q-90 -171 -90 -361t90 -361zM896 -128q190 0 361 90l-194 194q-82 -28 -167 -28t-167 28l-194 -194q171 -90 361 -90zM896 256q159 0 271.5 112.5t112.5 271.5t-112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5 t271.5 -112.5zM1380 473l194 -194q90 171 90 361t-90 361l-194 -194q28 -82 28 -167t-28 -167z" />
<glyph unicode="&#xf1ce;" horiz-adv-x="1792" d="M1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348q0 222 101 414.5t276.5 317t390.5 155.5v-260q-221 -45 -366.5 -221t-145.5 -406q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5 q0 230 -145.5 406t-366.5 221v260q215 -31 390.5 -155.5t276.5 -317t101 -414.5z" />
<glyph unicode="&#xf1ce;" horiz-adv-x="1792" d="M1760 640q0 -176 -68.5 -336t-184 -275.5t-275.5 -184t-336 -68.5t-336 68.5t-275.5 184t-184 275.5t-68.5 336q0 213 97 398.5t265 305.5t374 151v-228q-221 -45 -366.5 -221t-145.5 -406q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5 t136.5 204t51 248.5q0 230 -145.5 406t-366.5 221v228q206 -31 374 -151t265 -305.5t97 -398.5z" />
<glyph unicode="&#xf1d0;" horiz-adv-x="1792" d="M19 662q8 217 116 406t305 318h5q0 -1 -1 -3q-8 -8 -28 -33.5t-52 -76.5t-60 -110.5t-44.5 -135.5t-14 -150.5t39 -157.5t108.5 -154q50 -50 102 -69.5t90.5 -11.5t69.5 23.5t47 32.5l16 16q39 51 53 116.5t6.5 122.5t-21 107t-26.5 80l-14 29q-10 25 -30.5 49.5t-43 41 t-43.5 29.5t-35 19l-13 6l104 115q39 -17 78 -52t59 -61l19 -27q1 48 -18.5 103.5t-40.5 87.5l-20 31l161 183l160 -181q-33 -46 -52.5 -102.5t-22.5 -90.5l-4 -33q22 37 61.5 72.5t67.5 52.5l28 17l103 -115q-44 -14 -85 -50t-60 -65l-19 -29q-31 -56 -48 -133.5t-7 -170 t57 -156.5q33 -45 77.5 -60.5t85 -5.5t76 26.5t57.5 33.5l21 16q60 53 96.5 115t48.5 121.5t10 121.5t-18 118t-37 107.5t-45.5 93t-45 72t-34.5 47.5l-13 17q-14 13 -7 13l10 -3q40 -29 62.5 -46t62 -50t64 -58t58.5 -65t55.5 -77t45.5 -88t38 -103t23.5 -117t10.5 -136 q3 -259 -108 -465t-312 -321t-456 -115q-185 0 -351 74t-283.5 198t-184 293t-60.5 353z" />
<glyph unicode="&#xf1d1;" horiz-adv-x="1792" d="M874 -102v-66q-208 6 -385 109.5t-283 275.5l58 34q29 -49 73 -99l65 57q148 -168 368 -212l-17 -86q65 -12 121 -13zM276 428l-83 -28q22 -60 49 -112l-57 -33q-98 180 -98 385t98 385l57 -33q-30 -56 -49 -112l82 -28q-35 -100 -35 -212q0 -109 36 -212zM1528 251 l58 -34q-106 -172 -283 -275.5t-385 -109.5v66q56 1 121 13l-17 86q220 44 368 212l65 -57q44 50 73 99zM1377 805l-233 -80q14 -42 14 -85t-14 -85l232 -80q-31 -92 -98 -169l-185 162q-57 -67 -147 -85l48 -241q-52 -10 -98 -10t-98 10l48 241q-90 18 -147 85l-185 -162 q-67 77 -98 169l232 80q-14 42 -14 85t14 85l-233 80q33 93 99 169l185 -162q59 68 147 86l-48 240q44 10 98 10t98 -10l-48 -240q88 -18 147 -86l185 162q66 -76 99 -169zM874 1448v-66q-65 -2 -121 -13l17 -86q-220 -42 -368 -211l-65 56q-38 -42 -73 -98l-57 33 q106 172 282 275.5t385 109.5zM1705 640q0 -205 -98 -385l-57 33q27 52 49 112l-83 28q36 103 36 212q0 112 -35 212l82 28q-19 56 -49 112l57 33q98 -180 98 -385zM1585 1063l-57 -33q-35 56 -73 98l-65 -56q-148 169 -368 211l17 86q-56 11 -121 13v66q209 -6 385 -109.5 t282 -275.5zM1748 640q0 173 -67.5 331t-181.5 272t-272 181.5t-331 67.5t-331 -67.5t-272 -181.5t-181.5 -272t-67.5 -331t67.5 -331t181.5 -272t272 -181.5t331 -67.5t331 67.5t272 181.5t181.5 272t67.5 331zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71 t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
<glyph unicode="&#xf1d2;" d="M582 228q0 -66 -93 -66q-107 0 -107 63q0 64 98 64q102 0 102 -61zM546 694q0 -85 -74 -85q-77 0 -77 84q0 90 77 90q36 0 55 -25.5t19 -63.5zM712 769v125q-78 -29 -135 -29q-50 29 -110 29q-86 0 -145 -57t-59 -143q0 -50 29.5 -102t73.5 -67v-3q-38 -17 -38 -85 q0 -53 41 -77v-3q-113 -37 -113 -139q0 -45 20 -78.5t54 -51t72 -25.5t81 -8q224 0 224 188q0 67 -48 99t-126 46q-27 5 -51.5 20.5t-24.5 39.5q0 44 49 52q77 15 122 70t45 134q0 24 -10 52q37 9 49 13zM771 350h137q-2 27 -2 82v387q0 46 2 69h-137q3 -23 3 -71v-392 q0 -50 -3 -75zM1280 366v121q-30 -21 -68 -21q-53 0 -53 82v225h52q9 0 26.5 -1t26.5 -1v117h-105q0 82 3 102h-140q4 -24 4 -55v-47h-60v-117q36 3 37 3q3 0 11 -0.5t12 -0.5v-2h-2v-217q0 -37 2.5 -64t11.5 -56.5t24.5 -48.5t43.5 -31t66 -12q64 0 108 24zM924 1072 q0 36 -24 63.5t-60 27.5t-60.5 -27t-24.5 -64q0 -36 25 -62.5t60 -26.5t59.5 27t24.5 62zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
@ -555,7 +555,7 @@
<glyph unicode="&#xf237;" d="M1536 1536l-192 -448h192v-192h-274l-55 -128h329v-192h-411l-357 -832l-357 832h-411v192h329l-55 128h-274v192h192l-192 448h256l323 -768h378l323 768h256zM768 320l108 256h-216z" />
<glyph unicode="&#xf238;" d="M1088 1536q185 0 316.5 -93.5t131.5 -226.5v-896q0 -130 -125.5 -222t-305.5 -97l213 -202q16 -15 8 -35t-30 -20h-1056q-22 0 -30 20t8 35l213 202q-180 5 -305.5 97t-125.5 222v896q0 133 131.5 226.5t316.5 93.5h640zM768 192q80 0 136 56t56 136t-56 136t-136 56 t-136 -56t-56 -136t56 -136t136 -56zM1344 768v512h-1152v-512h1152z" />
<glyph unicode="&#xf239;" d="M1088 1536q185 0 316.5 -93.5t131.5 -226.5v-896q0 -130 -125.5 -222t-305.5 -97l213 -202q16 -15 8 -35t-30 -20h-1056q-22 0 -30 20t8 35l213 202q-180 5 -305.5 97t-125.5 222v896q0 133 131.5 226.5t316.5 93.5h640zM288 224q66 0 113 47t47 113t-47 113t-113 47 t-113 -47t-47 -113t47 -113t113 -47zM704 768v512h-544v-512h544zM1248 224q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47zM1408 768v512h-576v-512h576z" />
<glyph unicode="&#xf23a;" horiz-adv-x="1792" d="M1792 204v-209h-642v209h134v926h-6l-314 -1135h-243l-310 1135h-8v-926h135v-209h-538v209h69q21 0 43 19.5t22 37.5v881q0 18 -22 40t-43 22h-69v209h672l221 -821h6l223 821h670v-209h-71q-19 0 -41 -22t-22 -40v-881q0 -18 21.5 -37.5t41.5 -19.5h71z" />
<glyph unicode="&#xf23a;" horiz-adv-x="1792" d="M597 1115v-1173q0 -25 -12.5 -42.5t-36.5 -17.5q-17 0 -33 8l-465 233q-21 10 -35.5 33.5t-14.5 46.5v1140q0 20 10 34t29 14q14 0 44 -15l511 -256q3 -3 3 -5zM661 1014l534 -866l-534 266v600zM1792 996v-1054q0 -25 -14 -40.5t-38 -15.5t-47 13l-441 220zM1789 1116 q0 -3 -256.5 -419.5t-300.5 -487.5l-390 634l324 527q17 28 52 28q14 0 26 -6l541 -270q4 -2 4 -6z" />
<glyph unicode="&#xf23b;" d="M809 532l266 499h-112l-157 -312q-24 -48 -44 -92l-42 92l-155 312h-120l263 -493v-324h101v318zM1536 1408v-1536h-1536v1536h1536z" />
<glyph unicode="&#xf23c;" horiz-adv-x="2296" d="M478 -139q-8 -16 -27 -34.5t-37 -25.5q-25 -9 -51.5 3.5t-28.5 31.5q-1 22 40 55t68 38q23 4 34 -21.5t2 -46.5zM1819 -139q7 -16 26 -34.5t38 -25.5q25 -9 51.5 3.5t27.5 31.5q2 22 -39.5 55t-68.5 38q-22 4 -33 -21.5t-2 -46.5zM1867 -30q13 -27 56.5 -59.5t77.5 -41.5 q45 -13 82 4.5t37 50.5q0 46 -67.5 100.5t-115.5 59.5q-40 5 -63.5 -37.5t-6.5 -76.5zM428 -30q-13 -27 -56 -59.5t-77 -41.5q-45 -13 -82 4.5t-37 50.5q0 46 67.5 100.5t115.5 59.5q40 5 63 -37.5t6 -76.5zM1158 1094h1q-41 0 -76 -15q27 -8 44 -30.5t17 -49.5 q0 -35 -27 -60t-65 -25q-52 0 -80 43q-5 -23 -5 -42q0 -74 56 -126.5t135 -52.5q80 0 136 52.5t56 126.5t-56 126.5t-136 52.5zM1462 1312q-99 109 -220.5 131.5t-245.5 -44.5q27 60 82.5 96.5t118 39.5t121.5 -17t99.5 -74.5t44.5 -131.5zM2212 73q8 -11 -11 -42 q7 -23 7 -40q1 -56 -44.5 -112.5t-109.5 -91.5t-118 -37q-48 -2 -92 21.5t-66 65.5q-687 -25 -1259 0q-23 -41 -66.5 -65t-92.5 -22q-86 3 -179.5 80.5t-92.5 160.5q2 22 7 40q-19 31 -11 42q6 10 31 1q14 22 41 51q-7 29 2 38q11 10 39 -4q29 20 59 34q0 29 13 37 q23 12 51 -16q35 5 61 -2q18 -4 38 -19v73q-11 0 -18 2q-53 10 -97 44.5t-55 87.5q-9 38 0 81q15 62 93 95q2 17 19 35.5t36 23.5t33 -7.5t19 -30.5h13q46 -5 60 -23q3 -3 5 -7q10 1 30.5 3.5t30.5 3.5q-15 11 -30 17q-23 40 -91 43q0 6 1 10q-62 2 -118.5 18.5t-84.5 47.5 q-32 36 -42.5 92t-2.5 112q16 126 90 179q23 16 52 4.5t32 -40.5q0 -1 1.5 -14t2.5 -21t3 -20t5.5 -19t8.5 -10q27 -14 76 -12q48 46 98 74q-40 4 -162 -14l47 46q61 58 163 111q145 73 282 86q-20 8 -41 15.5t-47 14t-42.5 10.5t-47.5 11t-43 10q595 126 904 -139 q98 -84 158 -222q85 -10 121 9h1q5 3 8.5 10t5.5 19t3 19.5t3 21.5l1 14q3 28 32 40t52 -5q73 -52 91 -178q7 -57 -3.5 -113t-42.5 -91q-28 -32 -83.5 -48.5t-115.5 -18.5v-10q-71 -2 -95 -43q-14 -5 -31 -17q11 -1 32 -3.5t30 -3.5q1 4 5 8q16 18 60 23h13q5 18 19 30t33 8 t36 -23t19 -36q79 -32 93 -95q9 -40 1 -81q-12 -53 -56 -88t-97 -44q-10 -2 -17 -2q0 -49 -1 -73q20 15 38 19q26 7 61 2q28 28 51 16q14 -9 14 -37q33 -16 59 -34q27 13 38 4q10 -10 2 -38q28 -30 41 -51q23 8 31 -1zM1937 1025q0 -29 -9 -54q82 -32 112 -132 q4 37 -9.5 98.5t-41.5 90.5q-20 19 -36 17t-16 -20zM1859 925q35 -42 47.5 -108.5t-0.5 -124.5q67 13 97 45q13 14 18 28q-3 64 -31 114.5t-79 66.5q-15 -15 -52 -21zM1822 921q-30 0 -44 1q42 -115 53 -239q21 0 43 3q16 68 1 135t-53 100zM258 839q30 100 112 132 q-9 25 -9 54q0 18 -16.5 20t-35.5 -17q-28 -29 -41.5 -90.5t-9.5 -98.5zM294 737q29 -31 97 -45q-13 58 -0.5 124.5t47.5 108.5v0q-37 6 -52 21q-51 -16 -78.5 -66t-31.5 -115q9 -17 18 -28zM471 683q14 124 73 235q-19 -4 -55 -18l-45 -19v1q-46 -89 -20 -196q25 -3 47 -3z M1434 644q8 -38 16.5 -108.5t11.5 -89.5q3 -18 9.5 -21.5t23.5 4.5q40 20 62 85.5t23 125.5q-24 2 -146 4zM1152 1285q-116 0 -199 -82.5t-83 -198.5q0 -117 83 -199.5t199 -82.5t199 82.5t83 199.5q0 116 -83 198.5t-199 82.5zM1380 646q-106 2 -211 0v1q-1 -27 2.5 -86 t13.5 -66q29 -14 93.5 -14.5t95.5 10.5q9 3 11 39t-0.5 69.5t-4.5 46.5zM1112 447q8 4 9.5 48t-0.5 88t-4 63v1q-212 -3 -214 -3q-4 -20 -7 -62t0 -83t14 -46q34 -15 101 -16t101 10zM718 636q-16 -59 4.5 -118.5t77.5 -84.5q15 -8 24 -5t12 21q3 16 8 90t10 103 q-69 -2 -136 -6zM591 510q3 -23 -34 -36q132 -141 271.5 -240t305.5 -154q172 49 310.5 146t293.5 250q-33 13 -30 34l3 9v1v-1q-17 2 -50 5.5t-48 4.5q-26 -90 -82 -132q-51 -38 -82 1q-5 6 -9 14q-7 13 -17 62q-2 -5 -5 -9t-7.5 -7t-8 -5.5t-9.5 -4l-10 -2.5t-12 -2 l-12 -1.5t-13.5 -1t-13.5 -0.5q-106 -9 -163 11q-4 -17 -10 -26.5t-21 -15t-23 -7t-36 -3.5q-2 0 -3 -0.5t-3 -0.5h-3q-179 -17 -203 40q-2 -63 -56 -54q-47 8 -91 54q-12 13 -20 26q-17 29 -26 65q-58 -6 -87 -10q1 -2 4 -10zM507 -118q3 14 3 30q-17 71 -51 130t-73 70 q-41 12 -101.5 -14.5t-104.5 -80t-39 -107.5q35 -53 100 -93t119 -42q51 -2 94 28t53 79zM510 53q23 -63 27 -119q195 113 392 174q-98 52 -180.5 120t-179.5 165q-6 -4 -29 -13q0 -2 -1 -5t-1 -4q31 -18 22 -37q-12 -23 -56 -34q-10 -13 -29 -24h-1q-2 -83 1 -150 q19 -34 35 -73zM579 -113q532 -21 1145 0q-254 147 -428 196q-76 -35 -156 -57q-8 -3 -16 0q-65 21 -129 49q-208 -60 -416 -188h-1v-1q1 0 1 1zM1763 -67q4 54 28 120q14 38 33 71l-1 -1q3 77 3 153q-15 8 -30 25q-42 9 -56 33q-9 20 22 38q-2 4 -2 9q-16 4 -28 12 q-204 -190 -383 -284q198 -59 414 -176zM2155 -90q5 54 -39 107.5t-104 80t-102 14.5q-38 -11 -72.5 -70.5t-51.5 -129.5q0 -16 3 -30q10 -49 53 -79t94 -28q54 2 119 42t100 93z" />
<glyph unicode="&#xf23d;" horiz-adv-x="2304" d="M1524 -25q0 -68 -48 -116t-116 -48t-116.5 48t-48.5 116t48.5 116.5t116.5 48.5t116 -48.5t48 -116.5zM775 -25q0 -68 -48.5 -116t-116.5 -48t-116 48t-48 116t48 116.5t116 48.5t116.5 -48.5t48.5 -116.5zM0 1469q57 -60 110.5 -104.5t121 -82t136 -63t166 -45.5 t200 -31.5t250 -18.5t304 -9.5t372.5 -2.5q139 0 244.5 -5t181 -16.5t124 -27.5t71 -39.5t24 -51.5t-19.5 -64t-56.5 -76.5t-89.5 -91t-116 -104.5t-139 -119q-185 -157 -286 -247q29 51 76.5 109t94 105.5t94.5 98.5t83 91.5t54 80.5t13 70t-45.5 55.5t-116.5 41t-204 23.5 t-304 5q-168 -2 -314 6t-256 23t-204.5 41t-159.5 51.5t-122.5 62.5t-91.5 66.5t-68 71.5t-50.5 69.5t-40 68t-36.5 59.5z" />
@ -600,11 +600,11 @@
<glyph unicode="&#xf267;" horiz-adv-x="1792" d="M949 643q0 -26 -16.5 -45t-41.5 -19q-26 0 -45 16.5t-19 41.5q0 26 17 45t42 19t44 -16.5t19 -41.5zM964 585l350 581q-9 -8 -67.5 -62.5t-125.5 -116.5t-136.5 -127t-117 -110.5t-50.5 -51.5l-349 -580q7 7 67 62t126 116.5t136 127t117 111t50 50.5zM1611 640 q0 -201 -104 -371q-3 2 -17 11t-26.5 16.5t-16.5 7.5q-13 0 -13 -13q0 -10 59 -44q-74 -112 -184.5 -190.5t-241.5 -110.5l-16 67q-1 10 -15 10q-5 0 -8 -5.5t-2 -9.5l16 -68q-72 -15 -146 -15q-199 0 -372 105q1 2 13 20.5t21.5 33.5t9.5 19q0 13 -13 13q-6 0 -17 -14.5 t-22.5 -34.5t-13.5 -23q-113 75 -192 187.5t-110 244.5l69 15q10 3 10 15q0 5 -5.5 8t-10.5 2l-68 -15q-14 72 -14 139q0 206 109 379q2 -1 18.5 -12t30 -19t17.5 -8q13 0 13 12q0 6 -12.5 15.5t-32.5 21.5l-20 12q77 112 189 189t244 107l15 -67q2 -10 15 -10q5 0 8 5.5 t2 10.5l-15 66q71 13 134 13q204 0 379 -109q-39 -56 -39 -65q0 -13 12 -13q11 0 48 64q111 -75 187.5 -186t107.5 -241l-56 -12q-10 -2 -10 -16q0 -5 5.5 -8t9.5 -2l57 13q14 -72 14 -140zM1696 640q0 163 -63.5 311t-170.5 255t-255 170.5t-311 63.5t-311 -63.5 t-255 -170.5t-170.5 -255t-63.5 -311t63.5 -311t170.5 -255t255 -170.5t311 -63.5t311 63.5t255 170.5t170.5 255t63.5 311zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191 t191 -286t71 -348z" />
<glyph unicode="&#xf268;" horiz-adv-x="1792" d="M893 1536q240 2 451 -120q232 -134 352 -372l-742 39q-160 9 -294 -74.5t-185 -229.5l-276 424q128 159 311 245.5t383 87.5zM146 1131l337 -663q72 -143 211 -217t293 -45l-230 -451q-212 33 -385 157.5t-272.5 316t-99.5 411.5q0 267 146 491zM1732 962 q58 -150 59.5 -310.5t-48.5 -306t-153 -272t-246 -209.5q-230 -133 -498 -119l405 623q88 131 82.5 290.5t-106.5 277.5zM896 942q125 0 213.5 -88.5t88.5 -213.5t-88.5 -213.5t-213.5 -88.5t-213.5 88.5t-88.5 213.5t88.5 213.5t213.5 88.5z" />
<glyph unicode="&#xf269;" horiz-adv-x="1792" d="M903 -256q-283 0 -504.5 150.5t-329.5 398.5q-58 131 -67 301t26 332.5t111 312t179 242.5l-11 -281q11 14 68 15.5t70 -15.5q42 81 160.5 138t234.5 59q-54 -45 -119.5 -148.5t-58.5 -163.5q25 -8 62.5 -13.5t63 -7.5t68 -4t50.5 -3q15 -5 9.5 -45.5t-30.5 -75.5 q-5 -7 -16.5 -18.5t-56.5 -35.5t-101 -34l15 -189l-139 67q-18 -43 -7.5 -81.5t36 -66.5t65.5 -41.5t81 -6.5q51 9 98 34.5t83.5 45t73.5 17.5q61 -4 89.5 -33t19.5 -65q-1 -2 -2.5 -5.5t-8.5 -12.5t-18 -15.5t-31.5 -10.5t-46.5 -1q-60 -95 -144.5 -135.5t-209.5 -29.5 q74 -61 162.5 -82.5t168.5 -6t154.5 52t128 87.5t80.5 104q43 91 39 192.5t-37.5 188.5t-78.5 125q87 -38 137 -79.5t77 -112.5q15 170 -57.5 343t-209.5 284q265 -77 412 -279.5t151 -517.5q2 -127 -40.5 -255t-123.5 -238t-189 -196t-247.5 -135.5t-288.5 -49.5z" />
<glyph unicode="&#xf26a;" d="M768 -92q77 0 139.5 63t100.5 166t59 234.5t21 268.5t-21 268.5t-59 234.5t-100.5 166t-139.5 63t-139.5 -63t-100.5 -166t-59 -234.5t-21 -268.5t21 -268.5t59 -234.5t100.5 -166t139.5 -63zM768 -256q-184 0 -333 77t-240 203t-141 287t-50 329t50 329t141 287t240 203 t333 77q148 0 274 -50t214.5 -136t151.5 -201t92.5 -244t29.5 -265t-29.5 -265t-92.5 -244t-151.5 -201t-214.5 -136t-274 -50z" />
<glyph unicode="&#xf26b;" horiz-adv-x="1792" d="M716 -69q-143 35 -261.5 114t-197.5 191q-139 -300 -17 -398q26 -21 85 -24.5t127.5 9.5t141 41.5t122.5 66.5zM693 762h452q0 108 -61.5 169t-168.5 61q-103 0 -162.5 -62.5t-59.5 -167.5zM1724 1137h-34q26 102 22.5 170t-25 110t-63.5 57t-93.5 11t-115 -26.5 t-128.5 -56.5t-134 -79q129 -37 238.5 -113.5t185 -179t110 -231.5t15.5 -262h-1005q0 -60 10 -106t34 -85t69.5 -60t112.5 -21q87 0 142.5 44t72.5 122h540q-71 -230 -281.5 -377t-477.5 -147q-83 0 -159 15q-35 -40 -151 -94t-248 -78t-219 35q-78 60 -100 159t7 214 t88 242t143.5 248t173.5 226.5t177.5 183.5t156.5 112v24q-120 -37 -258.5 -137.5t-240.5 -207t-159 -195.5q4 106 34 201t80 169t118 135.5t147.5 100.5t168 65.5t180.5 29.5t185 -8q310 186 503 189h7q57 0 103 -18q80 -30 98 -132.5t-30 -248.5z" />
<glyph unicode="&#xf26a;" horiz-adv-x="1792" d="M1493 1308q-165 110 -359 110q-155 0 -293 -73t-240 -200q-75 -93 -119.5 -218t-48.5 -266v-42q4 -141 48.5 -266t119.5 -218q102 -127 240 -200t293 -73q194 0 359 110q-121 -108 -274.5 -168t-322.5 -60q-29 0 -43 1q-175 8 -333 82t-272 193t-181 281t-67 339 q0 182 71 348t191 286t286 191t348 71h3q168 -1 320.5 -60.5t273.5 -167.5zM1792 640q0 -192 -77 -362.5t-213 -296.5q-104 -63 -222 -63q-137 0 -255 84q154 56 253.5 233t99.5 405q0 227 -99 404t-253 234q119 83 254 83q119 0 226 -65q135 -125 210.5 -295t75.5 -361z " />
<glyph unicode="&#xf26b;" horiz-adv-x="1792" d="M1792 599q0 -56 -7 -104h-1151q0 -146 109.5 -244.5t257.5 -98.5q99 0 185.5 46.5t136.5 130.5h423q-56 -159 -170.5 -281t-267.5 -188.5t-321 -66.5q-187 0 -356 83q-228 -116 -394 -116q-237 0 -237 263q0 115 45 275q17 60 109 229q199 360 475 606 q-184 -79 -427 -354q63 274 283.5 449.5t501.5 175.5q30 0 45 -1q255 117 433 117q64 0 116 -13t94.5 -40.5t66.5 -76.5t24 -115q0 -116 -75 -286q101 -182 101 -390zM1722 1239q0 83 -53 132t-137 49q-108 0 -254 -70q121 -47 222.5 -131.5t170.5 -195.5q51 135 51 216z M128 2q0 -86 48.5 -132.5t134.5 -46.5q115 0 266 83q-122 72 -213.5 183t-137.5 245q-98 -205 -98 -332zM632 715h728q-5 142 -113 237t-251 95q-144 0 -251.5 -95t-112.5 -237z" />
<glyph unicode="&#xf26c;" horiz-adv-x="2048" d="M1792 288v960q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1248v-960q0 -66 -47 -113t-113 -47h-736v-128h352q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23 v64q0 14 9 23t23 9h352v128h-736q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
<glyph unicode="&#xf26d;" horiz-adv-x="1792" d="M138 1408h197q-70 -64 -126 -149q-36 -56 -59 -115t-30 -125.5t-8.5 -120t10.5 -132t21 -126t28 -136.5q4 -19 6 -28q51 -238 81 -329q57 -171 152 -275h-272q-48 0 -82 34t-34 82v1304q0 48 34 82t82 34zM1346 1408h308q48 0 82 -34t34 -82v-1304q0 -48 -34 -82t-82 -34 h-178q212 210 196 565l-469 -101q-2 -45 -12 -82t-31 -72t-59.5 -59.5t-93.5 -36.5q-123 -26 -199 40q-32 27 -53 61t-51.5 129t-64.5 258q-35 163 -45.5 263t-5.5 139t23 77q20 41 62.5 73t102.5 45q45 12 83.5 6.5t67 -17t54 -35t43 -48t34.5 -56.5l468 100 q-68 175 -180 287z" />
<glyph unicode="&#xf26e;" horiz-adv-x="2304" d="M1391 390v0l-1 1q-15 18 -34.5 37.5t-62.5 57.5t-93.5 62t-95.5 24q-48 0 -83 -21.5t-51 -54t-23 -59t-7 -47.5v0v0q0 -21 7 -48t23 -59t51 -53.5t83 -21.5q45 0 95.5 24t94 62.5t62 57t34.5 37.5zM2103 390q0 21 -7 47.5t-23 59t-51 54t-83 21.5q-45 0 -95.5 -24 t-94 -62.5t-62 -57t-34.5 -37.5l-1 -1v0v0l1 -1q15 -18 34.5 -37.5t62.5 -57.5t93.5 -62t95.5 -24q48 0 83 21.5t51 53.5t23 59t7 48zM2304 393q0 -69 -24 -137.5t-68 -126t-116 -93.5t-159 -36q-68 0 -134 24t-113.5 58.5t-84.5 69.5t-59.5 59t-25.5 24t-22.5 -24 t-54.5 -58.5t-81.5 -69.5t-115 -59t-143.5 -24q-65 0 -123.5 22.5t-96.5 54t-66.5 66.5t-41 59.5t-12.5 32.5q0 -8 -8.5 -26.5t-25 -45.5t-47 -55t-69 -52.5t-96.5 -40t-125 -15.5q-71 0 -130 15.5t-98.5 39.5t-70.5 56.5t-48 63.5t-27.5 63.5t-14 54t-3.5 36.5h217 q0 -55 49 -107.5t126 -52.5q79 0 134.5 67t55.5 148q0 80 -52 136.5t-138 56.5q-5 0 -13 -0.5t-31 -5t-43 -12t-42 -24.5t-34 -40h-195l102 583h602v-174h-445q-27 -159 -41 -248q4 0 16.5 13t31.5 28.5t65 28.5t108 13t114 -20.5t82.5 -49.5t51.5 -58.5t31 -50t11 -20.5 t13 25t36.5 60.5t60.5 71.5t97 61t133 25t140.5 -25t115.5 -60.5t83.5 -71.5t56.5 -61t21 -25q2 0 22 25t56 60.5t83.5 71.5t115.5 61t140 25q92 0 164.5 -35t115.5 -93t65 -125t22 -137z" />
<glyph unicode="&#xf26e;" d="M1401 -11l-6 -6q-113 -114 -259 -175q-154 -64 -317 -64q-165 0 -317 64q-148 63 -259 175q-113 112 -175 258q-42 103 -54 189q-4 28 48 36q51 8 56 -20q1 -1 1 -4q18 -90 46 -159q50 -124 152 -226q98 -98 226 -152q132 -56 276 -56q143 0 276 56q128 55 225 152l6 6 q10 10 25 6q12 -3 33 -22q36 -37 17 -58zM929 604l-66 -66l63 -63q21 -21 -7 -49q-17 -17 -32 -17q-10 0 -19 10l-62 61l-66 -66q-5 -5 -15 -5q-15 0 -31 16l-2 2q-18 15 -18 29q0 7 8 17l66 65l-66 66q-16 16 14 45q18 18 31 18q6 0 13 -5l65 -66l65 65q18 17 48 -13 q27 -27 11 -44zM1400 547q0 -118 -46 -228q-45 -105 -126 -186q-80 -80 -187 -126t-228 -46t-228 46t-187 126q-82 82 -125 186q-15 32 -15 40h-1q-9 27 43 44q50 16 60 -12q37 -99 97 -167h1v339v2q3 136 102 232q105 103 253 103q147 0 251 -103t104 -249 q0 -147 -104.5 -251t-250.5 -104q-58 0 -112 16q-28 11 -13 61q16 51 44 43l14 -3q14 -3 32.5 -6t30.5 -3q104 0 176 71.5t72 174.5q0 101 -72 171q-71 71 -175 71q-107 0 -178 -80q-64 -72 -64 -160v-413q110 -67 242 -67q96 0 185 36.5t156 103.5t103.5 155t36.5 183 q0 198 -141 339q-140 140 -339 140q-200 0 -340 -140q-53 -53 -77 -87l-2 -2q-8 -11 -13 -15.5t-21.5 -9.5t-38.5 3q-21 5 -36.5 16.5t-15.5 26.5v680q0 15 10.5 26.5t27.5 11.5h877q30 0 30 -55t-30 -55h-811v-483h1q40 42 102 84t108 61q109 46 231 46q121 0 228 -46 t187 -126q81 -81 126 -186q46 -112 46 -229zM1369 1128q9 -8 9 -18t-5.5 -18t-16.5 -21q-26 -26 -39 -26q-9 0 -16 7q-106 91 -207 133q-128 56 -276 56q-133 0 -262 -49q-27 -10 -45 37q-9 25 -8 38q3 16 16 20q130 57 299 57q164 0 316 -64q137 -58 235 -152z" />
<glyph unicode="&#xf270;" horiz-adv-x="1792" d="M1551 60q15 6 26 3t11 -17.5t-15 -33.5q-13 -16 -44 -43.5t-95.5 -68t-141 -74t-188 -58t-229.5 -24.5q-119 0 -238 31t-209 76.5t-172.5 104t-132.5 105t-84 87.5q-8 9 -10 16.5t1 12t8 7t11.5 2t11.5 -4.5q192 -117 300 -166q389 -176 799 -90q190 40 391 135z M1758 175q11 -16 2.5 -69.5t-28.5 -102.5q-34 -83 -85 -124q-17 -14 -26 -9t0 24q21 45 44.5 121.5t6.5 98.5q-5 7 -15.5 11.5t-27 6t-29.5 2.5t-35 0t-31.5 -2t-31 -3t-22.5 -2q-6 -1 -13 -1.5t-11 -1t-8.5 -1t-7 -0.5h-5.5h-4.5t-3 0.5t-2 1.5l-1.5 3q-6 16 47 40t103 30 q46 7 108 1t76 -24zM1364 618q0 -31 13.5 -64t32 -58t37.5 -46t33 -32l13 -11l-227 -224q-40 37 -79 75.5t-58 58.5l-19 20q-11 11 -25 33q-38 -59 -97.5 -102.5t-127.5 -63.5t-140 -23t-137.5 21t-117.5 65.5t-83 113t-31 162.5q0 84 28 154t72 116.5t106.5 83t122.5 57 t130 34.5t119.5 18.5t99.5 6.5v127q0 65 -21 97q-34 53 -121 53q-6 0 -16.5 -1t-40.5 -12t-56 -29.5t-56 -59.5t-48 -96l-294 27q0 60 22 119t67 113t108 95t151.5 65.5t190.5 24.5q100 0 181 -25t129.5 -61.5t81 -83t45 -86t12.5 -73.5v-589zM692 597q0 -86 70 -133 q66 -44 139 -22q84 25 114 123q14 45 14 101v162q-59 -2 -111 -12t-106.5 -33.5t-87 -71t-32.5 -114.5z" />
<glyph unicode="&#xf271;" horiz-adv-x="1792" d="M1536 1280q52 0 90 -38t38 -90v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128zM1152 1376v-288q0 -14 9 -23t23 -9 h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM384 1376v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM1536 -128v1024h-1408v-1024h1408zM896 448h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224 v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v224q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-224z" />
<glyph unicode="&#xf272;" horiz-adv-x="1792" d="M1152 416v-64q0 -14 -9 -23t-23 -9h-576q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h576q14 0 23 -9t9 -23zM128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23 t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47 t47 -113v-96h128q52 0 90 -38t38 -90z" />
@ -621,20 +621,35 @@
<glyph unicode="&#xf27d;" horiz-adv-x="1792" d="M1709 1018q-10 -236 -332 -651q-333 -431 -562 -431q-142 0 -240 263q-44 160 -132 482q-72 262 -157 262q-18 0 -127 -76l-77 98q24 21 108 96.5t130 115.5q156 138 241 146q95 9 153 -55.5t81 -203.5q44 -287 66 -373q55 -249 120 -249q51 0 154 161q101 161 109 246 q13 139 -109 139q-57 0 -121 -26q120 393 459 382q251 -8 236 -326z" />
<glyph unicode="&#xf27e;" d="M0 1408h1536v-1536h-1536v1536zM1085 293l-221 631l221 297h-634l221 -297l-221 -631l317 -304z" />
<glyph unicode="&#xf280;" d="M0 1408h1536v-1536h-1536v1536zM908 1088l-12 -33l75 -83l-31 -114l25 -25l107 57l107 -57l25 25l-31 114l75 83l-12 33h-95l-53 96h-32l-53 -96h-95zM641 925q32 0 44.5 -16t11.5 -63l174 21q0 55 -17.5 92.5t-50.5 56t-69 25.5t-85 7q-133 0 -199 -57.5t-66 -182.5v-72 h-96v-128h76q20 0 20 -8v-382q0 -14 -5 -20t-18 -7l-73 -7v-88h448v86l-149 14q-6 1 -8.5 1.5t-3.5 2.5t-0.5 4t1 7t0.5 10v387h191l38 128h-231q-6 0 -2 6t4 9v80q0 27 1.5 40.5t7.5 28t19.5 20t36.5 5.5zM1248 96v86l-54 9q-7 1 -9.5 2.5t-2.5 3t1 7.5t1 12v520h-275 l-23 -101l83 -22q23 -7 23 -27v-370q0 -14 -6 -18.5t-20 -6.5l-70 -9v-86h352z" />
<glyph unicode="&#xf281;" horiz-adv-x="1792" />
<glyph unicode="&#xf282;" horiz-adv-x="1792" />
<glyph unicode="&#xf283;" horiz-adv-x="1792" />
<glyph unicode="&#xf284;" horiz-adv-x="1792" />
<glyph unicode="&#xf285;" horiz-adv-x="1792" />
<glyph unicode="&#xf286;" horiz-adv-x="1792" />
<glyph unicode="&#xf287;" horiz-adv-x="1792" />
<glyph unicode="&#xf288;" horiz-adv-x="1792" />
<glyph unicode="&#xf289;" horiz-adv-x="1792" />
<glyph unicode="&#xf28a;" horiz-adv-x="1792" />
<glyph unicode="&#xf28b;" horiz-adv-x="1792" />
<glyph unicode="&#xf28c;" horiz-adv-x="1792" />
<glyph unicode="&#xf28d;" horiz-adv-x="1792" />
<glyph unicode="&#xf28e;" horiz-adv-x="1792" />
<glyph unicode="&#xf281;" horiz-adv-x="1792" d="M1792 690q0 -58 -29.5 -105.5t-79.5 -72.5q12 -46 12 -96q0 -155 -106.5 -287t-290.5 -208.5t-400 -76.5t-399.5 76.5t-290 208.5t-106.5 287q0 47 11 94q-51 25 -82 73.5t-31 106.5q0 82 58 140.5t141 58.5q85 0 145 -63q218 152 515 162l116 521q3 13 15 21t26 5 l369 -81q18 37 54 59.5t79 22.5q62 0 106 -43.5t44 -105.5t-44 -106t-106 -44t-105.5 43.5t-43.5 105.5l-334 74l-104 -472q300 -9 519 -160q58 61 143 61q83 0 141 -58.5t58 -140.5zM418 491q0 -62 43.5 -106t105.5 -44t106 44t44 106t-44 105.5t-106 43.5q-61 0 -105 -44 t-44 -105zM1228 136q11 11 11 26t-11 26q-10 10 -25 10t-26 -10q-41 -42 -121 -62t-160 -20t-160 20t-121 62q-11 10 -26 10t-25 -10q-11 -10 -11 -25.5t11 -26.5q43 -43 118.5 -68t122.5 -29.5t91 -4.5t91 4.5t122.5 29.5t118.5 68zM1225 341q62 0 105.5 44t43.5 106 q0 61 -44 105t-105 44q-62 0 -106 -43.5t-44 -105.5t44 -106t106 -44z" />
<glyph unicode="&#xf282;" horiz-adv-x="1792" d="M69 741h1q16 126 58.5 241.5t115 217t167.5 176t223.5 117.5t276.5 43q231 0 414 -105.5t294 -303.5q104 -187 104 -442v-188h-1125q1 -111 53.5 -192.5t136.5 -122.5t189.5 -57t213 -3t208 46.5t173.5 84.5v-377q-92 -55 -229.5 -92t-312.5 -38t-316 53 q-189 73 -311.5 249t-124.5 372q-3 242 111 412t325 268q-48 -60 -78 -125.5t-46 -159.5h635q8 77 -8 140t-47 101.5t-70.5 66.5t-80.5 41t-75 20.5t-56 8.5l-22 1q-135 -5 -259.5 -44.5t-223.5 -104.5t-176 -140.5t-138 -163.5z" />
<glyph unicode="&#xf283;" horiz-adv-x="2304" d="M0 32v608h2304v-608q0 -66 -47 -113t-113 -47h-1984q-66 0 -113 47t-47 113zM640 256v-128h384v128h-384zM256 256v-128h256v128h-256zM2144 1408q66 0 113 -47t47 -113v-224h-2304v224q0 66 47 113t113 47h1984z" />
<glyph unicode="&#xf284;" horiz-adv-x="1792" d="M1549 857q55 0 85.5 -28.5t30.5 -83.5t-34 -82t-91 -27h-136v-177h-25v398h170zM1710 267l-4 -11l-5 -10q-113 -230 -330.5 -366t-474.5 -136q-182 0 -348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71q244 0 454.5 -124t329.5 -338l2 -4l8 -16 q-30 -15 -136.5 -68.5t-163.5 -84.5q-6 -3 -479 -268q384 -183 799 -366zM896 -234q250 0 462.5 132.5t322.5 357.5l-287 129q-72 -140 -206 -222t-292 -82q-151 0 -280 75t-204 204t-75 280t75 280t204 204t280 75t280 -73.5t204 -204.5l280 143q-116 208 -321 329 t-443 121q-119 0 -232.5 -31.5t-209 -87.5t-176.5 -137t-137 -176.5t-87.5 -209t-31.5 -232.5t31.5 -232.5t87.5 -209t137 -176.5t176.5 -137t209 -87.5t232.5 -31.5z" />
<glyph unicode="&#xf285;" horiz-adv-x="1792" d="M1427 827l-614 386l92 151h855zM405 562l-184 116v858l1183 -743zM1424 697l147 -95v-858l-532 335zM1387 718l-500 -802h-855l356 571z" />
<glyph unicode="&#xf286;" horiz-adv-x="1792" d="M640 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1152 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1664 496v-752h-640v320q0 80 -56 136t-136 56t-136 -56t-56 -136v-320h-640v752q0 16 16 16h96 q16 0 16 -16v-112h128v624q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h16v393q-32 19 -32 55q0 26 19 45t45 19t45 -19t19 -45q0 -36 -32 -55v-9h272q16 0 16 -16v-224q0 -16 -16 -16h-272v-128h16q16 0 16 -16v-112h128 v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-624h128v112q0 16 16 16h96q16 0 16 -16z" />
<glyph unicode="&#xf287;" horiz-adv-x="2304" d="M2288 731q16 -8 16 -27t-16 -27l-320 -192q-8 -5 -16 -5q-9 0 -16 4q-16 10 -16 28v128h-858q37 -58 83 -165q16 -37 24.5 -55t24 -49t27 -47t27 -34t31.5 -26t33 -8h96v96q0 14 9 23t23 9h320q14 0 23 -9t9 -23v-320q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v96h-96 q-32 0 -61 10t-51 23.5t-45 40.5t-37 46t-33.5 57t-28.5 57.5t-28 60.5q-23 53 -37 81.5t-36 65t-44.5 53.5t-46.5 17h-360q-22 -84 -91 -138t-157 -54q-106 0 -181 75t-75 181t75 181t181 75q88 0 157 -54t91 -138h104q24 0 46.5 17t44.5 53.5t36 65t37 81.5q19 41 28 60.5 t28.5 57.5t33.5 57t37 46t45 40.5t51 23.5t61 10h107q21 57 70 92.5t111 35.5q80 0 136 -56t56 -136t-56 -136t-136 -56q-62 0 -111 35.5t-70 92.5h-107q-17 0 -33 -8t-31.5 -26t-27 -34t-27 -47t-24 -49t-24.5 -55q-46 -107 -83 -165h1114v128q0 18 16 28t32 -1z" />
<glyph unicode="&#xf288;" horiz-adv-x="1792" d="M1150 774q0 -56 -39.5 -95t-95.5 -39h-253v269h253q56 0 95.5 -39.5t39.5 -95.5zM1329 774q0 130 -91.5 222t-222.5 92h-433v-896h180v269h253q130 0 222 91.5t92 221.5zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348 t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
<glyph unicode="&#xf289;" horiz-adv-x="2304" d="M1645 438q0 59 -34 106.5t-87 68.5q-7 -45 -23 -92q-7 -24 -27.5 -38t-44.5 -14q-12 0 -24 3q-31 10 -45 38.5t-4 58.5q23 71 23 143q0 123 -61 227.5t-166 165.5t-228 61q-134 0 -247 -73t-167 -194q108 -28 188 -106q22 -23 22 -55t-22 -54t-54 -22t-55 22 q-75 75 -180 75q-106 0 -181 -74.5t-75 -180.5t75 -180.5t181 -74.5h1046q79 0 134.5 55.5t55.5 133.5zM1798 438q0 -142 -100.5 -242t-242.5 -100h-1046q-169 0 -289 119.5t-120 288.5q0 153 100 267t249 136q62 184 221 298t354 114q235 0 408.5 -158.5t196.5 -389.5 q116 -25 192.5 -118.5t76.5 -214.5zM2048 438q0 -175 -97 -319q-23 -33 -64 -33q-24 0 -43 13q-26 17 -32 48.5t12 57.5q71 104 71 233t-71 233q-18 26 -12 57t32 49t57.5 11.5t49.5 -32.5q97 -142 97 -318zM2304 438q0 -244 -134 -443q-23 -34 -64 -34q-23 0 -42 13 q-26 18 -32.5 49t11.5 57q108 164 108 358q0 195 -108 357q-18 26 -11.5 57.5t32.5 48.5q26 18 57 12t49 -33q134 -198 134 -442z" />
<glyph unicode="&#xf28a;" d="M1500 -13q0 -89 -63 -152.5t-153 -63.5t-153.5 63.5t-63.5 152.5q0 90 63.5 153.5t153.5 63.5t153 -63.5t63 -153.5zM1267 268q-115 -15 -192.5 -102.5t-77.5 -205.5q0 -74 33 -138q-146 -78 -379 -78q-109 0 -201 21t-153.5 54.5t-110.5 76.5t-76 85t-44.5 83 t-23.5 66.5t-6 39.5q0 19 4.5 42.5t18.5 56t36.5 58t64 43.5t94.5 18t94 -17.5t63 -41t35.5 -53t17.5 -49t4 -33.5q0 -34 -23 -81q28 -27 82 -42t93 -17l40 -1q115 0 190 51t75 133q0 26 -9 48.5t-31.5 44.5t-49.5 41t-74 44t-93.5 47.5t-119.5 56.5q-28 13 -43 20 q-116 55 -187 100t-122.5 102t-72 125.5t-20.5 162.5q0 78 20.5 150t66 137.5t112.5 114t166.5 77t221.5 28.5q120 0 220 -26t164.5 -67t109.5 -94t64 -105.5t19 -103.5q0 -46 -15 -82.5t-36.5 -58t-48.5 -36t-49 -19.5t-39 -5h-8h-32t-39 5t-44 14t-41 28t-37 46t-24 70.5 t-10 97.5q-15 16 -59 25.5t-81 10.5l-37 1q-68 0 -117.5 -31t-70.5 -70t-21 -76q0 -24 5 -43t24 -46t53 -51t97 -53.5t150 -58.5q76 -25 138.5 -53.5t109 -55.5t83 -59t60.5 -59.5t41 -62.5t26.5 -62t14.5 -63.5t6 -62t1 -62.5z" />
<glyph unicode="&#xf28b;" d="M704 352v576q0 14 -9 23t-23 9h-256q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h256q14 0 23 9t9 23zM1152 352v576q0 14 -9 23t-23 9h-256q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h256q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103 t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf28c;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM768 96q148 0 273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273 t73 -273t198 -198t273 -73zM864 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-192zM480 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-192z" />
<glyph unicode="&#xf28d;" d="M1088 352v576q0 14 -9 23t-23 9h-576q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h576q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" />
<glyph unicode="&#xf28e;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM768 96q148 0 273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273 t73 -273t198 -198t273 -73zM480 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h576q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-576z" />
<glyph unicode="&#xf290;" horiz-adv-x="1792" d="M1757 128l35 -313q3 -28 -16 -50q-19 -21 -48 -21h-1664q-29 0 -48 21q-19 22 -16 50l35 313h1722zM1664 967l86 -775h-1708l86 775q3 24 21 40.5t43 16.5h256v-128q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5v128h384v-128q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5v128h256q25 0 43 -16.5t21 -40.5zM1280 1152v-256q0 -26 -19 -45t-45 -19t-45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-256q0 -26 -19 -45t-45 -19t-45 19t-19 45v256q0 159 112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
<glyph unicode="&#xf291;" horiz-adv-x="2048" d="M1920 768q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5h-15l-115 -662q-8 -46 -44 -76t-82 -30h-1280q-46 0 -82 30t-44 76l-115 662h-15q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5h1792zM485 -32q26 2 43.5 22.5t15.5 46.5l-32 416q-2 26 -22.5 43.5 t-46.5 15.5t-43.5 -22.5t-15.5 -46.5l32 -416q2 -25 20.5 -42t43.5 -17h5zM896 32v416q0 26 -19 45t-45 19t-45 -19t-19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45zM1280 32v416q0 26 -19 45t-45 19t-45 -19t-19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45zM1632 27l32 416 q2 26 -15.5 46.5t-43.5 22.5t-46.5 -15.5t-22.5 -43.5l-32 -416q-2 -26 15.5 -46.5t43.5 -22.5h5q25 0 43.5 17t20.5 42zM476 1244l-93 -412h-132l101 441q19 88 89 143.5t160 55.5h167q0 26 19 45t45 19h384q26 0 45 -19t19 -45h167q90 0 160 -55.5t89 -143.5l101 -441 h-132l-93 412q-11 44 -45.5 72t-79.5 28h-167q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45h-167q-45 0 -79.5 -28t-45.5 -72z" />
<glyph unicode="&#xf292;" horiz-adv-x="1792" d="M991 512l64 256h-254l-64 -256h254zM1759 1016l-56 -224q-7 -24 -31 -24h-327l-64 -256h311q15 0 25 -12q10 -14 6 -28l-56 -224q-5 -24 -31 -24h-327l-81 -328q-7 -24 -31 -24h-224q-16 0 -26 12q-9 12 -6 28l78 312h-254l-81 -328q-7 -24 -31 -24h-225q-15 0 -25 12 q-9 12 -6 28l78 312h-311q-15 0 -25 12q-9 12 -6 28l56 224q7 24 31 24h327l64 256h-311q-15 0 -25 12q-10 14 -6 28l56 224q5 24 31 24h327l81 328q7 24 32 24h224q15 0 25 -12q9 -12 6 -28l-78 -312h254l81 328q7 24 32 24h224q15 0 25 -12q9 -12 6 -28l-78 -312h311 q15 0 25 -12q9 -12 6 -28z" />
<glyph unicode="&#xf293;" d="M841 483l148 -148l-149 -149zM840 1094l149 -149l-148 -148zM710 -130l464 464l-306 306l306 306l-464 464v-611l-255 255l-93 -93l320 -321l-320 -321l93 -93l255 255v-611zM1429 640q0 -209 -32 -365.5t-87.5 -257t-140.5 -162.5t-181.5 -86.5t-219.5 -24.5 t-219.5 24.5t-181.5 86.5t-140.5 162.5t-87.5 257t-32 365.5t32 365.5t87.5 257t140.5 162.5t181.5 86.5t219.5 24.5t219.5 -24.5t181.5 -86.5t140.5 -162.5t87.5 -257t32 -365.5z" />
<glyph unicode="&#xf294;" horiz-adv-x="1024" d="M596 113l173 172l-173 172v-344zM596 823l173 172l-173 172v-344zM628 640l356 -356l-539 -540v711l-297 -296l-108 108l372 373l-372 373l108 108l297 -296v711l539 -540z" />
<glyph unicode="&#xf295;" d="M1280 256q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM512 1024q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5 t112.5 -271.5zM1440 1344q0 -20 -13 -38l-1056 -1408q-19 -26 -51 -26h-160q-26 0 -45 19t-19 45q0 20 13 38l1056 1408q19 26 51 26h160q26 0 45 -19t19 -45zM768 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5 t271.5 -112.5t112.5 -271.5z" />
<glyph unicode="&#xf296;" horiz-adv-x="1792" />
<glyph unicode="&#xf297;" horiz-adv-x="1792" />
<glyph unicode="&#xf298;" horiz-adv-x="1792" />
<glyph unicode="&#xf299;" horiz-adv-x="1792" />
<glyph unicode="&#xf29a;" horiz-adv-x="1792" />
<glyph unicode="&#xf29b;" horiz-adv-x="1792" />
<glyph unicode="&#xf29c;" horiz-adv-x="1792" />
<glyph unicode="&#xf29d;" horiz-adv-x="1792" />
<glyph unicode="&#xf29e;" horiz-adv-x="1792" />
<glyph unicode="&#xf500;" horiz-adv-x="1792" />
</font>
</defs></svg>

Before

Width:  |  Height:  |  Size: 348 KiB

After

Width:  |  Height:  |  Size: 357 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -1,2 +0,0 @@
import CustomizationBase from 'admin/adapters/customization-base';
export default CustomizationBase;

View File

@ -16,7 +16,7 @@ export default Ember.Component.extend({
checked: {
get(value) { return !!value; },
set(value) {
this.set('value', value);
this.set('value', value);
return value;
}
}

View File

@ -0,0 +1,24 @@
import { on, observes } from 'ember-addons/ember-computed-decorators';
import autosize from 'discourse/lib/autosize';
export default Ember.TextArea.extend({
@on('didInsertElement')
_startWatching() {
Ember.run.scheduleOnce('afterRender', () => {
this.$().focus();
autosize(this.element);
});
},
@observes('value')
_updateAutosize() {
const evt = document.createEvent('Event');
evt.initEvent('autosize:update', true, false);
this.element.dispatchEvent(evt);
},
@on('willDestroyElement')
_disableAutosize() {
autosize.destroy(this.$());
}
});

View File

@ -1,3 +1,4 @@
export default Ember.Component.extend({
classNames: ["ip-lookup"],
@ -42,7 +43,8 @@ export default Ember.Component.extend({
self.set("totalOthersWithSameIP", result.total);
});
Discourse.AdminUser.findAll("active", data).then(function (users) {
const AdminUser = require('admin/models/admin-user').default;
AdminUser.findAll("active", data).then(function (users) {
self.setProperties({
other_accounts: users,
otherAccountsLoading: false,

View File

@ -18,15 +18,17 @@ export default Ember.Component.extend({
actions: {
submit: function() {
const Permalink = require('admin/models/permalink').default;
if (!this.get('formSubmitted')) {
const self = this;
self.set('formSubmitted', true);
const permalink = Discourse.Permalink.create({url: self.get('url'), permalink_type: self.get('permalinkType'), permalink_type_value: self.get('permalink_type_value')});
const permalink = Permalink.create({url: self.get('url'), permalink_type: self.get('permalinkType'), permalink_type_value: self.get('permalink_type_value')});
permalink.save().then(function(result) {
self.set('url', '');
self.set('permalink_type_value', '');
self.set('formSubmitted', false);
self.sendAction('action', Discourse.Permalink.create(result.permalink));
self.sendAction('action', Permalink.create(result.permalink));
Em.run.schedule('afterRender', function() { self.$('.permalink-url').focus(); });
}, function(e) {
self.set('formSubmitted', false);

View File

@ -10,7 +10,7 @@
uploadText="UPLOAD"
}}
**/
Discourse.ResumableUploadComponent = Ember.Component.extend(Discourse.StringBuffer, {
const ResumableUploadComponent = Ember.Component.extend(Discourse.StringBuffer, {
tagName: "button",
classNames: ["btn", "ru"],
classNameBindings: ["isUploading"],
@ -118,3 +118,5 @@ Discourse.ResumableUploadComponent = Ember.Component.extend(Discourse.StringBuff
}.on("willDestroyElement")
});
export default ResumableUploadComponent;

View File

@ -0,0 +1,18 @@
import computed from 'ember-addons/ember-computed-decorators';
export default Ember.Component.extend({
classNames: ['controls'],
buttonDisabled: Ember.computed.or('model.isSaving', 'saveDisabled'),
@computed('model.isSaving')
savingText(saving) {
return saving ? 'saving' : 'save';
},
actions: {
saveChanges() {
this.sendAction();
}
}
});

View File

@ -0,0 +1,75 @@
/**
A form to create an IP address that will be blocked or whitelisted.
Example usage:
{{screened-ip-address-form action="recordAdded"}}
where action is a callback on the controller or route that will get called after
the new record is successfully saved. It is called with the new ScreenedIpAddress record
as an argument.
**/
import ScreenedIpAddress from 'admin/models/screened-ip-address';
import computed from 'ember-addons/ember-computed-decorators';
import { on } from 'ember-addons/ember-computed-decorators';
export default Ember.Component.extend({
classNames: ['screened-ip-address-form'],
formSubmitted: false,
actionName: 'block',
@computed
adminWhitelistEnabled() {
return Discourse.SiteSettings.use_admin_ip_whitelist;
},
@computed("adminWhitelistEnabled")
actionNames(adminWhitelistEnabled) {
if (adminWhitelistEnabled) {
return [
{id: 'block', name: I18n.t('admin.logs.screened_ips.actions.block')},
{id: 'do_nothing', name: I18n.t('admin.logs.screened_ips.actions.do_nothing')},
{id: 'allow_admin', name: I18n.t('admin.logs.screened_ips.actions.allow_admin')}
];
} else {
return [
{id: 'block', name: I18n.t('admin.logs.screened_ips.actions.block')},
{id: 'do_nothing', name: I18n.t('admin.logs.screened_ips.actions.do_nothing')}
];
}
},
actions: {
submit() {
if (!this.get('formSubmitted')) {
this.set('formSubmitted', true);
const screenedIpAddress = ScreenedIpAddress.create({
ip_address: this.get('ip_address'),
action_name: this.get('actionName')
});
screenedIpAddress.save().then(result => {
this.setProperties({ ip_address: '', formSubmitted: false });
this.sendAction('action', ScreenedIpAddress.create(result.screened_ip_address));
Ember.run.schedule('afterRender', () => this.$('.ip-address-input').focus());
}).catch(e => {
this.set('formSubmitted', false);
const msg = (e.responseJSON && e.responseJSON.errors) ?
I18n.t("generic_error_with_reason", {error: e.responseJSON.errors.join('. ')}) :
I18n.t("generic_error");
bootbox.alert(msg, () => this.$('.ip-address-input').focus());
});
}
}
},
@on("didInsertElement")
_init() {
Ember.run.schedule('afterRender', () => {
this.$('.ip-address-input').keydown(e => {
if (e.keyCode === 13) {
this.send('submit');
}
});
});
}
});

View File

@ -1,65 +0,0 @@
/**
A form to create an IP address that will be blocked or whitelisted.
Example usage:
{{screened-ip-address-form action="recordAdded"}}
where action is a callback on the controller or route that will get called after
the new record is successfully saved. It is called with the new ScreenedIpAddress record
as an argument.
@class ScreenedIpAddressFormComponent
@extends Ember.Component
@namespace Discourse
@module Discourse
**/
Discourse.ScreenedIpAddressFormComponent = Ember.Component.extend({
classNames: ['screened-ip-address-form'],
formSubmitted: false,
actionName: 'block',
actionNames: function() {
return [
{id: 'block', name: I18n.t('admin.logs.screened_ips.actions.block')},
{id: 'do_nothing', name: I18n.t('admin.logs.screened_ips.actions.do_nothing')},
{id: 'allow_admin', name: I18n.t('admin.logs.screened_ips.actions.allow_admin')}
];
}.property(),
actions: {
submit: function() {
if (!this.get('formSubmitted')) {
var self = this;
this.set('formSubmitted', true);
var screenedIpAddress = Discourse.ScreenedIpAddress.create({ip_address: this.get('ip_address'), action_name: this.get('actionName')});
screenedIpAddress.save().then(function(result) {
self.set('ip_address', '');
self.set('formSubmitted', false);
self.sendAction('action', Discourse.ScreenedIpAddress.create(result.screened_ip_address));
Em.run.schedule('afterRender', function() { self.$('.ip-address-input').focus(); });
}, function(e) {
self.set('formSubmitted', false);
var msg;
if (e.responseJSON && e.responseJSON.errors) {
msg = I18n.t("generic_error_with_reason", {error: e.responseJSON.errors.join('. ')});
} else {
msg = I18n.t("generic_error");
}
bootbox.alert(msg, function() { self.$('.ip-address-input').focus(); });
});
}
}
},
didInsertElement: function() {
var self = this;
this._super();
Em.run.schedule('afterRender', function() {
self.$('.ip-address-input').keydown(function(e) {
if (e.keyCode === 13) { // enter key
self.send('submit');
}
});
});
}
});

View File

@ -0,0 +1,25 @@
import { on } from 'ember-addons/ember-computed-decorators';
export default Ember.Component.extend({
classNames: ['site-text'],
classNameBindings: ['siteText.overridden'],
@on('didInsertElement')
highlightTerm() {
const term = this.get('term');
if (term) {
this.$('.site-text-id, .site-text-value').highlight(term, {className: 'text-highlight'});
}
this.$('.site-text-value').ellipsis();
},
click() {
this.send('edit');
},
actions: {
edit() {
this.sendAction('editAction', this.get('siteText'));
}
}
});

View File

@ -1,3 +1,5 @@
import ApiKey from 'admin/models/api-key';
/**
This controller supports the interface for dealing with API keys
@ -16,7 +18,7 @@ export default Ember.ArrayController.extend({
**/
generateMasterKey: function() {
var self = this;
Discourse.ApiKey.generateMasterKey().then(function (key) {
ApiKey.generateMasterKey().then(function (key) {
self.get('model').pushObject(key);
});
},
@ -25,7 +27,7 @@ export default Ember.ArrayController.extend({
Creates an API key instance with internal user object
@method regenerateKey
@param {Discourse.ApiKey} key the key to regenerate
@param {ApiKey} key the key to regenerate
**/
regenerateKey: function(key) {
bootbox.confirm(I18n.t("admin.api.confirm_regen"), I18n.t("no_value"), I18n.t("yes_value"), function(result) {
@ -39,7 +41,7 @@ export default Ember.ArrayController.extend({
Revokes an API key
@method revokeKey
@param {Discourse.ApiKey} key the key to revoke
@param {ApiKey} key the key to revoke
**/
revokeKey: function(key) {
var self = this;

View File

@ -14,7 +14,6 @@ export default Ember.Controller.extend(BufferedContent, {
readOnly: Ember.computed.alias('buffered.system'),
showDisplayName: propertyNotEqual('name', 'displayName'),
canEditDescription: Em.computed.none('buffered.translatedDescription'),
hasQuery: function() {
const bQuery = this.get('buffered.query');
@ -37,6 +36,7 @@ export default Ember.Controller.extend(BufferedContent, {
'listable', 'auto_revoke',
'enabled', 'show_posts',
'target_posts', 'name', 'description',
'long_description',
'icon', 'image', 'query', 'badge_grouping_id',
'trigger', 'badge_type_id'],
self = this;
@ -68,7 +68,8 @@ export default Ember.Controller.extend(BufferedContent, {
model = this.get('model');
this.get('model').save(data).then(function() {
if (newBadge) {
self.get('controllers.admin-badges').pushObject(model);
var adminBadgesController = self.get('controllers.admin-badges');
if (!adminBadgesController.contains(model)) adminBadgesController.pushObject(model);
self.transitionToRoute('adminBadges.show', model.get('id'));
} else {
self.commitBuffer();

View File

@ -0,0 +1,37 @@
import { popupAjaxError } from 'discourse/lib/ajax-error';
import { bufferedProperty } from 'discourse/mixins/buffered-content';
export default Ember.Controller.extend(bufferedProperty('emailTemplate'), {
saved: false,
hasMultipleSubjects: function() {
const buffered = this.get('buffered');
if (buffered.getProperties('subject')['subject']) {
return false;
} else {
return buffered.getProperties('id')['id'];
}
}.property("buffered"),
actions: {
saveChanges() {
const buffered = this.get('buffered');
this.get('emailTemplate').save(buffered.getProperties('subject', 'body')).then(() => {
this.set('saved', true);
}).catch(popupAjaxError);
},
revertChanges() {
this.set('saved', false);
bootbox.confirm(I18n.t('admin.customize.email_templates.revert_confirm'), result => {
if (result) {
this.get('emailTemplate').revert().then(props => {
const buffered = this.get('buffered');
buffered.setProperties(props);
this.commitBuffer();
}).catch(popupAjaxError);
}
});
}
}
});

View File

@ -0,0 +1,6 @@
export default Ember.Controller.extend({
titleSorting: ['title'],
emailTemplates: null,
sortedTemplates: Ember.computed.sort('emailTemplates', 'titleSorting')
});

View File

@ -1,4 +1,5 @@
import { setting } from 'discourse/lib/computed';
import AdminDashboard from 'admin/models/admin-dashboard';
// This controller supports the default interface when you enter the admin section.
export default Ember.Controller.extend({
@ -26,7 +27,7 @@ export default Ember.Controller.extend({
this.set('loadingProblems', true);
this.set('problemsFetchedAt', new Date());
var c = this;
Discourse.AdminDashboard.fetchProblems().then(function(d) {
AdminDashboard.fetchProblems().then(function(d) {
c.set('problems', d.problems);
c.set('loadingProblems', false);
if( d.problems && d.problems.length > 0 ) {

View File

@ -1,3 +0,0 @@
import AdminEmailSkippedController from "admin/controllers/admin-email-skipped";
export default AdminEmailSkippedController.extend();

View File

@ -0,0 +1,21 @@
import IncomingEmail from 'admin/models/incoming-email';
export default Ember.Controller.extend({
loading: false,
actions: {
loadMore() {
if (this.get("loading") || this.get("model.allLoaded")) { return; }
this.set('loading', true);
IncomingEmail.findAll(this.get("filter"), this.get("model.length"))
.then(incoming => {
if (incoming.length < 50) { this.get("model").set("allLoaded", true); }
this.get("model").addObjects(incoming);
}).finally(() => {
this.set('loading', false);
});
}
}
});

View File

@ -0,0 +1,20 @@
import EmailLog from 'admin/models/email-log';
export default Ember.Controller.extend({
loading: false,
actions: {
loadMore() {
if (this.get("loading") || this.get("model.allLoaded")) { return; }
this.set('loading', true);
return EmailLog.findAll(this.get("filter"), this.get("model.length"))
.then(logs => {
if (logs.length < 50) { this.get("model").set("allLoaded", true); }
this.get("model").addObjects(logs);
}).finally(() => {
this.set('loading', false);
});
}
}
});

View File

@ -1,3 +1,5 @@
import EmailPreview from 'admin/models/email-preview';
export default Ember.Controller.extend({
actions: {
@ -5,7 +7,7 @@ export default Ember.Controller.extend({
const model = this.get('model');
this.set('loading', true);
Discourse.EmailPreview.findDigest(this.get('lastSeen')).then(email => {
EmailPreview.findDigest(this.get('lastSeen'), this.get('username')).then(email => {
model.setProperties(email.getProperties('html_content', 'text_content'));
this.set('loading', false);
});

View File

@ -0,0 +1,9 @@
import AdminEmailIncomingsController from 'admin/controllers/admin-email-incomings';
import debounce from 'discourse/lib/debounce';
import IncomingEmail from 'admin/models/incoming-email';
export default AdminEmailIncomingsController.extend({
filterIncomingEmails: debounce(function() {
IncomingEmail.findAll(this.get("filter")).then(incomings => this.set("model", incomings));
}, 250).observes("filter.{from,to,subject}")
});

View File

@ -0,0 +1,9 @@
import AdminEmailIncomingsController from 'admin/controllers/admin-email-incomings';
import debounce from 'discourse/lib/debounce';
import IncomingEmail from 'admin/models/incoming-email';
export default AdminEmailIncomingsController.extend({
filterIncomingEmails: debounce(function() {
IncomingEmail.findAll(this.get("filter")).then(incomings => this.set("model", incomings));
}, 250).observes("filter.{from,to,subject,error}")
});

View File

@ -1,11 +1,9 @@
import AdminEmailLogsController from 'admin/controllers/admin-email-logs';
import debounce from 'discourse/lib/debounce';
import EmailLog from 'admin/models/email-log';
export default Ember.Controller.extend({
export default AdminEmailLogsController.extend({
filterEmailLogs: debounce(function() {
var self = this;
Discourse.EmailLog.findAll(this.get("filter")).then(function(logs) {
self.set("model", logs);
});
}, 250).observes("filter.user", "filter.address", "filter.type", "filter.reply_key")
EmailLog.findAll(this.get("filter")).then(logs => this.set("model", logs));
}, 250).observes("filter.{user,address,type,reply_key}")
});

View File

@ -1,10 +1,9 @@
import AdminEmailLogsController from 'admin/controllers/admin-email-logs';
import debounce from 'discourse/lib/debounce';
import EmailLog from 'admin/models/email-log';
export default Ember.Controller.extend({
export default AdminEmailLogsController.extend({
filterEmailLogs: debounce(function() {
var self = this;
Discourse.EmailLog.findAll(this.get("filter")).then(function(logs) {
self.set("model", logs);
});
}, 250).observes("filter.user", "filter.address", "filter.type", "filter.skipped_reason")
EmailLog.findAll(this.get("filter")).then(logs => this.set("model", logs));
}, 250).observes("filter.{user,address,type,skipped_reason}")
});

View File

@ -1,3 +1,5 @@
import FlaggedPost from 'admin/models/flagged-post';
export default Ember.ArrayController.extend({
query: null,
@ -30,7 +32,7 @@ export default Ember.ArrayController.extend({
loadMore(){
var flags = this.get("model");
return Discourse.FlaggedPost.findAll(this.get("query"),flags.length+1).then(function(data){
return FlaggedPost.findAll(this.get("query"),flags.length+1).then(function(data){
if(data.length===0){
flags.set("allLoaded",true);
}

View File

@ -4,6 +4,7 @@ import { propertyEqual } from 'discourse/lib/computed';
export default Ember.Controller.extend({
needs: ['adminGroupsType'],
disableSave: false,
savingStatus: '',
currentPage: function() {
if (this.get("model.user_count") === 0) { return 0; }
@ -67,6 +68,22 @@ export default Ember.Controller.extend({
});
},
removeOwner(member) {
const self = this,
message = I18n.t("admin.groups.delete_owner_confirm", { username: member.get("username"), group: this.get("model.name") });
return bootbox.confirm(message, I18n.t("no_value"), I18n.t("yes_value"), function(confirm) {
if (confirm) {
self.get("model").removeOwner(member);
}
});
},
addOwners() {
if (Em.isEmpty(this.get("model.ownerUsernames"))) { return; }
this.get("model").addOwners(this.get("model.ownerUsernames")).catch(popupAjaxError);
this.set("model.ownerUsernames", null);
},
addMembers() {
if (Em.isEmpty(this.get("model.usernames"))) { return; }
this.get("model").addMembers(this.get("model.usernames")).catch(popupAjaxError);
@ -79,12 +96,15 @@ export default Ember.Controller.extend({
groupType = groupsController.get("type");
this.set('disableSave', true);
this.set('savingStatus', I18n.t('saving'));
let promise = group.get("id") ? group.save() : group.create().then(() => groupsController.addObject(group));
promise.then(() => this.transitionToRoute("adminGroup", groupType, group.get('name')))
.catch(popupAjaxError)
.finally(() => this.set('disableSave', false));
promise.then(() => {
this.transitionToRoute("adminGroup", groupType, group.get('name'));
this.set('savingStatus', I18n.t('saved'));
}).catch(popupAjaxError)
.finally(() => this.set('disableSave', false));
},
destroy() {

View File

@ -0,0 +1,34 @@
import computed from 'ember-addons/ember-computed-decorators';
import { popupAjaxError } from 'discourse/lib/ajax-error';
export default Ember.Controller.extend({
users: null,
groupId: null,
saving: false,
@computed('saving', 'users', 'groupId')
buttonDisabled(saving, users, groupId) {
return saving || !groupId || !users || !users.length;
},
actions: {
addToGroup() {
if (this.get('saving')) { return; }
const users = this.get('users').split("\n")
.uniq()
.reject(x => x.length === 0);
this.set('saving', true);
Discourse.ajax('/admin/groups/bulk', {
data: { users, group_id: this.get('groupId') },
method: 'PUT'
}).then(() => {
this.transitionToRoute('adminGroups.bulkComplete');
}).catch(popupAjaxError).finally(() => {
this.set('saving', false);
});
}
}
});

View File

@ -1,5 +1,6 @@
import { exportEntity } from 'discourse/lib/export-csv';
import { outputExportResult } from 'discourse/lib/export-result';
import ScreenedEmail from 'admin/models/screened-email';
export default Ember.ArrayController.extend({
loading: false,
@ -20,7 +21,7 @@ export default Ember.ArrayController.extend({
show() {
var self = this;
self.set('loading', true);
Discourse.ScreenedEmail.findAll().then(function(result) {
ScreenedEmail.findAll().then(function(result) {
self.set('model', result);
self.set('loading', false);
});

View File

@ -1,6 +1,7 @@
import debounce from 'discourse/lib/debounce';
import { outputExportResult } from 'discourse/lib/export-result';
import { exportEntity } from 'discourse/lib/export-csv';
import ScreenedIpAddress from 'admin/models/screened-ip-address';
export default Ember.ArrayController.extend({
loading: false,
@ -10,7 +11,7 @@ export default Ember.ArrayController.extend({
show: debounce(function() {
var self = this;
self.set('loading', true);
Discourse.ScreenedIpAddress.findAll(this.get("filter")).then(function(result) {
ScreenedIpAddress.findAll(this.get("filter")).then(function(result) {
self.set('model', result);
self.set('loading', false);
});
@ -26,7 +27,7 @@ export default Ember.ArrayController.extend({
return bootbox.confirm(I18n.t("admin.logs.screened_ips.roll_up_confirm"), I18n.t("no_value"), I18n.t("yes_value"), function (confirmed) {
if (confirmed) {
self.set("loading", true);
return Discourse.ScreenedIpAddress.rollUp().then(function(results) {
return ScreenedIpAddress.rollUp().then(function(results) {
if (results && results.subnets) {
if (results.subnets.length > 0) {
self.send("show");

View File

@ -1,5 +1,6 @@
import { exportEntity } from 'discourse/lib/export-csv';
import { outputExportResult } from 'discourse/lib/export-result';
import ScreenedUrl from 'admin/models/screened-url';
export default Ember.ArrayController.extend({
loading: false,
@ -7,7 +8,7 @@ export default Ember.ArrayController.extend({
show() {
const self = this;
self.set('loading', true);
Discourse.ScreenedUrl.findAll().then(function(result) {
ScreenedUrl.findAll().then(function(result) {
self.set('model', result);
self.set('loading', false);
});

View File

@ -1,5 +1,6 @@
import { exportEntity } from 'discourse/lib/export-csv';
import { outputExportResult } from 'discourse/lib/export-result';
import StaffActionLog from 'admin/models/staff-action-log';
export default Ember.ArrayController.extend({
loading: false,
@ -36,7 +37,7 @@ export default Ember.ArrayController.extend({
});
this.set('filterCount', count);
Discourse.StaffActionLog.findAll(params).then(function(result) {
StaffActionLog.findAll(params).then(function(result) {
self.set('model', result);
}).finally(function() {
self.set('loading', false);

View File

@ -1,4 +1,5 @@
import debounce from 'discourse/lib/debounce';
import Permalink from 'admin/models/permalink';
export default Ember.ArrayController.extend({
loading: false,
@ -7,7 +8,7 @@ export default Ember.ArrayController.extend({
show: debounce(function() {
var self = this;
self.set('loading', true);
Discourse.Permalink.findAll(self.get("filter")).then(function(result) {
Permalink.findAll(self.get("filter")).then(function(result) {
self.set('model', result);
self.set('loading', false);
});

View File

@ -1,5 +1,7 @@
import { exportEntity } from 'discourse/lib/export-csv';
import { outputExportResult } from 'discourse/lib/export-result';
import Report from 'admin/models/report';
import computed from 'ember-addons/ember-computed-decorators';
export default Ember.Controller.extend({
viewMode: 'table',
@ -8,22 +10,32 @@ export default Ember.Controller.extend({
startDate: null,
endDate: null,
categoryId: null,
groupId: null,
refreshing: false,
categoryOptions: function() {
var arr = [{name: I18n.t('category.all'), value: 'all'}];
return arr.concat( Discourse.Site.currentProp('sortedCategories').map(function(i) { return {name: i.get('name'), value: i.get('id') }; }) );
}.property(),
@computed()
categoryOptions() {
const arr = [{name: I18n.t('category.all'), value: 'all'}];
return arr.concat(Discourse.Site.currentProp('sortedCategories').map((i) => {return {name: i.get('name'), value: i.get('id')};}));
},
@computed()
groupOptions() {
const arr = [{name: I18n.t('admin.dashboard.reports.groups'), value: 'all'}];
return arr.concat(this.site.groups.map((i) => {return {name: i['name'], value: i['id']};}));
},
@computed('model.type')
showGroupOptions(modelType) {
return modelType === "visits" || modelType === "signups" || modelType === "profile_views";
},
actions: {
refreshReport() {
var q;
this.set("refreshing", true);
if (this.get('categoryId') === "all") {
q = Discourse.Report.find(this.get("model.type"), this.get("startDate"), this.get("endDate"));
} else {
q = Discourse.Report.find(this.get("model.type"), this.get("startDate"), this.get("endDate"), this.get("categoryId"));
}
q = Report.find(this.get("model.type"), this.get("startDate"), this.get("endDate"), this.get("categoryId"), this.get("groupId"));
q.then(m => this.set("model", m)).finally(() => this.set("refreshing", false));
},
@ -40,7 +52,8 @@ export default Ember.Controller.extend({
name: this.get("model.type"),
start_date: this.get('startDate'),
end_date: this.get('endDate'),
category_id: this.get('categoryId') === 'all' ? undefined : this.get('categoryId')
category_id: this.get('categoryId') === 'all' ? undefined : this.get('categoryId'),
group_id: this.get('groupId') === 'all' ? undefined : this.get('groupId')
}).then(outputExportResult);
}
}

View File

@ -5,7 +5,7 @@ export default Ember.ArrayController.extend({
onlyOverridden: false,
filtered: Ember.computed.notEmpty('filter'),
filterContentNow: function(category) {
filterContentNow(category) {
// If we have no content, don't bother filtering anything
if (!!Ember.isEmpty(this.get('allSiteSettings'))) return;
@ -20,12 +20,13 @@ export default Ember.ArrayController.extend({
return;
}
const self = this,
matchesGroupedByCategory = [{nameKey: 'all_results', name: I18n.t('admin.site_settings.categories.all_results'), siteSettings: []}];
const all = {nameKey: 'all_results', name: I18n.t('admin.site_settings.categories.all_results'), siteSettings: []};
const matchesGroupedByCategory = [all];
this.get('allSiteSettings').forEach(function(settingsCategory) {
const matches = settingsCategory.siteSettings.filter(function(item) {
if (self.get('onlyOverridden') && !item.get('overridden')) return false;
const matches = [];
this.get('allSiteSettings').forEach(settingsCategory => {
const siteSettings = settingsCategory.siteSettings.filter(item => {
if (this.get('onlyOverridden') && !item.get('overridden')) return false;
if (filter) {
if (item.get('setting').toLowerCase().indexOf(filter) > -1) return true;
if (item.get('setting').toLowerCase().replace(/_/g, ' ').indexOf(filter) > -1) return true;
@ -36,16 +37,20 @@ export default Ember.ArrayController.extend({
return true;
}
});
if (matches.length > 0) {
matchesGroupedByCategory[0].siteSettings.pushObjects(matches);
if (siteSettings.length > 0) {
matches.pushObjects(siteSettings);
matchesGroupedByCategory.pushObject({
nameKey: settingsCategory.nameKey,
name: I18n.t('admin.site_settings.categories.' + settingsCategory.nameKey),
siteSettings: matches
siteSettings,
count: siteSettings.length
});
}
});
all.siteSettings.pushObjects(matches.slice(0, 30));
all.count = matches.length;
this.set('model', matchesGroupedByCategory);
this.transitionToRoute("adminSiteSettingsCategory", category || "all_results");
},
@ -60,10 +65,7 @@ export default Ember.ArrayController.extend({
actions: {
clearFilter() {
this.setProperties({
filter: '',
onlyOverridden: false
});
this.setProperties({ filter: '', onlyOverridden: false });
},
toggleMenu() {

View File

@ -1,16 +1,29 @@
export default Ember.Controller.extend({
saved: false,
import { popupAjaxError } from 'discourse/lib/ajax-error';
import { bufferedProperty } from 'discourse/mixins/buffered-content';
saveDisabled: function() {
if (this.get('model.isSaving')) { return true; }
if ((!this.get('allow_blank')) && Ember.isEmpty(this.get('model.value'))) { return true; }
return false;
}.property('model.iSaving', 'model.value'),
export default Ember.Controller.extend(bufferedProperty('siteText'), {
saved: false,
actions: {
saveChanges() {
const model = this.get('model');
model.save(model.getProperties('value')).then(() => this.set('saved', true));
const buffered = this.get('buffered');
this.get('siteText').save(buffered.getProperties('value')).then(() => {
this.commitBuffer();
this.set('saved', true);
}).catch(popupAjaxError);
},
revertChanges() {
this.set('saved', false);
bootbox.confirm(I18n.t('admin.site_text.revert_confirm'), result => {
if (result) {
this.get('siteText').revert().then(props => {
const buffered = this.get('buffered');
buffered.setProperties(props);
this.commitBuffer();
}).catch(popupAjaxError);
}
});
}
}
});

View File

@ -0,0 +1,51 @@
import { default as computed } from 'ember-addons/ember-computed-decorators';
export default Ember.Controller.extend({
_q: null,
searching: false,
siteTexts: null,
preferred: false,
_overridden: null,
queryParams: ['q', 'overridden'],
@computed
overridden: {
set(value) {
if (!value || value === "false") { value = false; }
this._overridden = value;
return value;
},
get() {
return this._overridden;
}
},
@computed
q: {
set(value) {
if (Ember.isEmpty(value)) { value = null; }
this._q = value;
return value;
},
get() {
return this._q;
}
},
_performSearch() {
this.store.find('site-text', this.getProperties('q', 'overridden')).then(results => {
this.set('siteTexts', results);
}).finally(() => this.set('searching', false));
},
actions: {
edit(siteText) {
this.transitionToRoute('adminSiteText.edit', siteText.get('id'));
},
search() {
this.set('searching', true);
Ember.run.debounce(this, this._performSearch, 400);
}
}
});

View File

@ -1 +0,0 @@
export default Ember.ArrayController.extend();

View File

@ -56,12 +56,12 @@ export default Ember.ArrayController.extend({
var badges = [];
this.get('badges').forEach(function(badge) {
if (badge.get('multiple_grant') || !granted[badge.get('id')]) {
if (badge.get('enabled') && (badge.get('multiple_grant') || !granted[badge.get('id')])) {
badges.push(badge);
}
});
return _.sortBy(badges, "name");
return _.sortBy(badges, badge => badge.get('name'));
}.property('badges.@each', 'model.@each'),
/**

View File

@ -1,5 +1,6 @@
import debounce from 'discourse/lib/debounce';
import { i18n } from 'discourse/lib/computed';
import AdminUser from 'admin/models/admin-user';
export default Ember.ArrayController.extend({
query: null,
@ -42,7 +43,7 @@ export default Ember.ArrayController.extend({
var self = this;
this.set('refreshing', true);
Discourse.AdminUser.findAll(this.get('query'), { filter: this.get('listFilter'), show_emails: this.get('showEmails') }).then(function (result) {
AdminUser.findAll(this.get('query'), { filter: this.get('listFilter'), show_emails: this.get('showEmails') }).then(function (result) {
self.set('model', result);
}).finally(function() {
self.set('refreshing', false);
@ -51,14 +52,14 @@ export default Ember.ArrayController.extend({
actions: {
approveUsers: function() {
Discourse.AdminUser.bulkApprove(this.get('model').filterProperty('selected'));
AdminUser.bulkApprove(this.get('model').filterProperty('selected'));
this._refreshUsers();
},
rejectUsers: function() {
var maxPostAge = this.siteSettings.delete_user_max_post_age;
var controller = this;
Discourse.AdminUser.bulkReject(this.get('model').filterProperty('selected')).then(function(result){
AdminUser.bulkReject(this.get('model').filterProperty('selected')).then(function(result){
var message = I18n.t("admin.users.reject_successful", {count: result.success});
if (result.failed > 0) {
message += ' ' + I18n.t("admin.users.reject_failures", {count: result.failed});

View File

@ -2,15 +2,13 @@ export default Ember.Controller.extend({
needs: ['modal'],
modelChanged: function(){
var grouping = Em.Object.extend({});
var model = this.get('model');
var copy = Em.A();
const model = this.get('model');
const copy = Em.A();
const store = this.store;
if(model){
model.forEach(function(o){
copy.pushObject(grouping.create(o));
copy.pushObject(store.createRecord('badge-grouping', o));
});
}
@ -18,8 +16,8 @@ export default Ember.Controller.extend({
}.observes('model'),
moveItem: function(item, delta){
var copy = this.get('workingCopy');
var index = copy.indexOf(item);
const copy = this.get('workingCopy');
const index = copy.indexOf(item);
if (index + delta < 0 || index + delta >= copy.length){
return;
}
@ -50,14 +48,14 @@ export default Ember.Controller.extend({
item.set("editing", false);
},
add: function(){
var obj = Em.Object.create({editing: true, name: "Enter Name"});
const obj = this.store.createRecord('badge-grouping', {editing: true, name: I18n.t('admin.badges.badge_grouping')});
this.get('workingCopy').pushObject(obj);
},
saveAll: function(){
var self = this;
const self = this;
var items = this.get('workingCopy');
var groupIds = items.map(function(i){return i.get("id") || -1;});
var names = items.map(function(i){return i.get("name");});
const groupIds = items.map(function(i){return i.get("id") || -1;});
const names = items.map(function(i){return i.get("name");});
Discourse.ajax('/admin/badges/badge_groupings',{
data: {ids: groupIds, names: names},
@ -66,14 +64,13 @@ export default Ember.Controller.extend({
items = self.get("model");
items.clear();
data.badge_groupings.forEach(function(g){
items.pushObject(Em.Object.create(g));
items.pushObject(self.store.createRecord('badge-grouping', g));
});
self.set('model', null);
self.set('workingCopy', null);
self.send('closeModal');
},function(){
// TODO we can do better
bootbox.alert("Something went wrong");
bootbox.alert(I18n.t('generic_error'));
});
}
}

View File

@ -0,0 +1,17 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import IncomingEmail from 'admin/models/incoming-email';
import computed from 'ember-addons/ember-computed-decorators';
import { longDate } from 'discourse/lib/formatter';
export default Ember.Controller.extend(ModalFunctionality, {
@computed("model.date")
date(d) {
return longDate(d);
},
load(id) {
return IncomingEmail.find(id).then(result => this.set("model", result));
}
});

View File

@ -1,4 +1,5 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import Backup from 'admin/models/backup';
export default Ember.Controller.extend(ModalFunctionality, {
needs: ["adminBackupsLogs"],
@ -6,7 +7,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
_startBackup: function (withUploads) {
var self = this;
Discourse.User.currentProp("hideReadOnlyAlert", true);
Discourse.Backup.start(withUploads).then(function() {
Backup.start(withUploads).then(function() {
self.get("controllers.adminBackupsLogs").clear();
self.send("backupStarted");
});

View File

@ -0,0 +1,3 @@
Em.Handlebars.helper('preserve-newlines', str => {
return new Handlebars.SafeString(Discourse.Utilities.escapeExpression(str).replace(/\n/g, "<br>"));
});

View File

@ -1,15 +1,7 @@
/**
A model that stores all or some data that is displayed on the dashboard.
@class AdminDashboard
@extends Discourse.Model
@namespace Discourse
@module Discourse
**/
const AdminDashboard = Discourse.Model.extend({});
Discourse.AdminDashboard = Discourse.Model.extend({});
Discourse.AdminDashboard.reopenClass({
AdminDashboard.reopenClass({
/**
Fetch all dashboard data. This can be an expensive request when the cached data
@ -20,7 +12,7 @@ Discourse.AdminDashboard.reopenClass({
**/
find: function() {
return Discourse.ajax("/admin/dashboard.json").then(function(json) {
var model = Discourse.AdminDashboard.create(json);
var model = AdminDashboard.create(json);
model.set('loaded', true);
return model;
});
@ -38,9 +30,11 @@ Discourse.AdminDashboard.reopenClass({
type: 'GET',
dataType: 'json'
}).then(function(json) {
var model = Discourse.AdminDashboard.create(json);
var model = AdminDashboard.create(json);
model.set('loaded', true);
return model;
});
}
});
export default AdminDashboard;

View File

@ -1,17 +1,22 @@
import { propertyNotEqual } from 'discourse/lib/computed';
import { popupAjaxError } from 'discourse/lib/ajax-error';
import ApiKey from 'admin/models/api-key';
import Group from 'discourse/models/group';
import TL3Requirements from 'admin/models/tl3-requirements';
const AdminUser = Discourse.User.extend({
customGroups: Em.computed.filter("groups", (g) => !g.automatic && Discourse.Group.create(g)),
automaticGroups: Em.computed.filter("groups", (g) => g.automatic && Discourse.Group.create(g)),
customGroups: Em.computed.filter("groups", (g) => !g.automatic && Group.create(g)),
automaticGroups: Em.computed.filter("groups", (g) => g.automatic && Group.create(g)),
canViewProfile: Ember.computed.or("active", "staged"),
generateApiKey() {
const self = this;
return Discourse.ajax("/admin/users/" + this.get('id') + "/generate_api_key", {
type: 'POST'
}).then(function (result) {
const apiKey = Discourse.ApiKey.create(result.api_key);
const apiKey = ApiKey.create(result.api_key);
self.set('api_key', apiKey);
return apiKey;
});
@ -261,6 +266,7 @@ const AdminUser = Discourse.User.extend({
},
unblock() {
this.set('blockingUser', true);
return Discourse.ajax('/admin/users/' + this.id + '/unblock', {
type: 'PUT'
}).then(function() {
@ -272,14 +278,33 @@ const AdminUser = Discourse.User.extend({
},
block() {
return Discourse.ajax('/admin/users/' + this.id + '/block', {
type: 'PUT'
}).then(function() {
window.location.reload();
}).catch(function(e) {
var error = I18n.t('admin.user.block_failed', { error: "http: " + e.status + " - " + e.body });
bootbox.alert(error);
});
const user = this,
message = I18n.t("admin.user.block_confirm");
const performBlock = function() {
user.set('blockingUser', true);
return Discourse.ajax('/admin/users/' + user.id + '/block', {
type: 'PUT'
}).then(function() {
window.location.reload();
}).catch(function(e) {
var error = I18n.t('admin.user.block_failed', { error: "http: " + e.status + " - " + e.body });
bootbox.alert(error);
user.set('blockingUser', false);
});
};
const buttons = [{
"label": I18n.t("composer.cancel"),
"class": "cancel",
"link": true
}, {
"label": '<i class="fa fa-exclamation-triangle"></i>' + I18n.t('admin.user.block_accept'),
"class": "btn btn-danger",
"callback": function() { performBlock(); }
}];
bootbox.dialog(message, buttons, { "classes": "delete-user-modal" });
},
sendActivationEmail() {
@ -288,10 +313,7 @@ const AdminUser = Discourse.User.extend({
data: { username: this.get('username') }
}).then(function() {
bootbox.alert( I18n.t('admin.user.activation_email_sent') );
}).catch(function(e) {
var error = I18n.t('admin.user.send_activation_email_failed', { error: "http: " + e.status + " - " + e.body });
bootbox.alert(error);
});
}).catch(popupAjaxError);
},
anonymizeForbidden: Em.computed.not("can_be_anonymized"),
@ -306,7 +328,7 @@ const AdminUser = Discourse.User.extend({
}).then(function(data) {
if (data.success) {
if (data.username) {
document.location = Discourse.getURL("/admin/users/" + data.username);
document.location = Discourse.getURL("/admin/users/" + user.get('id') + "/" + data.username);
} else {
document.location = Discourse.getURL("/admin/users/list/active");
}
@ -380,23 +402,23 @@ const AdminUser = Discourse.User.extend({
}
}
}).catch(function() {
Discourse.AdminUser.find( user.get('username') ).then(function(u){ user.setProperties(u); });
AdminUser.find(user.get('id')).then(u => user.setProperties(u));
bootbox.alert(I18n.t("admin.user.delete_failed"));
});
};
const buttons = [{
"label": I18n.t("composer.cancel"),
"class": "cancel",
"link": true
}, {
"label": I18n.t('admin.user.delete_dont_block'),
"class": "btn",
"callback": function(){ performDestroy(false); }
"link": true
}, {
"label": '<i class="fa fa-exclamation-triangle"></i>' + I18n.t('admin.user.delete_and_block'),
"class": "btn btn-danger",
"callback": function(){ performDestroy(true); }
}, {
"label": I18n.t('admin.user.delete_dont_block'),
"class": "btn btn-primary",
"callback": function(){ performDestroy(false); }
}];
bootbox.dialog(message, buttons, { "classes": "delete-user-modal" });
@ -453,7 +475,7 @@ const AdminUser = Discourse.User.extend({
if (user.get('loadedDetails')) { return Ember.RSVP.resolve(user); }
return Discourse.AdminUser.find(user.get('username_lower')).then(function (result) {
return AdminUser.find(user.get('id')).then(result => {
user.setProperties(result);
user.set('loadedDetails', true);
});
@ -461,19 +483,19 @@ const AdminUser = Discourse.User.extend({
tl3Requirements: function() {
if (this.get('tl3_requirements')) {
return Discourse.TL3Requirements.create(this.get('tl3_requirements'));
return TL3Requirements.create(this.get('tl3_requirements'));
}
}.property('tl3_requirements'),
suspendedBy: function() {
if (this.get('suspended_by')) {
return Discourse.AdminUser.create(this.get('suspended_by'));
return AdminUser.create(this.get('suspended_by'));
}
}.property('suspended_by'),
approvedBy: function() {
if (this.get('approved_by')) {
return Discourse.AdminUser.create(this.get('approved_by'));
return AdminUser.create(this.get('approved_by'));
}
}.property('approved_by')
@ -511,10 +533,10 @@ AdminUser.reopenClass({
});
},
find(username) {
return Discourse.ajax("/admin/users/" + username + ".json").then(function (result) {
find(user_id) {
return Discourse.ajax("/admin/users/" + user_id + ".json").then(result => {
result.loadedDetails = true;
return Discourse.AdminUser.create(result);
return AdminUser.create(result);
});
},
@ -522,7 +544,7 @@ AdminUser.reopenClass({
return Discourse.ajax("/admin/users/list/" + query + ".json", {
data: filter
}).then(function(users) {
return users.map((u) => Discourse.AdminUser.create(u));
return users.map((u) => AdminUser.create(u));
});
}
});

View File

@ -1,12 +1,4 @@
/**
Our data model for representing an API key in the system
@class ApiKey
@extends Discourse.Model
@namespace Discourse
@module Discourse
**/
Discourse.ApiKey = Discourse.Model.extend({
const ApiKey = Discourse.Model.extend({
/**
Regenerates the api key
@ -34,19 +26,20 @@ Discourse.ApiKey = Discourse.Model.extend({
});
Discourse.ApiKey.reopenClass({
ApiKey.reopenClass({
/**
Creates an API key instance with internal user object
@method create
@param {...} var_args the properties to initialize this with
@returns {Discourse.ApiKey} the ApiKey instance
@returns {ApiKey} the ApiKey instance
**/
create: function() {
const AdminUser = require('admin/models/admin-user').default;
var result = this._super.apply(this, arguments);
if (result.user) {
result.user = Discourse.AdminUser.create(result.user);
result.user = AdminUser.create(result.user);
}
return result;
},
@ -55,12 +48,12 @@ Discourse.ApiKey.reopenClass({
Finds a list of API keys
@method find
@returns {Promise} a promise that resolves to the array of `Discourse.ApiKey` instances
@returns {Promise} a promise that resolves to the array of `ApiKey` instances
**/
find: function() {
return Discourse.ajax("/admin/api").then(function(keys) {
return keys.map(function (key) {
return Discourse.ApiKey.create(key);
return ApiKey.create(key);
});
});
},
@ -69,12 +62,14 @@ Discourse.ApiKey.reopenClass({
Generates a master api key and returns it.
@method generateMasterKey
@returns {Promise} a promise that resolves to a master `Discourse.ApiKey`
@returns {Promise} a promise that resolves to a master `ApiKey`
**/
generateMasterKey: function() {
return Discourse.ajax("/admin/api/key", {type: 'POST'}).then(function (result) {
return Discourse.ApiKey.create(result.api_key);
return ApiKey.create(result.api_key);
});
}
});
export default ApiKey;

View File

@ -1,13 +1,4 @@
/**
Our data model for a color within a color scheme.
(It's a funny name for a class, but Color seemed too generic for what this class is.)
@class ColorSchemeColor
@extends Discourse.Model
@namespace Discourse
@module Discourse
**/
Discourse.ColorSchemeColor = Discourse.Model.extend({
const ColorSchemeColor = Discourse.Model.extend({
init: function() {
this._super();
@ -78,3 +69,5 @@ Discourse.ColorSchemeColor = Discourse.Model.extend({
return this.get('hex').match(/^([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/) !== null;
}.property('hex')
});
export default ColorSchemeColor;

View File

@ -1,12 +1,6 @@
/**
Our data model for a color scheme.
import ColorSchemeColor from 'admin/models/color-scheme-color';
@class ColorScheme
@extends Discourse.Model
@namespace Discourse
@module Discourse
**/
Discourse.ColorScheme = Discourse.Model.extend(Ember.Copyable, {
const ColorScheme = Discourse.Model.extend(Ember.Copyable, {
init: function() {
this._super();
@ -25,9 +19,9 @@ Discourse.ColorScheme = Discourse.Model.extend(Ember.Copyable, {
},
copy: function() {
var newScheme = Discourse.ColorScheme.create({name: this.get('name'), enabled: false, can_edit: true, colors: Em.A()});
var newScheme = ColorScheme.create({name: this.get('name'), enabled: false, can_edit: true, colors: Em.A()});
_.each(this.get('colors'), function(c){
newScheme.colors.pushObject(Discourse.ColorSchemeColor.create({name: c.get('name'), hex: c.get('hex'), default_hex: c.get('default_hex')}));
newScheme.colors.pushObject(ColorSchemeColor.create({name: c.get('name'), hex: c.get('hex'), default_hex: c.get('default_hex')}));
});
return newScheme;
},
@ -109,17 +103,17 @@ var ColorSchemes = Ember.ArrayProxy.extend({
}.observes('selectedItem')
});
Discourse.ColorScheme.reopenClass({
ColorScheme.reopenClass({
findAll: function() {
var colorSchemes = ColorSchemes.create({ content: [], loading: true });
Discourse.ajax('/admin/color_schemes').then(function(all) {
_.each(all, function(colorScheme){
colorSchemes.pushObject(Discourse.ColorScheme.create({
colorSchemes.pushObject(ColorScheme.create({
id: colorScheme.id,
name: colorScheme.name,
enabled: colorScheme.enabled,
is_base: colorScheme.is_base,
colors: colorScheme.colors.map(function(c) { return Discourse.ColorSchemeColor.create({name: c.name, hex: c.hex, default_hex: c.default_hex}); })
colors: colorScheme.colors.map(function(c) { return ColorSchemeColor.create({name: c.name, hex: c.hex, default_hex: c.default_hex}); })
}));
});
colorSchemes.set('loading', false);
@ -127,3 +121,5 @@ Discourse.ColorScheme.reopenClass({
return colorSchemes;
}
});
export default ColorScheme;

View File

@ -0,0 +1,29 @@
import AdminUser from 'admin/models/admin-user';
const EmailLog = Discourse.Model.extend({});
EmailLog.reopenClass({
create(attrs) {
attrs = attrs || {};
if (attrs.user) {
attrs.user = AdminUser.create(attrs.user);
}
return this._super(attrs);
},
findAll(filter, offset) {
filter = filter || {};
offset = offset || 0;
const status = filter.status || "sent";
filter = _.omit(filter, "status");
return Discourse.ajax(`/admin/email/${status}.json?offset=${offset}`, { data: filter })
.then(logs => _.map(logs, log => EmailLog.create(log)));
}
});
export default EmailLog;

View File

@ -0,0 +1,22 @@
const EmailPreview = Discourse.Model.extend({});
EmailPreview.reopenClass({
findDigest: function(lastSeenAt, username) {
if (Em.isEmpty(lastSeenAt)) {
lastSeenAt = moment().subtract(7, 'days').format('YYYY-MM-DD');
}
if (Em.isEmpty(username)) {
username = Discourse.User.current().username;
}
return Discourse.ajax("/admin/email/preview-digest.json", {
data: { last_seen_at: lastSeenAt, username: username }
}).then(function (result) {
return EmailPreview.create(result);
});
}
});
export default EmailPreview;

View File

@ -0,0 +1,11 @@
const EmailSettings = Discourse.Model.extend({});
EmailSettings.reopenClass({
find: function() {
return Discourse.ajax("/admin/email.json").then(function (settings) {
return EmailSettings.create(settings);
});
}
});
export default EmailSettings;

View File

@ -0,0 +1,10 @@
import RestModel from 'discourse/models/rest';
const { getProperties } = Ember;
export default RestModel.extend({
revert() {
return Discourse.ajax(`/admin/customize/email_templates/${this.get('id')}`, {
method: 'DELETE'
}).then(result => getProperties(result.email_template, 'subject', 'body', 'can_revert'));
}
});

View File

@ -1,36 +0,0 @@
/**
Our data model for representing an email log.
@class EmailLog
@extends Discourse.Model
@namespace Discourse
@module Discourse
**/
Discourse.EmailLog = Discourse.Model.extend({});
Discourse.EmailLog.reopenClass({
create: function(attrs) {
attrs = attrs || {};
if (attrs.user) {
attrs.user = Discourse.AdminUser.create(attrs.user);
}
return this._super(attrs);
},
findAll: function(filter) {
filter = filter || {};
var status = filter.status || "all";
filter = _.omit(filter, "status");
return Discourse.ajax("/admin/email/" + status + ".json", { data: filter }).then(function(logs) {
return _.map(logs, function (log) {
return Discourse.EmailLog.create(log);
});
});
}
});

View File

@ -1,26 +0,0 @@
/**
Our data model for showing a preview of an email
@class EmailPreview
@extends Discourse.Model
@namespace Discourse
@module Discourse
**/
Discourse.EmailPreview = Discourse.Model.extend({});
Discourse.EmailPreview.reopenClass({
findDigest: function(lastSeenAt) {
if (Em.isEmpty(lastSeenAt)) {
lastSeenAt = moment().subtract(7, 'days').format('YYYY-MM-DD');
}
return Discourse.ajax("/admin/email/preview-digest.json", {
data: {last_seen_at: lastSeenAt}
}).then(function (result) {
return Discourse.EmailPreview.create(result);
});
}
});

View File

@ -1,17 +0,0 @@
/**
Our data model for representing the current email settings
@class EmailSettings
@extends Discourse.Model
@namespace Discourse
@module Discourse
**/
Discourse.EmailSettings = Discourse.Model.extend({});
Discourse.EmailSettings.reopenClass({
find: function() {
return Discourse.ajax("/admin/email.json").then(function (settings) {
return Discourse.EmailSettings.create(settings);
});
}
});

View File

@ -1,12 +1,9 @@
/**
Our data model for interacting with flagged posts.
import AdminUser from 'admin/models/admin-user';
import Topic from 'discourse/models/topic';
import Post from 'discourse/models/post';
@class FlaggedPost
@extends Discourse.Post
@namespace Discourse
@module Discourse
**/
Discourse.FlaggedPost = Discourse.Post.extend({
const FlaggedPost = Post.extend({
summary: function () {
return _(this.post_actions)
@ -140,7 +137,7 @@ Discourse.FlaggedPost = Discourse.Post.extend({
});
Discourse.FlaggedPost.reopenClass({
FlaggedPost.reopenClass({
findAll: function (filter, offset) {
offset = offset || 0;
@ -151,18 +148,18 @@ Discourse.FlaggedPost.reopenClass({
// users
var userLookup = {};
_.each(data.users, function (user) {
userLookup[user.id] = Discourse.AdminUser.create(user);
userLookup[user.id] = AdminUser.create(user);
});
// topics
var topicLookup = {};
_.each(data.topics, function (topic) {
topicLookup[topic.id] = Discourse.Topic.create(topic);
topicLookup[topic.id] = Topic.create(topic);
});
// posts
_.each(data.posts, function (post) {
var f = Discourse.FlaggedPost.create(post);
var f = FlaggedPost.create(post);
f.userLookup = userLookup;
f.topicLookup = topicLookup;
result.pushObject(f);
@ -174,3 +171,5 @@ Discourse.FlaggedPost.reopenClass({
});
}
});
export default FlaggedPost;

View File

@ -0,0 +1,37 @@
import AdminUser from 'admin/models/admin-user';
const IncomingEmail = Discourse.Model.extend({});
IncomingEmail.reopenClass({
create(attrs) {
attrs = attrs || {};
if (attrs.user) {
attrs.user = AdminUser.create(attrs.user);
}
return this._super(attrs);
},
find(id) {
return Discourse.ajax(`/admin/email/incoming/${id}.json`);
},
findAll(filter, offset) {
filter = filter || {};
offset = offset || 0;
const status = filter.status || "received";
filter = _.omit(filter, "status");
return Discourse.ajax(`/admin/email/${status}.json?offset=${offset}`, { data: filter })
.then(incomings => _.map(incomings, incoming => IncomingEmail.create(incoming)));
},
loadRawEmail(id) {
return Discourse.ajax(`/admin/email/incoming/${id}/raw.json`);
}
});
export default IncomingEmail;

View File

@ -14,7 +14,7 @@ const Permalink = Discourse.Model.extend({
Permalink.reopenClass({
findAll: function(filter) {
return Discourse.ajax("/admin/permalinks.json", { data: { filter: filter } }).then(function(permalinks) {
return permalinks.map(p => Discourse.Permalink.create(p));
return permalinks.map(p => Permalink.create(p));
});
}
});

View File

@ -131,12 +131,13 @@ const Report = Discourse.Model.extend({
Report.reopenClass({
find(type, startDate, endDate, categoryId) {
find(type, startDate, endDate, categoryId, groupId) {
return Discourse.ajax("/admin/reports/" + type, {
data: {
start_date: startDate,
end_date: endDate,
category_id: categoryId
category_id: categoryId,
group_id: groupId
}
}).then(json => {
// Add a percent field to each tuple
@ -147,7 +148,7 @@ Report.reopenClass({
if (maxY > 0) {
json.report.data.forEach(row => row.percentage = Math.round((row.y / maxY) * 100));
}
const model = Discourse.Report.create({ type: type });
const model = Report.create({ type: type });
model.setProperties(json.report);
return model;
});

View File

@ -1,13 +1,4 @@
/**
Represents an email address that is watched for during account registration,
and an action is taken.
@class ScreenedEmail
@extends Discourse.Model
@namespace Discourse
@module Discourse
**/
Discourse.ScreenedEmail = Discourse.Model.extend({
const ScreenedEmail = Discourse.Model.extend({
actionName: function() {
return I18n.t("admin.logs.screened_actions." + this.get('action'));
}.property('action'),
@ -17,12 +8,14 @@ Discourse.ScreenedEmail = Discourse.Model.extend({
}
});
Discourse.ScreenedEmail.reopenClass({
ScreenedEmail.reopenClass({
findAll: function() {
return Discourse.ajax("/admin/logs/screened_emails.json").then(function(screened_emails) {
return screened_emails.map(function(b) {
return Discourse.ScreenedEmail.create(b);
return ScreenedEmail.create(b);
});
});
}
});
export default ScreenedEmail;

View File

@ -1,8 +1,4 @@
/**
Represents an IP address that is watched for during account registration
(and possibly other times), and an action is taken.
**/
Discourse.ScreenedIpAddress = Discourse.Model.extend({
const ScreenedIpAddress = Discourse.Model.extend({
actionName: function() {
return I18n.t("admin.logs.screened_ips.actions." + this.get('action_name'));
}.property('action_name'),
@ -27,11 +23,11 @@ Discourse.ScreenedIpAddress = Discourse.Model.extend({
}
});
Discourse.ScreenedIpAddress.reopenClass({
ScreenedIpAddress.reopenClass({
findAll: function(filter) {
return Discourse.ajax("/admin/logs/screened_ip_addresses.json", { data: { filter: filter } }).then(function(screened_ips) {
return screened_ips.map(function(b) {
return Discourse.ScreenedIpAddress.create(b);
return ScreenedIpAddress.create(b);
});
});
},
@ -40,3 +36,5 @@ Discourse.ScreenedIpAddress.reopenClass({
return Discourse.ajax("/admin/logs/screened_ip_addresses/roll_up", { type: "POST" });
}
});
export default ScreenedIpAddress;

View File

@ -1,23 +1,17 @@
/**
Represents a URL that is watched for, and an action may be taken.
@class ScreenedUrl
@extends Discourse.Model
@namespace Discourse
@module Discourse
**/
Discourse.ScreenedUrl = Discourse.Model.extend({
const ScreenedUrl = Discourse.Model.extend({
actionName: function() {
return I18n.t("admin.logs.screened_actions." + this.get('action'));
}.property('action')
});
Discourse.ScreenedUrl.reopenClass({
ScreenedUrl.reopenClass({
findAll: function() {
return Discourse.ajax("/admin/logs/screened_urls.json").then(function(screened_urls) {
return screened_urls.map(function(b) {
return Discourse.ScreenedUrl.create(b);
return ScreenedUrl.create(b);
});
});
}
});
export default ScreenedUrl;

View File

@ -35,7 +35,7 @@ SiteSetting.reopenClass({
if (!categories[s.category]) {
categories[s.category] = [];
}
categories[s.category].pushObject(Discourse.SiteSetting.create(s));
categories[s.category].pushObject(SiteSetting.create(s));
});
return Object.keys(categories).map(function(n) {

View File

@ -1,2 +0,0 @@
import RestModel from 'discourse/models/rest';
export default RestModel.extend();

View File

@ -1,8 +1,10 @@
import RestModel from 'discourse/models/rest';
const { getProperties } = Ember;
export default RestModel.extend({
markdown: Em.computed.equal('format', 'markdown'),
plainText: Em.computed.equal('format', 'plain'),
html: Em.computed.equal('format', 'html'),
css: Em.computed.equal('format', 'css'),
revert() {
return Discourse.ajax(`/admin/customize/site_texts/${this.get('id')}`, {
method: 'DELETE'
}).then(result => getProperties(result.site_text, 'value', 'can_revert'));
}
});

View File

@ -1,4 +1,6 @@
Discourse.StaffActionLog = Discourse.Model.extend({
import AdminUser from 'admin/models/admin-user';
const StaffActionLog = Discourse.Model.extend({
showFullDetails: false,
actionName: function() {
@ -11,6 +13,7 @@ Discourse.StaffActionLog = Discourse.Model.extend({
formatted += this.format('admin.logs.ip_address', 'ip_address');
formatted += this.format('admin.logs.topic_id', 'topic_id');
formatted += this.format('admin.logs.post_id', 'post_id');
formatted += this.format('admin.logs.category_id', 'category_id');
if (!this.get('useCustomModalForDetails')) {
formatted += this.format('admin.logs.staff_actions.new_value', 'new_value');
formatted += this.format('admin.logs.staff_actions.previous_value', 'previous_value');
@ -19,7 +22,7 @@ Discourse.StaffActionLog = Discourse.Model.extend({
if (this.get('details')) formatted += Discourse.Utilities.escapeExpression(this.get('details')) + '<br/>';
}
return formatted;
}.property('ip_address', 'email', 'topic_id', 'post_id'),
}.property('ip_address', 'email', 'topic_id', 'post_id', 'category_id'),
format: function(label, propertyName) {
if (this.get(propertyName)) {
@ -38,15 +41,15 @@ Discourse.StaffActionLog = Discourse.Model.extend({
}.property('action_name')
});
Discourse.StaffActionLog.reopenClass({
StaffActionLog.reopenClass({
create: function(attrs) {
attrs = attrs || {};
if (attrs.acting_user) {
attrs.acting_user = Discourse.AdminUser.create(attrs.acting_user);
attrs.acting_user = AdminUser.create(attrs.acting_user);
}
if (attrs.target_user) {
attrs.target_user = Discourse.AdminUser.create(attrs.target_user);
attrs.target_user = AdminUser.create(attrs.target_user);
}
return this._super(attrs);
},
@ -54,8 +57,10 @@ Discourse.StaffActionLog.reopenClass({
findAll: function(filters) {
return Discourse.ajax("/admin/logs/staff_action_logs.json", { data: filters }).then(function(staff_actions) {
return staff_actions.map(function(s) {
return Discourse.StaffActionLog.create(s);
return StaffActionLog.create(s);
});
});
}
});
export default StaffActionLog;

View File

@ -1,10 +1,10 @@
Discourse.TL3Requirements = Discourse.Model.extend({
const TL3Requirements = Discourse.Model.extend({
days_visited_percent: function() {
return ((this.get('days_visited') * 100) / this.get('time_period'));
return Math.round((this.get('days_visited') * 100) / this.get('time_period'));
}.property('days_visited', 'time_period'),
min_days_visited_percent: function() {
return ((this.get('min_days_visited') * 100) / this.get('time_period'));
return Math.round((this.get('min_days_visited') * 100) / this.get('time_period'));
}.property('min_days_visited', 'time_period'),
met: function() {
@ -38,3 +38,5 @@ Discourse.TL3Requirements = Discourse.Model.extend({
'num_likes_received_users', 'min_likes_received_users',
'trust_level_locked')
});
export default TL3Requirements;

View File

@ -1,12 +1,4 @@
/**
Our data model for determining whether there's a new version of Discourse
@class VersionCheck
@extends Discourse.Model
@namespace Discourse
@module Discourse
**/
Discourse.VersionCheck = Discourse.Model.extend({
const VersionCheck = Discourse.Model.extend({
noCheckPerformed: function() {
return this.get('updated_at') === null;
@ -39,10 +31,12 @@ Discourse.VersionCheck = Discourse.Model.extend({
}.property('installed_sha')
});
Discourse.VersionCheck.reopenClass({
VersionCheck.reopenClass({
find: function() {
return Discourse.ajax('/admin/version_check').then(function(json) {
return Discourse.VersionCheck.create(json);
return VersionCheck.create(json);
});
}
});
export default VersionCheck;

View File

@ -1,5 +1,7 @@
import ApiKey from 'admin/models/api-key';
export default Ember.Route.extend({
model() {
return Discourse.ApiKey.find();
return ApiKey.find();
}
});

View File

@ -1,5 +1,7 @@
import Backup from 'admin/models/backup';
export default Ember.Route.extend({
model() {
return Discourse.Backup.find();
return Backup.find();
}
});

View File

@ -1,4 +1,6 @@
import showModal from 'discourse/lib/show-modal';
import BackupStatus from 'admin/models/backup-status';
import Backup from 'admin/models/backup';
const LOG_CHANNEL = "/admin/backups/logs";
@ -31,7 +33,7 @@ export default Discourse.Route.extend({
return PreloadStore.getAndRemove("operations_status", function() {
return Discourse.ajax("/admin/backups/status.json");
}).then(status => {
return Discourse.BackupStatus.create({
return BackupStatus.create({
isOperationRunning: status.is_operation_running,
canRollback: status.can_rollback,
allowRestore: status.allow_restore
@ -98,7 +100,7 @@ export default Discourse.Route.extend({
I18n.t("yes_value"),
function(confirmed) {
if (confirmed) {
Discourse.Backup.cancel().then(function() {
Backup.cancel().then(function() {
self.controllerFor("adminBackups").set("model.isOperationRunning", false);
});
}
@ -112,7 +114,7 @@ export default Discourse.Route.extend({
I18n.t("no_value"),
I18n.t("yes_value"),
function(confirmed) {
if (confirmed) { Discourse.Backup.rollback(); }
if (confirmed) { Backup.rollback(); }
}
);
},
@ -120,7 +122,7 @@ export default Discourse.Route.extend({
uploadSuccess(filename) {
const self = this;
bootbox.alert(I18n.t("admin.backups.upload.success", { filename: filename }), function() {
Discourse.Backup.find().then(function (backups) {
Backup.find().then(function (backups) {
self.controllerFor("adminBackupsIndex").set("model", backups);
});
});

View File

@ -1,4 +1,5 @@
import Badge from 'discourse/models/badge';
import BadgeGrouping from 'discourse/models/badge-grouping';
export default Discourse.Route.extend({
_json: null,
@ -13,14 +14,19 @@ export default Discourse.Route.extend({
setupController: function(controller, model) {
var json = this._json,
triggers = [];
triggers = [],
badgeGroupings = [];
_.each(json.admin_badges.triggers,function(v,k){
triggers.push({id: v, name: I18n.t('admin.badges.trigger_type.'+k)});
});
json.badge_groupings.forEach(function(badgeGroupingJson) {
badgeGroupings.push(BadgeGrouping.create(badgeGroupingJson));
});
controller.setProperties({
badgeGroupings: json.badge_groupings,
badgeGroupings: badgeGroupings,
badgeTypes: json.badge_types,
protectedSystemFields: json.admin_badges.protected_system_fields,
badgeTriggers: triggers,

View File

@ -1,7 +1,9 @@
import ColorScheme from 'admin/models/color-scheme';
export default Ember.Route.extend({
model() {
return Discourse.ColorScheme.findAll();
return ColorScheme.findAll();
},
deactivate() {

View File

@ -0,0 +1,13 @@
import { scrollTop } from 'discourse/mixins/scroll-top';
export default Ember.Route.extend({
model(params) {
const all = this.modelFor('adminCustomizeEmailTemplates');
return all.findProperty('id', params.id);
},
setupController(controller, emailTemplate) {
controller.setProperties({ emailTemplate, saved: false });
scrollTop();
}
});

View File

@ -0,0 +1,9 @@
export default Ember.Route.extend({
model() {
return this.store.findAll('email-template');
},
setupController(controller, model) {
controller.set('emailTemplates', model);
}
});

View File

@ -1,5 +1,5 @@
export default Ember.Route.extend({
beforeModel() {
this.replaceWith('adminCustomize.colors');
this.transitionTo('adminCustomize.colors');
}
});

View File

@ -1,3 +1,8 @@
import AdminDashboard from 'admin/models/admin-dashboard';
import VersionCheck from 'admin/models/version-check';
import Report from 'admin/models/report';
import AdminUser from 'admin/models/admin-user';
export default Discourse.Route.extend({
setupController: function(c) {
@ -8,19 +13,19 @@ export default Discourse.Route.extend({
if( !c.get('dashboardFetchedAt') || moment().subtract(30, 'minutes').toDate() > c.get('dashboardFetchedAt') ) {
c.set('dashboardFetchedAt', new Date());
var versionChecks = this.siteSettings.version_checks;
Discourse.AdminDashboard.find().then(function(d) {
AdminDashboard.find().then(function(d) {
if (versionChecks) {
c.set('versionCheck', Discourse.VersionCheck.create(d.version_check));
c.set('versionCheck', VersionCheck.create(d.version_check));
}
['global_reports', 'page_view_reports', 'private_message_reports', 'http_reports', 'user_reports', 'mobile_reports'].forEach(name => {
c.set(name, d[name].map(r => Discourse.Report.create(r)));
c.set(name, d[name].map(r => Report.create(r)));
});
var topReferrers = d.top_referrers;
if (topReferrers && topReferrers.data) {
d.top_referrers.data = topReferrers.data.map(function (user) {
return Discourse.AdminUser.create(user);
return AdminUser.create(user);
});
c.set('top_referrers', topReferrers);
}

View File

@ -0,0 +1,14 @@
import IncomingEmail from 'admin/models/incoming-email';
export default Discourse.Route.extend({
model() {
return IncomingEmail.findAll({ status: this.get("status") });
},
setupController(controller, model) {
controller.set("model", model);
controller.set("filter", { status: this.get("status") });
}
});

View File

@ -0,0 +1,11 @@
import EmailSettings from 'admin/models/email-settings';
export default Discourse.Route.extend({
model() {
return EmailSettings.find();
},
renderTemplate() {
this.render('admin/templates/email_index', { into: 'adminEmail' });
}
});

View File

@ -0,0 +1,14 @@
import EmailLog from 'admin/models/email-log';
export default Discourse.Route.extend({
model() {
return EmailLog.findAll({ status: this.get("status") });
},
setupController(controller, model) {
controller.set("model", model);
controller.set("filter", { status: this.get("status") });
}
});

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