Version bump to v1.1.1
This commit is contained in:
commit
6e0152ab94
@ -7,7 +7,7 @@ root = true
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
indent_style = spaces
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
|
||||
36
.travis.yml
36
.travis.yml
@ -1,16 +1,40 @@
|
||||
language: ruby
|
||||
|
||||
env:
|
||||
global:
|
||||
- DISCOURSE_HOSTNAME=www.example.com
|
||||
- RUBY_GC_MALLOC_LIMIT=50000000
|
||||
matrix:
|
||||
- "RAILS_MASTER=1"
|
||||
- "RAILS_MASTER=0"
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- rvm: 2.0.0
|
||||
env: "RAILS_MASTER=1"
|
||||
- rvm: 2.1
|
||||
env: "RAILS_MASTER=1"
|
||||
fast_finish: true
|
||||
|
||||
rvm:
|
||||
- 2.0.0
|
||||
- 2.1.2
|
||||
- 2.1
|
||||
|
||||
services:
|
||||
- redis-server
|
||||
|
||||
sudo: false
|
||||
|
||||
cache: bundler
|
||||
|
||||
before_install:
|
||||
- npm i -g jshint
|
||||
- jshint .
|
||||
|
||||
before_script:
|
||||
- psql -c 'create database discourse_test;' -U postgres
|
||||
- export DISCOURSE_HOSTNAME=www.example.com
|
||||
- export RUBY_GC_MALLOC_LIMIT=50000000
|
||||
- bundle exec rake db:migrate
|
||||
bundler_args: --without development
|
||||
|
||||
bundler_args: --without development --deployment --retry=3 --jobs=3
|
||||
|
||||
script: 'bundle exec rspec && bundle exec rake plugin:spec && bundle exec rake qunit:test'
|
||||
services:
|
||||
- redis-server
|
||||
|
||||
15
Gemfile
15
Gemfile
@ -4,7 +4,7 @@ source 'https://rubygems.org'
|
||||
|
||||
module ::Kernel
|
||||
def rails_master?
|
||||
ENV["RAILS_MASTER"]
|
||||
ENV["RAILS_MASTER"] == '1'
|
||||
end
|
||||
end
|
||||
|
||||
@ -70,12 +70,13 @@ end
|
||||
gem 'seed-fu', '~> 2.3.3'
|
||||
|
||||
if rails_master?
|
||||
gem 'arel', git: 'https://github.com/rails/arel.git'
|
||||
gem 'rails', git: 'https://github.com/rails/rails.git'
|
||||
gem 'actionpack-action_caching', git: 'https://github.com/rails/actionpack-action_caching.git'
|
||||
else
|
||||
gem 'rails'
|
||||
gem 'actionpack-action_caching'
|
||||
end
|
||||
|
||||
gem 'actionpack-action_caching'
|
||||
gem 'rails-observers'
|
||||
|
||||
# Rails 4.1.6+ will relax the mail gem version requirement to `~> 2.5, >= 2.5.4`.
|
||||
@ -91,7 +92,11 @@ gem 'redis', require: ["redis", "redis/connection/hiredis"]
|
||||
# We use some ams 0.8.0 features, need to amend code
|
||||
# to support 0.9 etc, bench needs to run and ensure no
|
||||
# perf regressions
|
||||
gem 'active_model_serializers', '~> 0.8.0'
|
||||
if rails_master?
|
||||
gem 'active_model_serializers', github: 'rails-api/active_model_serializers', branch: '0-8-stable'
|
||||
else
|
||||
gem 'active_model_serializers', '~> 0.8.0'
|
||||
end
|
||||
|
||||
|
||||
gem 'onebox'
|
||||
@ -241,6 +246,8 @@ gem 'memory_profiler', require: false, platform: :mri_21
|
||||
|
||||
gem 'rmmseg-cpp', require: false
|
||||
|
||||
gem 'stringex', require: false
|
||||
|
||||
gem 'logster'
|
||||
|
||||
# perftools only works on 1.9 atm
|
||||
|
||||
62
Gemfile.lock
62
Gemfile.lock
@ -6,31 +6,31 @@ PATH
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actionmailer (4.1.7)
|
||||
actionpack (= 4.1.7)
|
||||
actionview (= 4.1.7)
|
||||
actionmailer (4.1.8)
|
||||
actionpack (= 4.1.8)
|
||||
actionview (= 4.1.8)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
actionpack (4.1.7)
|
||||
actionview (= 4.1.7)
|
||||
activesupport (= 4.1.7)
|
||||
actionpack (4.1.8)
|
||||
actionview (= 4.1.8)
|
||||
activesupport (= 4.1.8)
|
||||
rack (~> 1.5.2)
|
||||
rack-test (~> 0.6.2)
|
||||
actionpack-action_caching (1.1.1)
|
||||
actionpack (>= 4.0.0, < 5.0)
|
||||
actionview (4.1.7)
|
||||
activesupport (= 4.1.7)
|
||||
actionview (4.1.8)
|
||||
activesupport (= 4.1.8)
|
||||
builder (~> 3.1)
|
||||
erubis (~> 2.7.0)
|
||||
active_model_serializers (0.8.2)
|
||||
activemodel (>= 3.0)
|
||||
activemodel (4.1.7)
|
||||
activesupport (= 4.1.7)
|
||||
activemodel (4.1.8)
|
||||
activesupport (= 4.1.8)
|
||||
builder (~> 3.1)
|
||||
activerecord (4.1.7)
|
||||
activemodel (= 4.1.7)
|
||||
activesupport (= 4.1.7)
|
||||
activerecord (4.1.8)
|
||||
activemodel (= 4.1.8)
|
||||
activesupport (= 4.1.8)
|
||||
arel (~> 5.0.0)
|
||||
activesupport (4.1.7)
|
||||
activesupport (4.1.8)
|
||||
i18n (~> 0.6, >= 0.6.9)
|
||||
json (~> 1.7, >= 1.7.7)
|
||||
minitest (~> 5.1)
|
||||
@ -99,7 +99,7 @@ GEM
|
||||
fastimage (1.6.3)
|
||||
addressable (~> 2.3, >= 2.3.5)
|
||||
ffi (1.9.5)
|
||||
flamegraph (0.0.5)
|
||||
flamegraph (0.0.8)
|
||||
fast_stack
|
||||
fog (1.22.1)
|
||||
fog-brightbox
|
||||
@ -170,7 +170,7 @@ GEM
|
||||
metaclass (0.0.4)
|
||||
method_source (0.8.2)
|
||||
mime-types (1.25.1)
|
||||
mini_portile (0.6.0)
|
||||
mini_portile (0.6.1)
|
||||
minitest (5.4.2)
|
||||
mocha (1.1.0)
|
||||
metaclass (~> 0.0.1)
|
||||
@ -185,8 +185,8 @@ GEM
|
||||
net-ssh (>= 2.6.5)
|
||||
net-ssh (2.9.1)
|
||||
netrc (0.7.7)
|
||||
nokogiri (1.6.3.1)
|
||||
mini_portile (= 0.6.0)
|
||||
nokogiri (1.6.4.1)
|
||||
mini_portile (~> 0.6.0)
|
||||
nokogumbo (1.1.12)
|
||||
nokogiri
|
||||
oauth (0.4.7)
|
||||
@ -222,7 +222,7 @@ GEM
|
||||
omniauth-twitter (1.0.1)
|
||||
multi_json (~> 1.3)
|
||||
omniauth-oauth (~> 1.0)
|
||||
onebox (1.5.3)
|
||||
onebox (1.5.5)
|
||||
moneta (~> 0.7)
|
||||
multi_json (~> 1.7)
|
||||
mustache (~> 0.99)
|
||||
@ -255,21 +255,21 @@ GEM
|
||||
rack
|
||||
rack-test (0.6.2)
|
||||
rack (>= 1.0)
|
||||
rails (4.1.7)
|
||||
actionmailer (= 4.1.7)
|
||||
actionpack (= 4.1.7)
|
||||
actionview (= 4.1.7)
|
||||
activemodel (= 4.1.7)
|
||||
activerecord (= 4.1.7)
|
||||
activesupport (= 4.1.7)
|
||||
rails (4.1.8)
|
||||
actionmailer (= 4.1.8)
|
||||
actionpack (= 4.1.8)
|
||||
actionview (= 4.1.8)
|
||||
activemodel (= 4.1.8)
|
||||
activerecord (= 4.1.8)
|
||||
activesupport (= 4.1.8)
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 4.1.7)
|
||||
railties (= 4.1.8)
|
||||
sprockets-rails (~> 2.0)
|
||||
rails-observers (0.1.2)
|
||||
activemodel (~> 4.0)
|
||||
railties (4.1.7)
|
||||
actionpack (= 4.1.7)
|
||||
activesupport (= 4.1.7)
|
||||
railties (4.1.8)
|
||||
actionpack (= 4.1.8)
|
||||
activesupport (= 4.1.8)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
raindrops (0.13.0)
|
||||
@ -371,6 +371,7 @@ GEM
|
||||
activesupport (>= 3.0)
|
||||
sprockets (~> 2.8)
|
||||
stackprof (0.2.7)
|
||||
stringex (2.5.2)
|
||||
therubyracer (0.12.1)
|
||||
libv8 (~> 3.16.14.0)
|
||||
ref
|
||||
@ -488,6 +489,7 @@ DEPENDENCIES
|
||||
sinatra
|
||||
spork-rails
|
||||
stackprof
|
||||
stringex
|
||||
therubyracer
|
||||
thin
|
||||
timecop
|
||||
|
||||
@ -1,73 +1,80 @@
|
||||
GIT
|
||||
remote: https://github.com/rails/actionpack-action_caching.git
|
||||
revision: a9f3f09477b12b51faa6756005eee4103f7f4030
|
||||
remote: git://github.com/rails-api/active_model_serializers.git
|
||||
revision: b6b01d0b7396f3deaa6e661cedf4bc5efe2f4525
|
||||
branch: 0-8-stable
|
||||
specs:
|
||||
actionpack-action_caching (1.1.0)
|
||||
actionpack (>= 4.0.0, < 5.0)
|
||||
active_model_serializers (0.8.2)
|
||||
activemodel (>= 3.0)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/rails/arel.git
|
||||
revision: 590c784a30b13153667f8db7915998d7731e24e5
|
||||
specs:
|
||||
arel (6.0.0.beta2)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/rails/rails.git
|
||||
revision: 316962d0922992fbe756521bd7c94a751aa1253e
|
||||
revision: eb26f24bde62cbbcd8ef0e7ee9c64060b098baff
|
||||
specs:
|
||||
actionmailer (4.2.0.beta1)
|
||||
actionpack (= 4.2.0.beta1)
|
||||
actionview (= 4.2.0.beta1)
|
||||
activejob (= 4.2.0.beta1)
|
||||
actionmailer (4.2.0.beta4)
|
||||
actionpack (= 4.2.0.beta4)
|
||||
actionview (= 4.2.0.beta4)
|
||||
activejob (= 4.2.0.beta4)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.2)
|
||||
actionpack (4.2.0.beta1)
|
||||
actionview (= 4.2.0.beta1)
|
||||
activesupport (= 4.2.0.beta1)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.4)
|
||||
actionpack (4.2.0.beta4)
|
||||
actionview (= 4.2.0.beta4)
|
||||
activesupport (= 4.2.0.beta4)
|
||||
rack (~> 1.6.0.beta)
|
||||
rack-test (~> 0.6.2)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.2)
|
||||
rails-html-sanitizer (~> 1.0)
|
||||
actionview (4.2.0.beta1)
|
||||
activesupport (= 4.2.0.beta1)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.4)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.1)
|
||||
actionview (4.2.0.beta4)
|
||||
activesupport (= 4.2.0.beta4)
|
||||
builder (~> 3.1)
|
||||
erubis (~> 2.7.0)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.2)
|
||||
rails-html-sanitizer (~> 1.0)
|
||||
activejob (4.2.0.beta1)
|
||||
activesupport (= 4.2.0.beta1)
|
||||
globalid (>= 0.2.3)
|
||||
activemodel (4.2.0.beta1)
|
||||
activesupport (= 4.2.0.beta1)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.4)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.1)
|
||||
activejob (4.2.0.beta4)
|
||||
activesupport (= 4.2.0.beta4)
|
||||
globalid (>= 0.3.0)
|
||||
activemodel (4.2.0.beta4)
|
||||
activesupport (= 4.2.0.beta4)
|
||||
builder (~> 3.1)
|
||||
activerecord (4.2.0.beta1)
|
||||
activemodel (= 4.2.0.beta1)
|
||||
activesupport (= 4.2.0.beta1)
|
||||
arel (>= 6.0.0.beta1, < 6.1)
|
||||
activesupport (4.2.0.beta1)
|
||||
activerecord (4.2.0.beta4)
|
||||
activemodel (= 4.2.0.beta4)
|
||||
activesupport (= 4.2.0.beta4)
|
||||
arel (>= 6.0.0.beta2, < 6.1)
|
||||
activesupport (4.2.0.beta4)
|
||||
i18n (>= 0.7.0.beta1, < 0.8)
|
||||
json (~> 1.7, >= 1.7.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.1)
|
||||
tzinfo (~> 1.1)
|
||||
rails (4.2.0.beta1)
|
||||
actionmailer (= 4.2.0.beta1)
|
||||
actionpack (= 4.2.0.beta1)
|
||||
actionview (= 4.2.0.beta1)
|
||||
activejob (= 4.2.0.beta1)
|
||||
activemodel (= 4.2.0.beta1)
|
||||
activerecord (= 4.2.0.beta1)
|
||||
activesupport (= 4.2.0.beta1)
|
||||
rails (4.2.0.beta4)
|
||||
actionmailer (= 4.2.0.beta4)
|
||||
actionpack (= 4.2.0.beta4)
|
||||
actionview (= 4.2.0.beta4)
|
||||
activejob (= 4.2.0.beta4)
|
||||
activemodel (= 4.2.0.beta4)
|
||||
activerecord (= 4.2.0.beta4)
|
||||
activesupport (= 4.2.0.beta4)
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 4.2.0.beta1)
|
||||
railties (= 4.2.0.beta4)
|
||||
sprockets-rails (~> 3.0.0.beta1)
|
||||
railties (4.2.0.beta1)
|
||||
actionpack (= 4.2.0.beta1)
|
||||
activesupport (= 4.2.0.beta1)
|
||||
railties (4.2.0.beta4)
|
||||
actionpack (= 4.2.0.beta4)
|
||||
activesupport (= 4.2.0.beta4)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/rails/sass-rails.git
|
||||
revision: 423178729e7b84addcee78b33891644b1fc1705b
|
||||
revision: b4b5f32a2928ef203f4b442bc538a572645de8e3
|
||||
specs:
|
||||
sass-rails (5.0.0.beta1)
|
||||
railties (>= 4.0.0, < 5.0)
|
||||
sass (~> 3.2)
|
||||
sass (~> 3.2, >= 3.2.2)
|
||||
sprockets (~> 2.12)
|
||||
sprockets-rails (>= 2.0, < 4.0)
|
||||
|
||||
@ -79,16 +86,12 @@ PATH
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
active_model_serializers (0.8.2)
|
||||
activemodel (>= 3.0)
|
||||
actionpack-action_caching (1.1.1)
|
||||
actionpack (>= 4.0.0, < 5.0)
|
||||
addressable (2.3.6)
|
||||
airbrake (3.1.2)
|
||||
activesupport
|
||||
builder
|
||||
annotate (2.6.5)
|
||||
activerecord (>= 2.3.0)
|
||||
rake (>= 0.8.7)
|
||||
arel (6.0.0.beta1)
|
||||
barber (0.4.2)
|
||||
ember-source
|
||||
execjs
|
||||
@ -114,25 +117,25 @@ GEM
|
||||
dotenv-deployment (~> 0.0.2)
|
||||
dotenv-deployment (0.0.2)
|
||||
email_reply_parser-discourse (0.6)
|
||||
ember-data-source (1.0.0.beta.9)
|
||||
ember-data-source (0.14)
|
||||
ember-source
|
||||
ember-rails (0.15.0)
|
||||
ember-rails (0.14.1)
|
||||
active_model_serializers
|
||||
barber (>= 0.4.1)
|
||||
ember-data-source (>= 1.0.0.beta.5)
|
||||
ember-source (>= 1.1.0)
|
||||
ember-data-source
|
||||
ember-source
|
||||
execjs (>= 1.2)
|
||||
handlebars-source (> 1.0.0)
|
||||
handlebars-source
|
||||
jquery-rails (>= 1.0.17)
|
||||
railties (>= 3.1)
|
||||
ember-source (1.6.0.beta.2)
|
||||
handlebars-source (~> 1.0)
|
||||
erubis (2.7.0)
|
||||
eventmachine (1.0.3)
|
||||
excon (0.39.5)
|
||||
excon (0.39.6)
|
||||
execjs (2.2.1)
|
||||
exifr (1.1.3)
|
||||
fabrication (2.11.3)
|
||||
fabrication (2.9.8)
|
||||
fakeweb (1.3.0)
|
||||
faraday (0.9.0)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
@ -146,8 +149,8 @@ GEM
|
||||
fast_xs (0.8.0)
|
||||
fastimage (1.6.3)
|
||||
addressable (~> 2.3, >= 2.3.5)
|
||||
ffi (1.9.3)
|
||||
flamegraph (0.0.5)
|
||||
ffi (1.9.5)
|
||||
flamegraph (0.0.8)
|
||||
fast_stack
|
||||
fog (1.22.1)
|
||||
fog-brightbox
|
||||
@ -155,7 +158,7 @@ GEM
|
||||
fog-json
|
||||
ipaddress (~> 0.5)
|
||||
nokogiri (~> 1.5, >= 1.5.11)
|
||||
fog-brightbox (0.5.0)
|
||||
fog-brightbox (0.5.1)
|
||||
fog-core (~> 1.22)
|
||||
fog-json
|
||||
inflecto
|
||||
@ -176,7 +179,7 @@ GEM
|
||||
gctools (0.2.3)
|
||||
given_core (3.5.4)
|
||||
sorcerer (>= 0.3.7)
|
||||
globalid (0.2.3)
|
||||
globalid (0.3.0)
|
||||
activesupport (>= 4.1.0)
|
||||
guess_html_encoding (0.0.9)
|
||||
handlebars-source (1.3.0)
|
||||
@ -205,7 +208,7 @@ GEM
|
||||
librarian (0.1.2)
|
||||
highline
|
||||
thor (~> 0.15)
|
||||
libv8 (3.16.14.3)
|
||||
libv8 (3.16.14.7)
|
||||
listen (0.7.3)
|
||||
logster (0.1.6)
|
||||
loofah (2.0.1)
|
||||
@ -215,15 +218,15 @@ GEM
|
||||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
memory_profiler (0.0.4)
|
||||
message_bus (0.9.5)
|
||||
message_bus (1.0.5)
|
||||
eventmachine
|
||||
rack (>= 1.1.3)
|
||||
redis
|
||||
metaclass (0.0.4)
|
||||
method_source (0.8.2)
|
||||
mime-types (1.25.1)
|
||||
mini_portile (0.6.0)
|
||||
minitest (5.4.1)
|
||||
mini_portile (0.6.1)
|
||||
minitest (5.4.3)
|
||||
mocha (1.1.0)
|
||||
metaclass (~> 0.0.1)
|
||||
mock_redis (0.13.2)
|
||||
@ -237,8 +240,8 @@ GEM
|
||||
net-ssh (>= 2.6.5)
|
||||
net-ssh (2.9.1)
|
||||
netrc (0.7.7)
|
||||
nokogiri (1.6.3.1)
|
||||
mini_portile (= 0.6.0)
|
||||
nokogiri (1.6.4.1)
|
||||
mini_portile (~> 0.6.0)
|
||||
nokogumbo (1.1.12)
|
||||
nokogiri
|
||||
oauth (0.4.7)
|
||||
@ -274,7 +277,7 @@ GEM
|
||||
omniauth-twitter (1.0.1)
|
||||
multi_json (~> 1.3)
|
||||
omniauth-oauth (~> 1.0)
|
||||
onebox (1.4.9)
|
||||
onebox (1.5.3)
|
||||
moneta (~> 0.7)
|
||||
multi_json (~> 1.7)
|
||||
mustache (~> 0.99)
|
||||
@ -293,7 +296,7 @@ GEM
|
||||
pry (>= 0.9.10, < 0.11.0)
|
||||
pry-rails (0.3.2)
|
||||
pry (>= 0.9.10)
|
||||
puma (2.9.0)
|
||||
puma (2.9.1)
|
||||
rack (>= 1.1, < 2.0)
|
||||
qunit-rails (0.0.7)
|
||||
railties
|
||||
@ -307,13 +310,13 @@ GEM
|
||||
rack
|
||||
rack-test (0.6.2)
|
||||
rack (>= 1.0)
|
||||
rails-deprecated_sanitizer (1.0.2)
|
||||
rails-deprecated_sanitizer (1.0.3)
|
||||
activesupport (>= 4.2.0.alpha)
|
||||
rails-dom-testing (1.0.2)
|
||||
activesupport
|
||||
rails-dom-testing (1.0.4)
|
||||
activesupport (>= 4.2.0.beta, < 5.0)
|
||||
nokogiri (~> 1.6.0)
|
||||
rails-deprecated_sanitizer (>= 1.0.1)
|
||||
rails-html-sanitizer (1.0.0)
|
||||
rails-html-sanitizer (1.0.1)
|
||||
loofah (~> 2.0)
|
||||
rails-observers (0.1.2)
|
||||
activemodel (~> 4.0)
|
||||
@ -338,29 +341,28 @@ GEM
|
||||
netrc (~> 0.7)
|
||||
rinku (1.7.3)
|
||||
rmmseg-cpp (0.2.9)
|
||||
rspec (3.0.0)
|
||||
rspec-core (~> 3.0.0)
|
||||
rspec-expectations (~> 3.0.0)
|
||||
rspec-mocks (~> 3.0.0)
|
||||
rspec-core (3.0.4)
|
||||
rspec-support (~> 3.0.0)
|
||||
rspec-expectations (3.0.4)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.0.0)
|
||||
rspec (2.99.0)
|
||||
rspec-core (~> 2.99.0)
|
||||
rspec-expectations (~> 2.99.0)
|
||||
rspec-mocks (~> 2.99.0)
|
||||
rspec-collection_matchers (1.0.0)
|
||||
rspec-expectations (>= 2.99.0.beta1)
|
||||
rspec-core (2.99.2)
|
||||
rspec-expectations (2.99.2)
|
||||
diff-lcs (>= 1.1.3, < 2.0)
|
||||
rspec-given (3.5.4)
|
||||
given_core (= 3.5.4)
|
||||
rspec (>= 2.12)
|
||||
rspec-mocks (3.0.4)
|
||||
rspec-support (~> 3.0.0)
|
||||
rspec-rails (3.0.2)
|
||||
rspec-mocks (2.99.2)
|
||||
rspec-rails (2.99.0)
|
||||
actionpack (>= 3.0)
|
||||
activemodel (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
rspec-core (~> 3.0.0)
|
||||
rspec-expectations (~> 3.0.0)
|
||||
rspec-mocks (~> 3.0.0)
|
||||
rspec-support (~> 3.0.0)
|
||||
rspec-support (3.0.4)
|
||||
rspec-collection_matchers
|
||||
rspec-core (~> 2.99.0)
|
||||
rspec-expectations (~> 2.99.0)
|
||||
rspec-mocks (~> 2.99.0)
|
||||
rtlit (0.0.5)
|
||||
ruby-openid (2.5.0)
|
||||
ruby-readability (0.7.0)
|
||||
@ -370,7 +372,7 @@ GEM
|
||||
crass (~> 0.2.0)
|
||||
nokogiri (>= 1.4.4)
|
||||
nokogumbo (= 1.1.12)
|
||||
sass (3.4.2)
|
||||
sass (3.2.19)
|
||||
seed-fu (2.3.3)
|
||||
activerecord (>= 3.1, < 4.2)
|
||||
activesupport (>= 3.1, < 4.2)
|
||||
@ -380,16 +382,16 @@ GEM
|
||||
shoulda-context (1.2.1)
|
||||
shoulda-matchers (2.7.0)
|
||||
activesupport (>= 3.0.0)
|
||||
sidekiq (3.2.3)
|
||||
celluloid (>= 0.15.2)
|
||||
sidekiq (3.2.5)
|
||||
celluloid (= 0.15.2)
|
||||
connection_pool (>= 2.0.0)
|
||||
json
|
||||
redis (>= 3.0.6)
|
||||
redis-namespace (>= 1.3.1)
|
||||
simple-rss (1.3.1)
|
||||
simplecov (0.9.0)
|
||||
simplecov (0.9.1)
|
||||
docile (~> 1.1.0)
|
||||
multi_json
|
||||
multi_json (~> 1.0)
|
||||
simplecov-html (~> 0.8.0)
|
||||
simplecov-html (0.8.0)
|
||||
sinatra (1.4.5)
|
||||
@ -402,7 +404,7 @@ GEM
|
||||
spork-rails (4.0.0)
|
||||
rails (>= 3.0.0, < 5)
|
||||
spork (>= 1.0rc0)
|
||||
sprockets (2.12.1)
|
||||
sprockets (2.12.3)
|
||||
hike (~> 1.2)
|
||||
multi_json (~> 1.0)
|
||||
rack (~> 1.0)
|
||||
@ -412,6 +414,7 @@ GEM
|
||||
activesupport (>= 4.0)
|
||||
sprockets (~> 2.8)
|
||||
stackprof (0.2.7)
|
||||
stringex (2.5.2)
|
||||
therubyracer (0.12.1)
|
||||
libv8 (~> 3.16.14.0)
|
||||
ref
|
||||
@ -445,10 +448,10 @@ PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
actionpack-action_caching!
|
||||
active_model_serializers (~> 0.8.0)
|
||||
airbrake (= 3.1.2)
|
||||
actionpack-action_caching
|
||||
active_model_serializers!
|
||||
annotate
|
||||
arel!
|
||||
barber
|
||||
better_errors
|
||||
binding_of_caller
|
||||
@ -457,7 +460,7 @@ DEPENDENCIES
|
||||
ember-rails
|
||||
ember-source (= 1.6.0.beta.2)
|
||||
eventmachine
|
||||
fabrication
|
||||
fabrication (= 2.9.8)
|
||||
fakeweb (~> 1.3.0)
|
||||
fast_blank
|
||||
fast_xor
|
||||
@ -514,6 +517,7 @@ DEPENDENCIES
|
||||
rest-client
|
||||
rinku
|
||||
rmmseg-cpp
|
||||
rspec (= 2.99.0)
|
||||
rspec-given
|
||||
rspec-rails
|
||||
rtlit
|
||||
@ -529,6 +533,7 @@ DEPENDENCIES
|
||||
sinatra
|
||||
spork-rails
|
||||
stackprof
|
||||
stringex
|
||||
therubyracer
|
||||
thin
|
||||
timecop
|
||||
|
||||
@ -23,14 +23,14 @@ export default Ember.Component.extend({
|
||||
}
|
||||
|
||||
if (!this.get("other_accounts")) {
|
||||
this.set("other_accounts_loading", true);
|
||||
this.set("otherAccountsLoading", true);
|
||||
Discourse.AdminUser.findAll("active", {
|
||||
"ip": this.get("ip"),
|
||||
"exclude": this.get("user_id")
|
||||
}).then(function (users) {
|
||||
self.setProperties({
|
||||
other_accounts: users,
|
||||
other_accounts_loading: false,
|
||||
otherAccountsLoading: false,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -2,10 +2,10 @@ import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
||||
import ObjectController from 'discourse/controllers/object';
|
||||
|
||||
export default ObjectController.extend(ModalFunctionality, {
|
||||
needs: ["adminFlags"],
|
||||
needs: ["admin-flags-list"],
|
||||
|
||||
_agreeFlag: function (actionOnPost) {
|
||||
var adminFlagController = this.get("controllers.adminFlags");
|
||||
var adminFlagController = this.get("controllers.admin-flags-list");
|
||||
var post = this.get("content");
|
||||
var self = this;
|
||||
|
||||
|
||||
@ -3,13 +3,12 @@ import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
||||
import ObjectController from 'discourse/controllers/object';
|
||||
|
||||
export default ObjectController.extend(ModalFunctionality, {
|
||||
|
||||
needs: ["adminFlags"],
|
||||
needs: ["admin-flags-list"],
|
||||
|
||||
actions: {
|
||||
|
||||
deletePostDeferFlag: function () {
|
||||
var adminFlagController = this.get("controllers.adminFlags");
|
||||
var adminFlagController = this.get("controllers.admin-flags-list");
|
||||
var post = this.get("content");
|
||||
var self = this;
|
||||
|
||||
@ -22,7 +21,7 @@ export default ObjectController.extend(ModalFunctionality, {
|
||||
},
|
||||
|
||||
deletePostAgreeFlag: function () {
|
||||
var adminFlagController = this.get("controllers.adminFlags");
|
||||
var adminFlagController = this.get("controllers.admin-flags-list");
|
||||
var post = this.get("content");
|
||||
var self = this;
|
||||
|
||||
|
||||
@ -1,13 +1,5 @@
|
||||
import ObjectController from 'discourse/controllers/object';
|
||||
|
||||
/**
|
||||
This controller previews an email digest
|
||||
|
||||
@class AdminEmailPreviewDigestController
|
||||
@extends ObjectController
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
export default ObjectController.extend({
|
||||
|
||||
actions: {
|
||||
|
||||
@ -1,18 +1,10 @@
|
||||
/**
|
||||
This controller supports the interface for dealing with flags in the admin section.
|
||||
|
||||
@class AdminFlagsController
|
||||
@extends Ember.Controller
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
export default Ember.ArrayController.extend({
|
||||
query: null,
|
||||
|
||||
adminOldFlagsView: Em.computed.equal("query", "old"),
|
||||
adminActiveFlagsView: Em.computed.equal("query", "active"),
|
||||
|
||||
actions: {
|
||||
|
||||
disagreeFlags: function (flaggedPost) {
|
||||
var self = this;
|
||||
flaggedPost.disagreeFlags().then(function () {
|
||||
@ -1,14 +1,5 @@
|
||||
/**
|
||||
This controller supports the interface for listing screened email addresses in the admin section.
|
||||
|
||||
@class AdminLogsScreenedEmailsController
|
||||
@extends Ember.ArrayController
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
export default Ember.ArrayController.extend(Discourse.Presence, {
|
||||
loading: false,
|
||||
content: [],
|
||||
|
||||
actions: {
|
||||
clearBlock: function(row){
|
||||
@ -23,7 +14,7 @@ export default Ember.ArrayController.extend(Discourse.Presence, {
|
||||
var self = this;
|
||||
this.set('loading', true);
|
||||
Discourse.ScreenedEmail.findAll().then(function(result) {
|
||||
self.set('content', result);
|
||||
self.set('model', result);
|
||||
self.set('loading', false);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,28 +1,19 @@
|
||||
/**
|
||||
This controller supports the interface for listing screened IP addresses in the admin section.
|
||||
|
||||
@class AdminLogsScreenedIpAddressesController
|
||||
@extends Ember.ArrayController
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
export default Ember.ArrayController.extend(Discourse.Presence, {
|
||||
loading: false,
|
||||
content: [],
|
||||
itemController: 'admin-log-screened-ip-address',
|
||||
|
||||
show: function() {
|
||||
var self = this;
|
||||
this.set('loading', true);
|
||||
Discourse.ScreenedIpAddress.findAll().then(function(result) {
|
||||
self.set('content', result);
|
||||
self.set('model', result);
|
||||
self.set('loading', false);
|
||||
});
|
||||
},
|
||||
|
||||
actions: {
|
||||
recordAdded: function(arg) {
|
||||
this.get("content").unshiftObject(arg);
|
||||
this.get("model").unshiftObject(arg);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,20 +1,11 @@
|
||||
/**
|
||||
This controller supports the interface for listing screened URLs in the admin section.
|
||||
|
||||
@class AdminLogsScreenedUrlsController
|
||||
@extends Ember.ArrayController
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
export default Ember.ArrayController.extend(Discourse.Presence, {
|
||||
loading: false,
|
||||
content: [],
|
||||
|
||||
show: function() {
|
||||
var self = this;
|
||||
this.set('loading', true);
|
||||
Discourse.ScreenedUrl.findAll().then(function(result) {
|
||||
self.set('content', result);
|
||||
self.set('model', result);
|
||||
self.set('loading', false);
|
||||
});
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ export default Ember.ArrayController.extend(Discourse.Presence, {
|
||||
this.set('loading', true);
|
||||
Discourse.URL.set('queryParams', this.get('filters')); // TODO: doesn't work
|
||||
Discourse.StaffActionLog.findAll(this.get('filters')).then(function(result) {
|
||||
self.set('content', result);
|
||||
self.set('model', result);
|
||||
self.set('loading', false);
|
||||
});
|
||||
}.observes('filters.action_name', 'filters.acting_user', 'filters.target_user', 'filters.subject'),
|
||||
|
||||
@ -10,7 +10,6 @@ export default Ember.ArrayController.extend(Discourse.Presence, {
|
||||
username: null,
|
||||
query: null,
|
||||
selectAll: false,
|
||||
content: null,
|
||||
loading: false,
|
||||
|
||||
mustApproveUsers: Discourse.computed.setting('must_approve_users'),
|
||||
@ -27,7 +26,7 @@ export default Ember.ArrayController.extend(Discourse.Presence, {
|
||||
**/
|
||||
selectAllChanged: function() {
|
||||
var _this = this;
|
||||
_.each(this.get('content'),function(user) {
|
||||
_.each(this.get('model'),function(user) {
|
||||
user.set('selected', _this.get('selectAll'));
|
||||
});
|
||||
}.observes('selectAll'),
|
||||
@ -74,9 +73,9 @@ export default Ember.ArrayController.extend(Discourse.Presence, {
|
||||
@property selectedCount
|
||||
**/
|
||||
selectedCount: function() {
|
||||
if (this.blank('content')) return 0;
|
||||
return this.get('content').filterProperty('selected').length;
|
||||
}.property('content.@each.selected'),
|
||||
if (this.blank('model')) return 0;
|
||||
return this.get('model').filterProperty('selected').length;
|
||||
}.property('model.@each.selected'),
|
||||
|
||||
/**
|
||||
Do we have any selected users?
|
||||
@ -95,7 +94,7 @@ export default Ember.ArrayController.extend(Discourse.Presence, {
|
||||
adminUsersListController.set('loading', true);
|
||||
|
||||
Discourse.AdminUser.findAll(this.get('query'), { filter: this.get('username'), show_emails: showEmails }).then(function (result) {
|
||||
adminUsersListController.set('content', result);
|
||||
adminUsersListController.set('model', result);
|
||||
adminUsersListController.set('loading', false);
|
||||
});
|
||||
},
|
||||
@ -114,36 +113,28 @@ export default Ember.ArrayController.extend(Discourse.Presence, {
|
||||
this.set('query', term);
|
||||
},
|
||||
|
||||
/**
|
||||
Approve all the currently selected users.
|
||||
actions: {
|
||||
approveUsers: function() {
|
||||
Discourse.AdminUser.bulkApprove(this.get('model').filterProperty('selected'));
|
||||
this.refreshUsers();
|
||||
},
|
||||
|
||||
@method approveUsers
|
||||
**/
|
||||
approveUsers: function() {
|
||||
Discourse.AdminUser.bulkApprove(this.get('content').filterProperty('selected'));
|
||||
this.refreshUsers();
|
||||
},
|
||||
rejectUsers: function() {
|
||||
var controller = this;
|
||||
Discourse.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});
|
||||
message += ' ' + I18n.t("admin.user.delete_forbidden", {count: Discourse.SiteSettings.delete_user_max_post_age});
|
||||
}
|
||||
bootbox.alert(message);
|
||||
controller.refreshUsers();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
Reject all the currently selected users.
|
||||
|
||||
@method rejectUsers
|
||||
**/
|
||||
rejectUsers: function() {
|
||||
var controller = this;
|
||||
Discourse.AdminUser.bulkReject(this.get('content').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});
|
||||
message += ' ' + I18n.t("admin.user.delete_forbidden", {count: Discourse.SiteSettings.delete_user_max_post_age});
|
||||
}
|
||||
bootbox.alert(message);
|
||||
controller.refreshUsers();
|
||||
});
|
||||
},
|
||||
|
||||
showEmails: function() {
|
||||
this.refreshUsers(true);
|
||||
showEmails: function() {
|
||||
this.refreshUsers(true);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@ -314,7 +314,7 @@ Discourse.AdminUser = Discourse.User.extend({
|
||||
}
|
||||
}.property('deleteForbidden'),
|
||||
|
||||
destroy: function() {
|
||||
destroy: function(opts) {
|
||||
var user = this;
|
||||
|
||||
var performDestroy = function(block) {
|
||||
@ -324,6 +324,9 @@ Discourse.AdminUser = Discourse.User.extend({
|
||||
formData["block_urls"] = true;
|
||||
formData["block_ip"] = true;
|
||||
}
|
||||
if (opts && opts.deletePosts) {
|
||||
formData["delete_posts"] = true;
|
||||
}
|
||||
Discourse.ajax("/admin/users/" + user.get('id') + '.json', {
|
||||
type: 'DELETE',
|
||||
data: formData
|
||||
|
||||
@ -7,47 +7,38 @@
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.SiteCustomization = Discourse.Model.extend({
|
||||
trackedProperties: ['enabled', 'name', 'stylesheet', 'header', 'mobile_stylesheet', 'mobile_header', 'override_default_style'],
|
||||
trackedProperties: ['enabled', 'name', 'stylesheet', 'header', 'footer', 'mobile_stylesheet', 'mobile_header', 'mobile_footer', 'override_default_style'],
|
||||
|
||||
description: function() {
|
||||
return "" + this.name + (this.enabled ? ' (*)' : '');
|
||||
}.property('selected', 'name'),
|
||||
|
||||
changed: function() {
|
||||
var self = this;
|
||||
|
||||
var _this = this;
|
||||
if(!this.originals) return false;
|
||||
if (!this.originals) { return false; }
|
||||
|
||||
var changed = _.some(this.trackedProperties,function(p) {
|
||||
return _this.originals[p] !== _this.get(p);
|
||||
var changed = _.some(this.trackedProperties, function (p) {
|
||||
return self.originals[p] !== self.get(p);
|
||||
});
|
||||
|
||||
if(changed){
|
||||
this.set('savingStatus','');
|
||||
}
|
||||
if (changed) { this.set('savingStatus', ''); }
|
||||
|
||||
return changed;
|
||||
|
||||
}.property('override_default_style', 'enabled', 'name', 'stylesheet', 'header', 'mobile_stylesheet', 'mobile_header', 'originals'),
|
||||
}.property('override_default_style', 'enabled', 'name', 'stylesheet', 'header', 'footer', 'mobile_stylesheet', 'mobile_header', 'mobile_footer', 'originals'),
|
||||
|
||||
startTrackingChanges: function() {
|
||||
var _this = this;
|
||||
var self = this;
|
||||
var originals = {};
|
||||
_.each(this.trackedProperties,function(prop) {
|
||||
originals[prop] = _this.get(prop);
|
||||
return true;
|
||||
_.each(this.trackedProperties, function (prop) {
|
||||
originals[prop] = self.get(prop);
|
||||
});
|
||||
this.set('originals', originals);
|
||||
}.on('init'),
|
||||
|
||||
previewUrl: function() {
|
||||
return "/?preview-style=" + (this.get('key'));
|
||||
}.property('key'),
|
||||
|
||||
disableSave: function() {
|
||||
return !this.get('changed') || this.get('saving');
|
||||
}.property('changed'),
|
||||
|
||||
previewUrl: function() { return "/?preview-style=" + this.get('key'); }.property('key'),
|
||||
disableSave: function() { return !this.get('changed') || this.get('saving'); }.property('changed'),
|
||||
|
||||
save: function() {
|
||||
this.set('savingStatus', I18n.t('saving'));
|
||||
@ -57,8 +48,10 @@ Discourse.SiteCustomization = Discourse.Model.extend({
|
||||
enabled: this.enabled,
|
||||
stylesheet: this.stylesheet,
|
||||
header: this.header,
|
||||
footer: this.footer,
|
||||
mobile_stylesheet: this.mobile_stylesheet,
|
||||
mobile_header: this.mobile_header,
|
||||
mobile_footer: this.mobile_footer,
|
||||
override_default_style: this.override_default_style
|
||||
};
|
||||
|
||||
@ -75,23 +68,19 @@ Discourse.SiteCustomization = Discourse.Model.extend({
|
||||
siteCustomization.set('saving',false);
|
||||
siteCustomization.startTrackingChanges();
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
if(!this.id) return;
|
||||
return Discourse.ajax("/admin/site_customizations/" + this.id, {
|
||||
type: 'DELETE'
|
||||
});
|
||||
if (!this.id) return;
|
||||
return Discourse.ajax("/admin/site_customizations/" + this.id, { type: 'DELETE' });
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var SiteCustomizations = Ember.ArrayProxy.extend({
|
||||
selectedItemChanged: function() {
|
||||
var selected = this.get('selectedItem');
|
||||
_.each(this.get('content'),function(i) {
|
||||
return i.set('selected', selected === i);
|
||||
_.each(this.get('content'), function (i) {
|
||||
i.set('selected', selected === i);
|
||||
});
|
||||
}.observes('selectedItem')
|
||||
});
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
export default Discourse.Route.extend({
|
||||
redirect: function() {
|
||||
this.replaceWith('adminFlags.list', 'active');
|
||||
}
|
||||
});
|
||||
24
app/assets/javascripts/admin/routes/admin-flags-list.js.es6
Normal file
24
app/assets/javascripts/admin/routes/admin-flags-list.js.es6
Normal file
@ -0,0 +1,24 @@
|
||||
export default Discourse.Route.extend({
|
||||
model: function(params) {
|
||||
this.filter = params.filter;
|
||||
return Discourse.FlaggedPost.findAll(params.filter);
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
controller.set('model', model);
|
||||
controller.set('query', this.filter);
|
||||
},
|
||||
|
||||
actions: {
|
||||
showAgreeFlagModal: function (flaggedPost) {
|
||||
Discourse.Route.showModal(this, 'admin_agree_flag', flaggedPost);
|
||||
this.controllerFor('modal').set('modalClass', 'agree-flag-modal');
|
||||
},
|
||||
|
||||
showDeleteFlagModal: function (flaggedPost) {
|
||||
Discourse.Route.showModal(this, 'admin_delete_flag', flaggedPost);
|
||||
this.controllerFor('modal').set('modalClass', 'delete-flag-modal');
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
@ -1,41 +0,0 @@
|
||||
Discourse.AdminFlagsIndexRoute = Discourse.Route.extend({
|
||||
redirect: function() {
|
||||
this.transitionTo('adminFlags.active');
|
||||
}
|
||||
});
|
||||
|
||||
Discourse.AdminFlagsRouteType = Discourse.Route.extend({
|
||||
model: function() {
|
||||
return Discourse.FlaggedPost.findAll(this.get('filter'));
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
var adminFlagsController = this.controllerFor('adminFlags');
|
||||
adminFlagsController.set('content', model);
|
||||
adminFlagsController.set('query', this.get('filter'));
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
Discourse.AdminFlagsActiveRoute = Discourse.AdminFlagsRouteType.extend({
|
||||
filter: 'active',
|
||||
|
||||
actions: {
|
||||
|
||||
showAgreeFlagModal: function (flaggedPost) {
|
||||
Discourse.Route.showModal(this, 'admin_agree_flag', flaggedPost);
|
||||
this.controllerFor('modal').set('modalClass', 'agree-flag-modal');
|
||||
},
|
||||
|
||||
showDeleteFlagModal: function (flaggedPost) {
|
||||
Discourse.Route.showModal(this, 'admin_delete_flag', flaggedPost);
|
||||
this.controllerFor('modal').set('modalClass', 'delete-flag-modal');
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Discourse.AdminFlagsOldRoute = Discourse.AdminFlagsRouteType.extend({
|
||||
filter: 'old'
|
||||
});
|
||||
@ -30,8 +30,7 @@ Discourse.Route.buildRoutes(function() {
|
||||
this.resource('adminReports', { path: '/reports/:type' });
|
||||
|
||||
this.resource('adminFlags', { path: '/flags' }, function() {
|
||||
this.route('active');
|
||||
this.route('old');
|
||||
this.route('list', { path: '/:filter' });
|
||||
});
|
||||
|
||||
this.resource('adminLogs', { path: '/logs' }, function() {
|
||||
|
||||
@ -2,71 +2,58 @@
|
||||
<h3>{{i18n admin.customize.css_html.long_title}}</h3>
|
||||
<ul>
|
||||
{{#each model}}
|
||||
<li><a {{action "selectStyle" this}} {{bind-attr class="this.selected:active"}}>{{this.description}}</a></li>
|
||||
<li><a {{action "selectStyle" this}} {{bind-attr class="this.selected:active"}}>{{this.description}}</a></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
<button {{action "newCustomization"}} class='btn'><i class="fa fa-plus"></i>{{i18n admin.customize.new}}</button>
|
||||
<button {{action "newCustomization"}} class='btn'>
|
||||
{{fa-icon "plus"}}{{i18n admin.customize.new}}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
{{#if selectedItem}}
|
||||
<div class='current-style'>
|
||||
{{#with selectedItem}}
|
||||
{{text-field class="style-name" value=name}}
|
||||
<div class='current-style'>
|
||||
{{#with selectedItem}}
|
||||
{{text-field class="style-name" value=name}}
|
||||
|
||||
<div class='admin-controls'>
|
||||
<ul class="nav nav-pills">
|
||||
<li>
|
||||
<a {{bind-attr class="view.stylesheetActive:active"}}{{action "selectStylesheet" href="true" target="view"}}>{{i18n admin.customize.css}}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a {{bind-attr class="view.headerActive:active"}}{{action "selectHeader" href="true" target="view"}}>{{i18n admin.customize.header}}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a {{bind-attr class="view.mobileStylesheetActive:active"}}{{action "selectMobileStylesheet" href="true" target="view"}}>{{i18n admin.customize.mobile_css}}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a {{bind-attr class="view.mobileHeaderActive:active"}}{{action "selectMobileHeader" href="true" target="view"}}>{{i18n admin.customize.mobile_header}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class='admin-controls'>
|
||||
<ul class="nav nav-pills">
|
||||
<li><a {{bind-attr class="view.stylesheetActive:active"}} {{action "selectStylesheet" target="view"}}>{{i18n admin.customize.css}}</a></li>
|
||||
<li><a {{bind-attr class="view.headerActive:active"}} {{action "selectHeader" target="view"}}>{{i18n admin.customize.header}}</a></li>
|
||||
<li><a {{bind-attr class="view.footerActive:active"}} {{action "selectFooter" target="view"}}>{{i18n admin.customize.footer}}</a></li>
|
||||
<li><a {{bind-attr class="view.mobileStylesheetActive:active"}} {{action "selectMobileStylesheet" target="view"}}>{{fa-icon "mobile"}} {{i18n admin.customize.css}}</a></li>
|
||||
<li><a {{bind-attr class="view.mobileHeaderActive:active"}} {{action "selectMobileHeader" target="view"}}>{{fa-icon "mobile"}} {{i18n admin.customize.header}}</a></li>
|
||||
<li><a {{bind-attr class="view.mobileFooterActive:active"}} {{action "selectMobileFooter" target="view"}}>{{fa-icon "mobile"}} {{i18n admin.customize.footer}}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="admin-container">
|
||||
{{#if view.stylesheetActive}}{{aceEditor content=stylesheet mode="scss"}}{{/if}}
|
||||
{{#if view.headerActive}}{{aceEditor content=header mode="html"}}{{/if}}
|
||||
{{#if view.footerActive}}{{aceEditor content=footer mode="html"}}{{/if}}
|
||||
{{#if view.mobileStylesheetActive}}{{aceEditor content=mobile_stylesheet mode="scss"}}{{/if}}
|
||||
{{#if view.mobileHeaderActive}}{{aceEditor content=mobile_header mode="html"}}{{/if}}
|
||||
{{#if view.mobileFooterActive}}{{aceEditor content=mobile_footer mode="html"}}{{/if}}
|
||||
</div>
|
||||
{{/with}}
|
||||
<br>
|
||||
<div class='status-actions'>
|
||||
<span>{{i18n admin.customize.override_default}} {{view Ember.Checkbox checkedBinding="selectedItem.override_default_style"}}</span>
|
||||
<span>{{i18n admin.customize.enabled}} {{view Ember.Checkbox checkedBinding="selectedItem.enabled"}}</span>
|
||||
{{#unless selectedItem.changed}}
|
||||
<a class='preview-link' {{bind-attr href="selectedItem.previewUrl"}} target='_blank' title="{{i18n admin.customize.explain_preview}}">{{i18n admin.customize.preview}}</a>
|
||||
|
|
||||
<a href="/?preview-style=" target='_blank' title="{{i18n admin.customize.explain_undo_preview}}">{{i18n admin.customize.undo_preview}}</a>
|
||||
|
|
||||
<a href="/?preview-style=default" target='_blank' title="{{i18n admin.customize.explain_rescue_preview}}">{{i18n admin.customize.rescue_preview}}</a><br>
|
||||
{{/unless}}
|
||||
</div>
|
||||
|
||||
<div class="admin-container">
|
||||
{{#if view.headerActive}}
|
||||
{{aceEditor content=header mode="html"}}
|
||||
{{/if}}
|
||||
{{#if view.stylesheetActive}}
|
||||
{{aceEditor content=stylesheet mode="scss"}}
|
||||
{{/if}}
|
||||
{{#if view.mobileHeaderActive}}
|
||||
{{aceEditor content=mobile_header mode="html"}}
|
||||
{{/if}}
|
||||
{{#if view.mobileStylesheetActive}}
|
||||
{{aceEditor content=mobile_stylesheet mode="scss"}}
|
||||
{{/if}}
|
||||
<div class='buttons'>
|
||||
<button {{action "save"}} {{bind-attr disabled="selectedItem.disableSave"}} class='btn'>{{i18n admin.customize.save}}</button>
|
||||
<span class='saving'>{{selectedItem.savingStatus}}</span>
|
||||
<a {{action "destroy"}} class='delete-link'>{{i18n admin.customize.delete}}</a>
|
||||
</div>
|
||||
{{/with}}
|
||||
<br>
|
||||
<div class='status-actions'>
|
||||
<span>{{i18n admin.customize.override_default}} {{view Ember.Checkbox checkedBinding="selectedItem.override_default_style"}}</span>
|
||||
<span>{{i18n admin.customize.enabled}} {{view Ember.Checkbox checkedBinding="selectedItem.enabled"}}</span>
|
||||
{{#unless selectedItem.changed}}
|
||||
<a class='preview-link' {{bind-attr href="selectedItem.previewUrl"}} target='_blank' title="{{i18n admin.customize.explain_preview}}">{{i18n admin.customize.preview}}</a>
|
||||
|
|
||||
<a href="/?preview-style=" target='_blank' title="{{i18n admin.customize.explain_undo_preview}}">{{i18n admin.customize.undo_preview}}</a>
|
||||
|
|
||||
<a href="/?preview-style=default" target='_blank' title="{{i18n admin.customize.explain_rescue_preview}}">{{i18n admin.customize.rescue_preview}}</a><br>
|
||||
{{/unless}}
|
||||
</div>
|
||||
|
||||
<div class='buttons'>
|
||||
<button {{action "save"}} {{bind-attr disabled="selectedItem.disableSave"}} class='btn'>{{i18n admin.customize.save}}</button>
|
||||
<span class='saving'>{{selectedItem.savingStatus}}</span>
|
||||
<a {{action "destroy"}} class='delete-link'>{{i18n admin.customize.delete}}</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{{else}}
|
||||
<p class="about">{{i18n admin.customize.about}}</p>
|
||||
{{/if}}
|
||||
<div class='clearfix'></div>
|
||||
|
||||
@ -18,14 +18,10 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if loading}}
|
||||
{{loading-spinner}}
|
||||
{{else}}
|
||||
{{#loading-spinner condition=loading}}
|
||||
{{#if showHtml}}
|
||||
{{{html_content}}}
|
||||
{{else}}
|
||||
<pre>{{{text_content}}}</pre>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
|
||||
{{/loading-spinner}}
|
||||
|
||||
153
app/assets/javascripts/admin/templates/flags-list.hbs
Normal file
153
app/assets/javascripts/admin/templates/flags-list.hbs
Normal file
@ -0,0 +1,153 @@
|
||||
{{#if length}}
|
||||
<table class='admin-flags'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='user'></th>
|
||||
<th class='excerpt'></th>
|
||||
<th class='flaggers'>{{i18n admin.flags.flagged_by}}</th>
|
||||
<th class='flaggers'>{{#if adminOldFlagsView}}{{i18n admin.flags.resolved_by}}{{/if}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each flaggedPost in content}}
|
||||
<tr {{bind-attr class="flaggedPost.extraClasses"}}>
|
||||
|
||||
<td class='user'>
|
||||
{{#if flaggedPost.postAuthorFlagged}}
|
||||
{{#if flaggedPost.user}}
|
||||
{{#link-to 'adminUser' flaggedPost.user}}{{avatar flaggedPost.user imageSize="small"}}{{/link-to}}
|
||||
{{#if flaggedPost.wasEdited}}<i class="fa fa-pencil" title="{{i18n admin.flags.was_edited}}"></i>{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{#if adminActiveFlagsView}}
|
||||
{{#if flaggedPost.previous_flags_count}}
|
||||
<span title="{{i18n admin.flags.previous_flags_count count=flaggedPost.previous_flags_count}}" class="badge-notification flagged-posts">{{flaggedPost.previous_flags_count}}</span>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</td>
|
||||
|
||||
<td class='excerpt'>
|
||||
<h3>
|
||||
{{#if flaggedPost.topic.isPrivateMessage}}
|
||||
<span class="private-message-glyph">{{fa-icon envelope}}</span>
|
||||
{{/if}}
|
||||
{{topic-status topic=flaggedPost.topic}}
|
||||
<a href='{{unbound flaggedPost.url}}'>{{flaggedPost.topic.title}}</a>
|
||||
</h3>
|
||||
{{#if flaggedPost.postAuthorFlagged}}
|
||||
{{{flaggedPost.excerpt}}}
|
||||
{{/if}}
|
||||
</td>
|
||||
|
||||
<td class='flaggers'>
|
||||
<table>
|
||||
<tbody>
|
||||
{{#each flaggedPost.flaggers}}
|
||||
<tr>
|
||||
<td class='avatar'>
|
||||
{{#link-to 'adminUser' user}}
|
||||
{{avatar user imageSize="small"}}
|
||||
{{/link-to}}
|
||||
</td>
|
||||
<td>
|
||||
{{#link-to 'adminUser' user}}
|
||||
{{user.username}}
|
||||
{{/link-to}}
|
||||
{{format-age flaggedAt}}
|
||||
<br />
|
||||
{{flagType}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
|
||||
<td class='flaggers result'>
|
||||
{{#if adminOldFlagsView}}
|
||||
<table>
|
||||
<tbody>
|
||||
{{#each flaggedPost.flaggers}}
|
||||
<tr>
|
||||
<td class='avatar'>
|
||||
{{#link-to 'adminUser' disposedBy}}
|
||||
{{avatar disposedBy imageSize="small"}}
|
||||
{{/link-to}}
|
||||
</td>
|
||||
<td>
|
||||
{{format-age disposedAt}}
|
||||
{{{dispositionIcon}}}
|
||||
{{#if tookAction}}
|
||||
<i class='fa fa-gavel' title='{{i18n admin.flags.took_action}}'></i>
|
||||
{{/if}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{/if}}
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
{{#if flaggedPost.topicFlagged}}
|
||||
<tr class='message'>
|
||||
<td></td>
|
||||
<td colspan="3">
|
||||
<div>
|
||||
{{{i18n admin.flags.topic_flagged}}} <a href='{{unbound flaggedPost.url}}' class="btn">{{i18n admin.flags.visit_topic}}</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
|
||||
{{#each flaggedPost.conversations}}
|
||||
<tr class='message'>
|
||||
<td></td>
|
||||
<td colspan="3">
|
||||
<div>
|
||||
{{#if response}}
|
||||
<p>
|
||||
{{#link-to 'adminUser' response.user}}{{avatar response.user imageSize="small"}}{{/link-to}} {{{response.excerpt}}}
|
||||
</p>
|
||||
{{#if reply}}
|
||||
<p>
|
||||
{{#link-to 'adminUser' reply.user}}{{avatar reply.user imageSize="small"}}{{/link-to}} {{{reply.excerpt}}}
|
||||
{{#if hasMore}}
|
||||
<a href="{{unbound permalink}}">{{i18n admin.flags.more}}</a>
|
||||
{{/if}}
|
||||
</p>
|
||||
{{/if}}
|
||||
<a href="{{unbound permalink}}">
|
||||
<button class='btn btn-reply'><i class="fa fa-reply"></i> {{i18n admin.flags.reply_message}}</button>
|
||||
</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
|
||||
<tr>
|
||||
<td colspan="4" class="action">
|
||||
{{#if adminActiveFlagsView}}
|
||||
<button title='{{i18n admin.flags.agree_title}}' class='btn' {{action "showAgreeFlagModal" flaggedPost}}><i class="fa fa-thumbs-o-up"></i>{{i18n admin.flags.agree}}…</button>
|
||||
{{#if flaggedPost.postHidden}}
|
||||
<button title='{{i18n admin.flags.disagree_flag_unhide_post_title}}' class='btn' {{action "disagreeFlags" flaggedPost}}><i class="fa fa-thumbs-o-down"></i>{{i18n admin.flags.disagree_flag_unhide_post}}</button>
|
||||
{{else}}
|
||||
<button title='{{i18n admin.flags.disagree_flag_title}}' class='btn' {{action "disagreeFlags" flaggedPost}}><i class="fa fa-thumbs-o-down"></i>{{i18n admin.flags.disagree_flag}}</button>
|
||||
{{/if}}
|
||||
<button title='{{i18n admin.flags.defer_flag_title}}' class='btn' {{action "deferFlags" flaggedPost}}><i class="fa fa-external-link"></i>{{i18n admin.flags.defer_flag}}</button>
|
||||
<button title='{{i18n admin.flags.delete_title}}' class='btn btn-danger' {{action "showDeleteFlagModal" flaggedPost}}><i class="fa fa-trash-o"></i>{{i18n admin.flags.delete}}…</button>
|
||||
{{/if}}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{{/each}}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{{loading-spinner condition=view.loading}}
|
||||
{{else}}
|
||||
<p>{{i18n admin.flags.no_results}}</p>
|
||||
{{/if}}
|
||||
@ -1,170 +1,12 @@
|
||||
<div class='admin-controls'>
|
||||
<div class='span15'>
|
||||
<ul class="nav nav-pills">
|
||||
<li>{{#link-to 'adminFlags.active'}}{{i18n admin.flags.active}}{{/link-to}}</li>
|
||||
<li>{{#link-to 'adminFlags.old'}}{{i18n admin.flags.old}}{{/link-to}}</li>
|
||||
<li>{{#link-to 'adminFlags.list' 'active'}}{{i18n admin.flags.active}}{{/link-to}}</li>
|
||||
<li>{{#link-to 'adminFlags.list' 'old'}}{{i18n admin.flags.old}}{{/link-to}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="admin-container">
|
||||
{{#if loading}}
|
||||
{{loading-spinner}}
|
||||
{{else}}
|
||||
{{#if length}}
|
||||
<table class='admin-flags'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='user'></th>
|
||||
<th class='excerpt'></th>
|
||||
<th class='flaggers'>{{i18n admin.flags.flagged_by}}</th>
|
||||
<th class='flaggers'>{{#if adminOldFlagsView}}{{i18n admin.flags.resolved_by}}{{/if}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each flaggedPost in content}}
|
||||
<tr {{bind-attr class="flaggedPost.extraClasses"}}>
|
||||
|
||||
<td class='user'>
|
||||
{{#if flaggedPost.postAuthorFlagged}}
|
||||
{{#if flaggedPost.user}}
|
||||
{{#link-to 'adminUser' flaggedPost.user}}{{avatar flaggedPost.user imageSize="small"}}{{/link-to}}
|
||||
{{#if flaggedPost.wasEdited}}<i class="fa fa-pencil" title="{{i18n admin.flags.was_edited}}"></i>{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{#if adminActiveFlagsView}}
|
||||
{{#if flaggedPost.previous_flags_count}}
|
||||
<span title="{{i18n admin.flags.previous_flags_count count=flaggedPost.previous_flags_count}}" class="badge-notification flagged-posts">{{flaggedPost.previous_flags_count}}</span>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</td>
|
||||
|
||||
<td class='excerpt'>
|
||||
<h3>
|
||||
{{#if flaggedPost.topic.isPrivateMessage}}
|
||||
<span class="private-message-glyph">{{fa-icon envelope}}</span>
|
||||
{{/if}}
|
||||
{{topic-status topic=flaggedPost.topic}}
|
||||
<a href='{{unbound flaggedPost.url}}'>{{flaggedPost.topic.title}}</a>
|
||||
</h3>
|
||||
{{#if flaggedPost.postAuthorFlagged}}
|
||||
{{{flaggedPost.excerpt}}}
|
||||
{{/if}}
|
||||
</td>
|
||||
|
||||
<td class='flaggers'>
|
||||
<table>
|
||||
<tbody>
|
||||
{{#each flaggedPost.flaggers}}
|
||||
<tr>
|
||||
<td class='avatar'>
|
||||
{{#link-to 'adminUser' user}}
|
||||
{{avatar user imageSize="small"}}
|
||||
{{/link-to}}
|
||||
</td>
|
||||
<td>
|
||||
{{#link-to 'adminUser' user}}
|
||||
{{user.username}}
|
||||
{{/link-to}}
|
||||
{{format-age flaggedAt}}
|
||||
<br />
|
||||
{{flagType}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
|
||||
<td class='flaggers result'>
|
||||
{{#if adminOldFlagsView}}
|
||||
<table>
|
||||
<tbody>
|
||||
{{#each flaggedPost.flaggers}}
|
||||
<tr>
|
||||
<td class='avatar'>
|
||||
{{#link-to 'adminUser' disposedBy}}
|
||||
{{avatar disposedBy imageSize="small"}}
|
||||
{{/link-to}}
|
||||
</td>
|
||||
<td>
|
||||
{{format-age disposedAt}}
|
||||
{{{dispositionIcon}}}
|
||||
{{#if tookAction}}
|
||||
<i class='fa fa-gavel' title='{{i18n admin.flags.took_action}}'></i>
|
||||
{{/if}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{/if}}
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
{{#if flaggedPost.topicFlagged}}
|
||||
<tr class='message'>
|
||||
<td></td>
|
||||
<td colspan="3">
|
||||
<div>
|
||||
{{{i18n admin.flags.topic_flagged}}} <a href='{{unbound flaggedPost.url}}' class="btn">{{i18n admin.flags.visit_topic}}</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
|
||||
{{#each flaggedPost.conversations}}
|
||||
<tr class='message'>
|
||||
<td></td>
|
||||
<td colspan="3">
|
||||
<div>
|
||||
{{#if response}}
|
||||
<p>
|
||||
{{#link-to 'adminUser' response.user}}{{avatar response.user imageSize="small"}}{{/link-to}} {{{response.excerpt}}}
|
||||
</p>
|
||||
{{#if reply}}
|
||||
<p>
|
||||
{{#link-to 'adminUser' reply.user}}{{avatar reply.user imageSize="small"}}{{/link-to}} {{{reply.excerpt}}}
|
||||
{{#if hasMore}}
|
||||
<a href="{{unbound permalink}}">{{i18n admin.flags.more}}</a>
|
||||
{{/if}}
|
||||
</p>
|
||||
{{/if}}
|
||||
<a href="{{unbound permalink}}">
|
||||
<button class='btn btn-reply'><i class="fa fa-reply"></i> {{i18n admin.flags.reply_message}}</button>
|
||||
</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
|
||||
<tr>
|
||||
<td colspan="4" class="action">
|
||||
{{#if adminActiveFlagsView}}
|
||||
<button title='{{i18n admin.flags.agree_title}}' class='btn' {{action "showAgreeFlagModal" flaggedPost}}><i class="fa fa-thumbs-o-up"></i>{{i18n admin.flags.agree}}…</button>
|
||||
{{#if flaggedPost.postHidden}}
|
||||
<button title='{{i18n admin.flags.disagree_flag_unhide_post_title}}' class='btn' {{action "disagreeFlags" flaggedPost}}><i class="fa fa-thumbs-o-down"></i>{{i18n admin.flags.disagree_flag_unhide_post}}</button>
|
||||
{{else}}
|
||||
<button title='{{i18n admin.flags.disagree_flag_title}}' class='btn' {{action "disagreeFlags" flaggedPost}}><i class="fa fa-thumbs-o-down"></i>{{i18n admin.flags.disagree_flag}}</button>
|
||||
{{/if}}
|
||||
<button title='{{i18n admin.flags.defer_flag_title}}' class='btn' {{action "deferFlags" flaggedPost}}><i class="fa fa-external-link"></i>{{i18n admin.flags.defer_flag}}</button>
|
||||
<button title='{{i18n admin.flags.delete_title}}' class='btn btn-danger' {{action "showDeleteFlagModal" flaggedPost}}><i class="fa fa-trash-o"></i>{{i18n admin.flags.delete}}…</button>
|
||||
{{/if}}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{{/each}}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
{{#if view.loading}}
|
||||
{{loading-spinner}}
|
||||
{{/if}}
|
||||
|
||||
{{else}}
|
||||
<p>{{i18n admin.flags.no_results}}</p>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{outlet}}
|
||||
</div>
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
<p>{{i18n admin.logs.screened_emails.description}}</p>
|
||||
|
||||
{{#if loading}}
|
||||
{{loading-spinner}}
|
||||
{{else}}
|
||||
{{#loading-spinner condition=loading}}
|
||||
{{#if model.length}}
|
||||
|
||||
<div class='table screened-emails'>
|
||||
@ -23,4 +21,4 @@
|
||||
{{else}}
|
||||
{{i18n search.no_results}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/loading-spinner}}
|
||||
|
||||
@ -3,9 +3,7 @@
|
||||
{{screened-ip-address-form action="recordAdded"}}
|
||||
<br/>
|
||||
|
||||
{{#if loading}}
|
||||
{{loading-spinner}}
|
||||
{{else}}
|
||||
{{#loading-spinner condition=loading}}
|
||||
{{#if model.length}}
|
||||
|
||||
<div class='table admin-logs-table screened-ip-addresses'>
|
||||
@ -25,4 +23,4 @@
|
||||
{{else}}
|
||||
{{i18n search.no_results}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/loading-spinner}}
|
||||
|
||||
@ -1,10 +1,7 @@
|
||||
<p>{{i18n admin.logs.screened_urls.description}}</p>
|
||||
|
||||
{{#if loading}}
|
||||
{{loading-spinner}}
|
||||
{{else}}
|
||||
{{#loading-spinner condition=loading}}
|
||||
{{#if model.length}}
|
||||
|
||||
<div class='table screened-urls'>
|
||||
<div class="heading-container">
|
||||
<div class="col heading first domain">{{i18n admin.logs.screened_urls.domain}}</div>
|
||||
@ -17,8 +14,7 @@
|
||||
|
||||
{{view 'screened-urls-list' content=controller}}
|
||||
</div>
|
||||
|
||||
{{else}}
|
||||
{{i18n search.no_results}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/loading-spinner}}
|
||||
|
||||
@ -43,14 +43,11 @@
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
|
||||
{{#if loading}}
|
||||
<br/>
|
||||
{{loading-spinner}}
|
||||
{{else}}
|
||||
{{#loading-spinner condition=loading}}
|
||||
{{#if model.length}}
|
||||
{{view "staff-action-logs-list" content=controller}}
|
||||
{{else}}
|
||||
{{i18n search.no_results}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/loading-spinner}}
|
||||
</div>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<div>
|
||||
{{i18n admin.dashboard.reports.start_date}} {{input type="date" value=startDate}}
|
||||
{{i18n admin.dashboard.reports.end_date}} {{input type="date" value=endDate}}
|
||||
<button {{action refreshReport}} class='btn btn-primary'>{{i18n admin.dashboard.reports.refresh_report}}</button>
|
||||
<button {{action "refreshReport"}} class='btn btn-primary'>{{i18n admin.dashboard.reports.refresh_report}}</button>
|
||||
</div>
|
||||
|
||||
<div class='view-options'>
|
||||
@ -20,9 +20,7 @@
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{#if refreshing}}
|
||||
{{loading-spinner}}
|
||||
{{else}}
|
||||
{{#loading-spinner condition=refreshing}}
|
||||
<table class='table report'>
|
||||
<tr>
|
||||
<th>{{xaxis}}</th>
|
||||
@ -45,4 +43,4 @@
|
||||
</tr>
|
||||
{{/each}}
|
||||
</table>
|
||||
{{/if}}
|
||||
{{/loading-spinner}}
|
||||
|
||||
@ -14,15 +14,14 @@
|
||||
<div class="site-settings-nav pull-left">
|
||||
<ul class="nav nav-stacked">
|
||||
{{#each category in controller}}
|
||||
<li {{bind-attr class="category.nameKey"}}>
|
||||
{{#link-to 'adminSiteSettingsCategory' category.nameKey tagName='li' class=category.nameKey}}
|
||||
{{#link-to 'adminSiteSettingsCategory' category.nameKey class=category.nameKey}}
|
||||
{{category.name}}
|
||||
{{#if filtered}}
|
||||
<span class="count">({{category.siteSettings.length}})</span>
|
||||
{{/if}}
|
||||
<span class='fa fa-chevron-right'></span>
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/link-to}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@ -6,9 +6,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if loading}}
|
||||
{{loading-spinner}}
|
||||
{{else}}
|
||||
{{#loading-spinner condition=loading}}
|
||||
<div class='admin-container user-badges'>
|
||||
<h2>{{i18n admin.badges.grant_badge}}</h2>
|
||||
{{#if noBadges}}
|
||||
@ -56,4 +54,4 @@
|
||||
{{/each}}
|
||||
</table>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/loading-spinner}}
|
||||
|
||||
@ -37,9 +37,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if loading}}
|
||||
{{loading-spinner}}
|
||||
{{else}}
|
||||
{{#loading-spinner condition=loading}}
|
||||
{{#if model.length}}
|
||||
<table class='table'>
|
||||
<tr>
|
||||
@ -101,5 +99,5 @@
|
||||
{{else}}
|
||||
<p>{{i18n search.no_results}}</p>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/loading-spinner}}
|
||||
</div>
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
Discourse.AdminBackupsLogsView = Discourse.View.extend({
|
||||
import { renderSpinner } from 'discourse/helpers/loading-spinner';
|
||||
|
||||
export default Discourse.View.extend({
|
||||
classNames: ["admin-backups-logs"],
|
||||
|
||||
_initialize: function() { this._reset(); }.on("init"),
|
||||
@ -38,7 +39,7 @@ Discourse.AdminBackupsLogsView = Discourse.View.extend({
|
||||
}
|
||||
// add a loading indicator
|
||||
if (this.get("controller.status.isOperationRunning")) {
|
||||
buffer.push("<i class='fa fa-spinner fa-spin'></i>");
|
||||
buffer.push(renderSpinner('small'));
|
||||
}
|
||||
},
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
Discourse.AdminFlagsView = Discourse.View.extend(Discourse.LoadMore, {
|
||||
export default Discourse.View.extend(Discourse.LoadMore, {
|
||||
loading: false,
|
||||
eyelineSelector: '.admin-flags tbody tr',
|
||||
|
||||
actions: {
|
||||
|
||||
loadMore: function() {
|
||||
var self = this;
|
||||
|
||||
if (this.get("loading") || this.get("model.allLoaded")) { return; }
|
||||
|
||||
this.set("loading", true);
|
||||
@ -15,7 +13,6 @@ Discourse.AdminFlagsView = Discourse.View.extend(Discourse.LoadMore, {
|
||||
self.set("loading", false);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
@ -12,15 +12,20 @@ Discourse.AdminCustomizeView = Discourse.View.extend({
|
||||
templateName: 'admin/templates/customize',
|
||||
classNames: ['customize'],
|
||||
selected: 'stylesheet',
|
||||
|
||||
headerActive: Em.computed.equal('selected', 'header'),
|
||||
footerActive: Em.computed.equal('selected', 'footer'),
|
||||
stylesheetActive: Em.computed.equal('selected', 'stylesheet'),
|
||||
mobileHeaderActive: Em.computed.equal('selected', 'mobileHeader'),
|
||||
mobileFooterActive: Em.computed.equal('selected', 'mobileFooter'),
|
||||
mobileStylesheetActive: Em.computed.equal('selected', 'mobileStylesheet'),
|
||||
|
||||
actions: {
|
||||
selectHeader: function() { this.set('selected', 'header'); },
|
||||
selectFooter: function() { this.set('selected', 'footer'); },
|
||||
selectStylesheet: function() { this.set('selected', 'stylesheet'); },
|
||||
selectMobileHeader: function() { this.set('selected', 'mobileHeader'); },
|
||||
selectMobileFooter: function() { this.set('selected', 'mobileFooter'); },
|
||||
selectMobileStylesheet: function() { this.set('selected', 'mobileStylesheet'); }
|
||||
},
|
||||
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
Discourse.AdminIpLocatorView = Discourse.View.extend({
|
||||
templateName: 'admin/templates/ip_locator',
|
||||
classNames: ["iplocator"],
|
||||
actions: {
|
||||
hideBox: function(){
|
||||
this.set("showBox", false);
|
||||
},
|
||||
lookup: function(){
|
||||
if (!this.get("location")){
|
||||
$.get("http://ipinfo.io/" + this.get("ip"), function(response) {
|
||||
this.set("location", response);
|
||||
}.bind(this), "jsonp");
|
||||
}
|
||||
|
||||
if (!this.get("other_accounts")){
|
||||
this.set("other_accounts_loading", true);
|
||||
Discourse.ajax("/admin/users/list/active.json", {
|
||||
data: {"ip": this.get("ip"),
|
||||
"exclude": this.get("controller.id")
|
||||
}
|
||||
}).then(function (users) {
|
||||
this.set("other_accounts", users.map(function(u) { return Discourse.AdminUser.create(u);}));
|
||||
this.set("other_accounts_loading", false);
|
||||
}.bind(this));
|
||||
}
|
||||
this.set("showBox", true);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -1,11 +1,3 @@
|
||||
/**
|
||||
A modal view for agreeing with a flag.
|
||||
|
||||
@class AdminAgreeFlagView
|
||||
@extends Discourse.ModalBodyView
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.AdminAgreeFlagView = Discourse.ModalBodyView.extend({
|
||||
templateName: 'admin/templates/modal/admin_agree_flag',
|
||||
title: I18n.t('admin.flags.agree_flag_modal_title')
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
@module Discourse
|
||||
**/
|
||||
export default Ember.Component.extend({
|
||||
loading: Ember.computed.not('loaded'),
|
||||
|
||||
loaded: function() {
|
||||
var topicList = this.get('topicList');
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
export default Ember.Component.extend({
|
||||
classNameBindings: ['containerClass'],
|
||||
layoutName: 'components/conditional-loading-spinner',
|
||||
|
||||
containerClass: function() {
|
||||
return (this.get('size') === 'small') ? 'inline-spinner' : undefined;
|
||||
}.property('size')
|
||||
});
|
||||
@ -2,14 +2,14 @@ import ObjectController from 'discourse/controllers/object';
|
||||
import TopPeriod from 'discourse/models/top-period';
|
||||
|
||||
export default ObjectController.extend({
|
||||
needs: ['navigation/category'],
|
||||
needs: ['navigation/category', 'discovery/topics'],
|
||||
loading: false,
|
||||
loadingSpinner: false,
|
||||
scheduledSpinner: null,
|
||||
|
||||
category: Em.computed.alias('controllers.navigation/category.category'),
|
||||
noSubcategories: Em.computed.alias('controllers.navigation/category.noSubcategories'),
|
||||
|
||||
loadedAllItems: Em.computed.not("controllers.discovery/topics.canLoadMore"),
|
||||
|
||||
showMoreUrl: function(period) {
|
||||
var url = '', category = this.get('category');
|
||||
if (category) {
|
||||
|
||||
@ -13,7 +13,10 @@ export default DiscoveryController.extend({
|
||||
// Don't refresh if we're still loading
|
||||
if (this.get('controllers.discovery.loading')) { return; }
|
||||
|
||||
this.send('loading');
|
||||
// If we `send('loading')` here, due to returning true it bubbles up to the
|
||||
// router and ember throws an error due to missing `handlerInfos`.
|
||||
// Lesson learned: Don't call `loading` yourself.
|
||||
this.set('controllers.discovery.loading', true);
|
||||
Discourse.CategoryList.list('categories').then(function(list) {
|
||||
self.set('model', list);
|
||||
self.send('loadingComplete');
|
||||
|
||||
@ -42,7 +42,10 @@ var controllerOpts = {
|
||||
// Don't refresh if we're still loading
|
||||
if (this.get('controllers.discovery.loading')) { return; }
|
||||
|
||||
this.send('loading');
|
||||
// If we `send('loading')` here, due to returning true it bubbles up to the
|
||||
// router and ember throws an error due to missing `handlerInfos`.
|
||||
// Lesson learned: Don't call `loading` yourself.
|
||||
this.set('controllers.discovery.loading', true);
|
||||
Discourse.TopicList.find(filter).then(function(list) {
|
||||
self.setProperties({ model: list, selected: [] });
|
||||
|
||||
|
||||
@ -48,7 +48,7 @@ export default ObjectController.extend(Discourse.SelectedPostsCount, {
|
||||
if (arguments.length > 1) {
|
||||
postStream.set('show_deleted', value);
|
||||
}
|
||||
return postStream.get('show_deleted') ? true : null;
|
||||
return postStream.get('show_deleted') ? true : undefined;
|
||||
}.property('postStream.summary'),
|
||||
|
||||
filter: function(key, value) {
|
||||
@ -58,10 +58,18 @@ export default ObjectController.extend(Discourse.SelectedPostsCount, {
|
||||
if (arguments.length > 1) {
|
||||
postStream.set('summary', value === "summary");
|
||||
}
|
||||
return postStream.get('summary') ? "summary" : null;
|
||||
return postStream.get('summary') ? "summary" : undefined;
|
||||
}.property('postStream.summary'),
|
||||
|
||||
username_filters: Discourse.computed.queryAlias('postStream.streamFilters.username_filters'),
|
||||
username_filters: function(key, value) {
|
||||
var postStream = this.get('postStream');
|
||||
if (!postStream) { return; }
|
||||
|
||||
if (arguments.length > 1) {
|
||||
postStream.set('streamFilters.username_filters', value);
|
||||
}
|
||||
return postStream.get('streamFilters.username_filters');
|
||||
}.property('postStream.streamFilters.username_filters'),
|
||||
|
||||
init: function() {
|
||||
this._super();
|
||||
@ -361,6 +369,11 @@ export default ObjectController.extend(Discourse.SelectedPostsCount, {
|
||||
this.get('content').clearPin();
|
||||
},
|
||||
|
||||
togglePinnedForUser: function() {
|
||||
if (this.get('pinned_at'))
|
||||
this.get('pinned') ? this.get('content').clearPin() : this.get('content').rePin();
|
||||
},
|
||||
|
||||
replyAsNewTopic: function(post) {
|
||||
var composerController = this.get('controllers.composer'),
|
||||
quoteController = this.get('controllers.quote-button'),
|
||||
@ -429,6 +442,10 @@ export default ObjectController.extend(Discourse.SelectedPostsCount, {
|
||||
}
|
||||
},
|
||||
|
||||
togglePinnedState: function() {
|
||||
this.send('togglePinnedForUser');
|
||||
},
|
||||
|
||||
showExpandButton: function() {
|
||||
var post = this.get('post');
|
||||
return post.get('post_number') === 1 && post.get('topic.expandable_first_post');
|
||||
@ -478,6 +495,7 @@ export default ObjectController.extend(Discourse.SelectedPostsCount, {
|
||||
}.property('selectedPostsCount'),
|
||||
|
||||
hasError: Ember.computed.or('notFoundHtml', 'message'),
|
||||
noErrorYet: Ember.computed.not('hasError'),
|
||||
|
||||
multiSelectChanged: function() {
|
||||
// Deselect all posts when multi select is turned off
|
||||
|
||||
@ -78,6 +78,7 @@ export default ObjectController.extend({
|
||||
|
||||
Discourse.User.findByUsername(username).then(function (user) {
|
||||
self.setProperties({ user: user, avatar: user, visible: true});
|
||||
self.appEvents.trigger('usercard:shown');
|
||||
}).finally(function(){
|
||||
self.set('userLoading', null);
|
||||
});
|
||||
|
||||
@ -3,6 +3,7 @@ export default Ember.ArrayController.extend({
|
||||
needs: ['user-notifications'],
|
||||
canLoadMore: true,
|
||||
loading: false,
|
||||
|
||||
showDismissButton: function() {
|
||||
return this.get('user').total_unread_notifications > 0;
|
||||
}.property('user'),
|
||||
@ -26,7 +27,7 @@ export default Ember.ArrayController.extend({
|
||||
var notifications = result.get('content');
|
||||
self.pushObjects(notifications);
|
||||
// Stop trying if it's the end
|
||||
if (notifications && notifications.length === 0) {
|
||||
if (notifications && (notifications.length === 0 || notifications.length < 60)) {
|
||||
self.set('canLoadMore', false);
|
||||
}
|
||||
}).catch(function(error) {
|
||||
|
||||
@ -2,6 +2,8 @@ import ObjectController from 'discourse/controllers/object';
|
||||
import CanCheckEmails from 'discourse/mixins/can-check-emails';
|
||||
|
||||
export default ObjectController.extend(CanCheckEmails, {
|
||||
indexStream: true,
|
||||
needs: ['user-notifications', 'user_topics_list'],
|
||||
|
||||
viewingSelf: function() {
|
||||
return this.get('content.username') === Discourse.User.currentProp('username');
|
||||
@ -32,16 +34,44 @@ export default ObjectController.extend(CanCheckEmails, {
|
||||
(this.get('userActionType') === Discourse.UserAction.TYPES.messages_received);
|
||||
}.property('userActionType'),
|
||||
|
||||
/**
|
||||
Can the currently logged in user invite users to the site
|
||||
|
||||
@property canInviteToForum
|
||||
**/
|
||||
canInviteToForum: function() {
|
||||
return Discourse.User.currentProp('can_invite_to_forum');
|
||||
}.property(),
|
||||
|
||||
canDeleteUser: function() {
|
||||
return this.get('can_be_deleted') && this.get('can_delete_all_posts');
|
||||
}.property('can_be_deleted', 'can_delete_all_posts'),
|
||||
|
||||
loadedAllItems: function() {
|
||||
switch (this.get("datasource")) {
|
||||
case "badges": { return true; }
|
||||
case "notifications": { return !this.get("controllers.user-notifications.canLoadMore"); }
|
||||
case "topic_list": { return !this.get("controllers.user_topics_list.canLoadMore"); }
|
||||
case "stream": {
|
||||
if (this.get("userActionType")) {
|
||||
var stat = _.find(this.get("stats"), { action_type: this.get("userActionType") });
|
||||
return stat && stat.count <= this.get("stream.itemsLoaded");
|
||||
} else {
|
||||
return this.get("statsCountNonPM") <= this.get("stream.itemsLoaded");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}.property("datasource",
|
||||
"userActionType", "stats", "stream.itemsLoaded",
|
||||
"controllers.user_topics_list.canLoadMore",
|
||||
"controllers.user-notifications.canLoadMore"),
|
||||
|
||||
privateMessagesActive: Em.computed.equal('pmView', 'index'),
|
||||
privateMessagesMineActive: Em.computed.equal('pmView', 'mine'),
|
||||
privateMessagesUnreadActive: Em.computed.equal('pmView', 'unread')
|
||||
privateMessagesUnreadActive: Em.computed.equal('pmView', 'unread'),
|
||||
|
||||
actions: {
|
||||
adminDelete: function() {
|
||||
Discourse.AdminUser.find(this.get('username').toLowerCase()).then(function(user){
|
||||
user.destroy({deletePosts: true});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -3,12 +3,12 @@
|
||||
**/
|
||||
|
||||
var acceptableCodeClasses =
|
||||
["lang-auto", "1c", "actionscript", "apache", "applescript", "avrasm", "axapta", "bash", "brainfuck",
|
||||
["auto", "1c", "actionscript", "apache", "applescript", "avrasm", "axapta", "bash", "brainfuck",
|
||||
"clojure", "cmake", "coffeescript", "cpp", "cs", "css", "d", "delphi", "diff", "xml", "django", "dos",
|
||||
"erlang-repl", "erlang", "glsl", "go", "handlebars", "haskell", "http", "ini", "java", "javascript",
|
||||
"json", "lisp", "lua", "markdown", "matlab", "mel", "nginx", "objectivec", "parser3", "perl", "php",
|
||||
"profile", "python", "r", "rib", "rsl", "ruby", "rust", "scala", "smalltalk", "sql", "tex", "text",
|
||||
"vala", "vbscript", "vhdl"];
|
||||
"json", "lisp", "lua", "markdown", "matlab", "mel", "nginx", "nohighlight", "objectivec", "parser3",
|
||||
"perl", "php", "profile", "python", "r", "rib", "rsl", "ruby", "rust", "scala", "smalltalk", "sql",
|
||||
"tex", "text", "vala", "vbscript", "vhdl"];
|
||||
|
||||
var textCodeClasses = ["text", "pre"];
|
||||
|
||||
@ -32,9 +32,9 @@ Discourse.Dialect.replaceBlock({
|
||||
}
|
||||
|
||||
if (textCodeClasses.indexOf(matches[1]) !== -1) {
|
||||
return ['p', ['pre', ['code', flattenBlocks(blockContents) ]]];
|
||||
return ['p', ['pre', ['code', {'class': 'lang-nohighlight'}, flattenBlocks(blockContents) ]]];
|
||||
} else {
|
||||
return ['p', ['pre', ['code', {'class': klass}, flattenBlocks(blockContents) ]]];
|
||||
return ['p', ['pre', ['code', {'class': 'lang-' + klass}, flattenBlocks(blockContents) ]]];
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -69,3 +69,7 @@ Discourse.Dialect.replaceBlock({
|
||||
return ['p', ['pre', flattenBlocks(blockContents)]];
|
||||
}
|
||||
});
|
||||
|
||||
// Whitelist the language classes
|
||||
var regexpSource = "^lang-(" + acceptableCodeClasses.join('|') + ")$";
|
||||
Discourse.Markdown.whiteListTag('code', 'class', new RegExp(regexpSource, "i"));
|
||||
|
||||
@ -3,6 +3,24 @@
|
||||
var classify = Ember.String.classify;
|
||||
var get = Ember.get;
|
||||
|
||||
var LOADING_WHITELIST = ['badges', 'userActivity', 'userPrivateMessages', 'admin', 'adminFlags',
|
||||
'user', 'preferences', 'adminEmail'],
|
||||
_dummyRoute,
|
||||
_loadingView;
|
||||
|
||||
function loadingResolver(cb) {
|
||||
return function(parsedName) {
|
||||
var fullNameWithoutType = parsedName.fullNameWithoutType;
|
||||
|
||||
if (fullNameWithoutType.indexOf('Loading') >= 0) {
|
||||
fullNameWithoutType = fullNameWithoutType.replace('Loading', '');
|
||||
if (LOADING_WHITELIST.indexOf(fullNameWithoutType) !== -1) {
|
||||
return cb(fullNameWithoutType);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function parseName(fullName) {
|
||||
/*jshint validthis:true */
|
||||
|
||||
@ -66,7 +84,7 @@ export default Ember.DefaultResolver.extend({
|
||||
},
|
||||
|
||||
resolveView: function(parsedName) {
|
||||
return this.customResolve(parsedName) || this._super(parsedName);
|
||||
return this.findLoadingView(parsedName) || this.customResolve(parsedName) || this._super(parsedName);
|
||||
},
|
||||
|
||||
resolveHelper: function(parsedName) {
|
||||
@ -82,16 +100,9 @@ export default Ember.DefaultResolver.extend({
|
||||
},
|
||||
|
||||
resolveRoute: function(parsedName) {
|
||||
return this.customResolve(parsedName) || this._super(parsedName);
|
||||
return this.findLoadingRoute(parsedName) || this.customResolve(parsedName) || this._super(parsedName);
|
||||
},
|
||||
|
||||
/**
|
||||
Attaches a view and wires up the container properly
|
||||
|
||||
@method resolveTemplate
|
||||
@param {String} parsedName the name of the template we want to resolve
|
||||
@returns {Template} the template (if found)
|
||||
**/
|
||||
resolveTemplate: function(parsedName) {
|
||||
return this.findPluginTemplate(parsedName) ||
|
||||
this.findMobileTemplate(parsedName) ||
|
||||
@ -99,6 +110,19 @@ export default Ember.DefaultResolver.extend({
|
||||
Ember.TEMPLATES.not_found;
|
||||
},
|
||||
|
||||
findLoadingRoute: loadingResolver(function() {
|
||||
_dummyRoute = _dummyRoute || Ember.Route.extend();
|
||||
return _dummyRoute;
|
||||
}),
|
||||
|
||||
findLoadingView: loadingResolver(function() {
|
||||
if (!_loadingView) {
|
||||
_loadingView = require('discourse/views/loading', null, null, true /* force sync */);
|
||||
if (_loadingView && _loadingView['default']) { _loadingView = _loadingView['default']; }
|
||||
}
|
||||
return _loadingView;
|
||||
}),
|
||||
|
||||
findPluginTemplate: function(parsedName) {
|
||||
var pluginParsedName = this.parseName(parsedName.fullName.replace("template:", "template:javascripts/"));
|
||||
return this.findTemplate(pluginParsedName);
|
||||
|
||||
@ -1,139 +0,0 @@
|
||||
var DiscourseGroupedEach = function(context, path, options) {
|
||||
var self = this,
|
||||
normalized = Ember.Handlebars.normalizePath(context, path, options.data);
|
||||
|
||||
this.context = context;
|
||||
this.path = path;
|
||||
this.options = options;
|
||||
this.template = options.fn;
|
||||
this.containingView = options.data.view;
|
||||
this.normalizedRoot = normalized.root;
|
||||
this.normalizedPath = normalized.path;
|
||||
this.content = this.lookupContent();
|
||||
this.destroyed = false;
|
||||
|
||||
this.addContentObservers();
|
||||
this.addArrayObservers();
|
||||
|
||||
this.containingView.on('willClearRender', function() {
|
||||
self.destroy();
|
||||
});
|
||||
};
|
||||
|
||||
DiscourseGroupedEach.prototype = {
|
||||
contentWillChange: function() {
|
||||
this.removeArrayObservers();
|
||||
},
|
||||
|
||||
contentDidChange: function() {
|
||||
this.content = this.lookupContent();
|
||||
this.addArrayObservers();
|
||||
this.rerenderContainingView();
|
||||
},
|
||||
|
||||
contentArrayWillChange: Ember.K,
|
||||
|
||||
contentArrayDidChange: function() {
|
||||
this.rerenderContainingView();
|
||||
},
|
||||
|
||||
lookupContent: function() {
|
||||
return Ember.Handlebars.get(this.normalizedRoot, this.normalizedPath, this.options);
|
||||
},
|
||||
|
||||
addArrayObservers: function() {
|
||||
if (!this.content) { return; }
|
||||
|
||||
this.content.addArrayObserver(this, {
|
||||
willChange: 'contentArrayWillChange',
|
||||
didChange: 'contentArrayDidChange'
|
||||
});
|
||||
},
|
||||
|
||||
removeArrayObservers: function() {
|
||||
if (!this.content) { return; }
|
||||
|
||||
this.content.removeArrayObserver(this, {
|
||||
willChange: 'contentArrayWillChange',
|
||||
didChange: 'contentArrayDidChange'
|
||||
});
|
||||
},
|
||||
|
||||
addContentObservers: function() {
|
||||
Ember.addBeforeObserver(this.normalizedRoot, this.normalizedPath, this, this.contentWillChange);
|
||||
Ember.addObserver(this.normalizedRoot, this.normalizedPath, this, this.contentDidChange);
|
||||
},
|
||||
|
||||
removeContentObservers: function() {
|
||||
Ember.removeBeforeObserver(this.normalizedRoot, this.normalizedPath, this.contentWillChange);
|
||||
Ember.removeObserver(this.normalizedRoot, this.normalizedPath, this.contentDidChange);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
if (!this.content) { return; }
|
||||
|
||||
var content = this.content,
|
||||
contentLength = Em.get(content, 'length'),
|
||||
data = this.options.data,
|
||||
template = this.template,
|
||||
keyword = this.options.hash.keyword;
|
||||
|
||||
data.insideEach = true;
|
||||
for (var i = 0; i < contentLength; i++) {
|
||||
var row = content.objectAt(i);
|
||||
if (keyword) {
|
||||
data.keywords = data.keywords || {};
|
||||
data.keywords[keyword] = row;
|
||||
}
|
||||
template(row, { data: data });
|
||||
}
|
||||
},
|
||||
|
||||
rerenderContainingView: function() {
|
||||
var self = this;
|
||||
Ember.run.scheduleOnce('render', this, function() {
|
||||
// It's possible it's been destroyed after we enqueued a re-render call.
|
||||
if (!self.destroyed) {
|
||||
self.containingView.rerender();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.removeContentObservers();
|
||||
if (this.content) {
|
||||
this.removeArrayObservers();
|
||||
}
|
||||
this.destroyed = true;
|
||||
}
|
||||
};
|
||||
|
||||
function groupedEachHelper(path, options) {
|
||||
if (arguments.length === 4) {
|
||||
Ember.assert("If you pass more than one argument to the groupedEach helper, it must be in the form #groupedEach foo in bar", arguments[1] === "in");
|
||||
|
||||
var keywordName = arguments[0];
|
||||
|
||||
options = arguments[3];
|
||||
path = arguments[2];
|
||||
if (path === '') { path = "this"; }
|
||||
|
||||
options.hash.keyword = keywordName;
|
||||
}
|
||||
|
||||
if (arguments.length === 1) {
|
||||
options = path;
|
||||
path = 'this';
|
||||
}
|
||||
|
||||
options.hash.dataSourceBinding = path;
|
||||
options.data.insideGroup = true;
|
||||
new DiscourseGroupedEach(this, path, options).render();
|
||||
}
|
||||
|
||||
Ember.Handlebars.registerHelper('groupedEach', function() {
|
||||
Em.warn("The `groupedEach` helper is deprecated. Use `grouped-each` instead.");
|
||||
return groupedEachHelper.apply(this, Array.prototype.slice.apply(arguments));
|
||||
});
|
||||
|
||||
Ember.Handlebars.registerHelper('grouped-each', groupedEachHelper);
|
||||
@ -1,7 +1,31 @@
|
||||
var spinnerHTML = "<div class='spinner'><div class='spinner-container container1'><div class='circle1'></div><div class='circle2'></div><div class='circle3'></div><div class='circle4'></div></div><div class='spinner-container container2'><div class='circle1'></div><div class='circle2'></div><div class='circle3'></div><div class='circle4'></div></div><div class='spinner-container container3'><div class='circle1'></div><div class='circle2'></div><div class='circle3'></div><div class='circle4'></div></div></div>";
|
||||
import ConditionalLoadingSpinner from 'discourse/components/conditional-loading-spinner';
|
||||
|
||||
Handlebars.registerHelper('loading-spinner', function() {
|
||||
return new Handlebars.SafeString(spinnerHTML);
|
||||
function renderSpinner(cssClass) {
|
||||
var html = "<div class='spinner";
|
||||
if (cssClass) { html += ' ' + cssClass; }
|
||||
return html + "'></div>";
|
||||
}
|
||||
var spinnerHTML = renderSpinner();
|
||||
|
||||
/**
|
||||
If you use it as a regular helper {{loading-spinner}} you'll just get the
|
||||
HTML for a spinner.
|
||||
|
||||
If you provide an `condition=xyz` parameter, it will be bound to that property
|
||||
and only show when it's truthy.
|
||||
|
||||
If you use the block form `{{#loading-spinner}} ... {{/loading-spinner}`,
|
||||
the contents will shown when the loading condition finishes.
|
||||
**/
|
||||
Handlebars.registerHelper('loading-spinner', function(options) {
|
||||
var hash = options.hash;
|
||||
if (hash && hash.condition) {
|
||||
var types = options.hashTypes;
|
||||
Discourse.Utilities.normalizeHash(hash, types);
|
||||
return Ember.Handlebars.helpers.view.call(this, ConditionalLoadingSpinner, options);
|
||||
} else {
|
||||
return new Handlebars.SafeString(renderSpinner((hash && hash.size) ? hash.size : undefined));
|
||||
}
|
||||
});
|
||||
|
||||
export { spinnerHTML };
|
||||
export { spinnerHTML, renderSpinner };
|
||||
|
||||
@ -3,7 +3,10 @@ export function renderAvatar(user, options) {
|
||||
|
||||
if (user) {
|
||||
var username = Em.get(user, 'username');
|
||||
if (!username) username = Em.get(user, options.usernamePath);
|
||||
if (!username) {
|
||||
if (!options.usernamePath) { return ''; }
|
||||
username = Em.get(user, options.usernamePath);
|
||||
}
|
||||
|
||||
var title;
|
||||
if (!options.ignoreTitle) {
|
||||
|
||||
@ -112,24 +112,6 @@ Discourse.computed = {
|
||||
return computed.property.apply(computed, args);
|
||||
},
|
||||
|
||||
/**
|
||||
Creates a one way alias to a computed property, suitable for query params.
|
||||
|
||||
@method queryAlias
|
||||
@param {String} path to the alias
|
||||
@param {String} defaultValue for the variable (omitted if equal)
|
||||
**/
|
||||
queryAlias: function(path, defaultValue) {
|
||||
return Em.computed(function(key, value) {
|
||||
if (value) {
|
||||
// Annoying but this ensures the parameter is present
|
||||
}
|
||||
var result = this.get(path);
|
||||
if (typeof result !== "undefined" && result.toString() === defaultValue) { return; }
|
||||
return result;
|
||||
}).property(path);
|
||||
},
|
||||
|
||||
/**
|
||||
Creates a property from a SiteSetting. In the future the plan is for them to
|
||||
be able to update when changed.
|
||||
|
||||
@ -95,8 +95,8 @@ updateRelativeAge = function(elems) {
|
||||
};
|
||||
|
||||
autoUpdatingRelativeAge = function(date,options) {
|
||||
|
||||
if (!date) return "";
|
||||
if (+date === +new Date(0)) return "";
|
||||
|
||||
options = options || {};
|
||||
var format = options.format || "tiny";
|
||||
|
||||
@ -52,6 +52,7 @@ Discourse.KeyboardShortcuts = Ember.Object.createWithMixins({
|
||||
'shift+j': 'nextSection',
|
||||
'j': 'selectDown',
|
||||
'shift+k': 'prevSection',
|
||||
'shift+p': 'pinUnpinTopic',
|
||||
'k': 'selectUp',
|
||||
'u': 'goBack',
|
||||
'/': 'showSearch',
|
||||
@ -131,7 +132,11 @@ Discourse.KeyboardShortcuts = Ember.Object.createWithMixins({
|
||||
},
|
||||
|
||||
createTopic: function() {
|
||||
Discourse.__container__.lookup('controller:composer').open({action: Discourse.Composer.CREATE_TOPIC, draftKey: Discourse.Composer.DRAFT});
|
||||
Discourse.__container__.lookup('controller:composer').open({action: Discourse.Composer.CREATE_TOPIC, draftKey: Discourse.Composer.CREATE_TOPIC});
|
||||
},
|
||||
|
||||
pinUnpinTopic: function() {
|
||||
Discourse.__container__.lookup('controller:topic').togglePinnedState();
|
||||
},
|
||||
|
||||
toggleProgress: function() {
|
||||
@ -240,7 +245,7 @@ Discourse.KeyboardShortcuts = Ember.Object.createWithMixins({
|
||||
if ($article.is('.topic-post')) {
|
||||
var tabLoc = $article.find('a.tabLoc');
|
||||
if (tabLoc.length === 0) {
|
||||
tabLoc = $('<a href="#" class="tabLoc"></a>');
|
||||
tabLoc = $('<a href class="tabLoc"></a>');
|
||||
$article.prepend(tabLoc);
|
||||
}
|
||||
tabLoc.focus();
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*global Markdown:true, hljs:true */
|
||||
/*global Markdown, console */
|
||||
|
||||
/**
|
||||
Contains methods to help us with markdown formatting.
|
||||
@ -7,10 +7,44 @@
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
var _validClasses = {},
|
||||
_validIframes = [],
|
||||
_validTags = {},
|
||||
_decoratedCaja = false;
|
||||
|
||||
/**
|
||||
* An object mapping from HTML tag names to an object mapping the valid
|
||||
* attributes on that tag to an array of permitted values.
|
||||
*
|
||||
* The permitted values can be strings or regexes.
|
||||
*
|
||||
* The pseduo-attribute 'data-*' can be used to validate any data-foo
|
||||
* attributes without any specified validations.
|
||||
*
|
||||
* Code can insert into this map by calling Discourse.Markdown.whiteListTag().
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* <pre><code>
|
||||
* {
|
||||
* a: {
|
||||
* href: ['*'],
|
||||
* data-mention-id: [/^\d+$/],
|
||||
* ...
|
||||
* },
|
||||
* code: {
|
||||
* class: ['ada', 'haskell', 'c', 'cpp', ... ]
|
||||
* },
|
||||
* ...
|
||||
* }
|
||||
* </code></pre>
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
var _validTags = {};
|
||||
/**
|
||||
* Classes valid on all elements. Map from class name to 'true'.
|
||||
* @private
|
||||
*/
|
||||
var _validClasses = {};
|
||||
var _validIframes = [];
|
||||
var _decoratedCaja = false;
|
||||
|
||||
function validateAttribute(tagName, attribName, value) {
|
||||
var tag = _validTags[tagName];
|
||||
@ -18,18 +52,17 @@ function validateAttribute(tagName, attribName, value) {
|
||||
// Handle classes
|
||||
if (attribName === "class") {
|
||||
if (_validClasses[value]) { return value; }
|
||||
}
|
||||
|
||||
if (tag) {
|
||||
var classes = tag['class'];
|
||||
if (classes && (classes.indexOf(value) !== -1 || classes.indexOf('*') !== -1)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
} else if (attribName.indexOf('data-') === 0) {
|
||||
// data-* attributes
|
||||
if (tag) {
|
||||
var allowed = tag[attribName] || tag['data-*'];
|
||||
if (allowed && (allowed === value || allowed.indexOf('*') !== -1)) { return value; }
|
||||
if (attribName.indexOf('data-') === 0) {
|
||||
// data-* catch-all validators
|
||||
if (tag && tag['data-*'] && !tag[attribName]) {
|
||||
var permitted = tag['data-*'];
|
||||
if (permitted && (
|
||||
permitted.indexOf(value) !== -1 ||
|
||||
permitted.indexOf('*') !== -1 ||
|
||||
((permitted instanceof RegExp) && permitted.test(value)))
|
||||
) { return value; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,21 +70,45 @@ function validateAttribute(tagName, attribName, value) {
|
||||
var attrs = tag[attribName];
|
||||
if (attrs && (attrs.indexOf(value) !== -1 ||
|
||||
attrs.indexOf('*') !== -1) ||
|
||||
_.any(attrs,function(r){return (r instanceof RegExp) && value.search(r) >= 0;})
|
||||
_.any(attrs, function(r) { return (r instanceof RegExp) && r.test(value); })
|
||||
) { return value; }
|
||||
}
|
||||
|
||||
// return undefined;
|
||||
}
|
||||
|
||||
function anchorRegexp(regex) {
|
||||
if (/^\^.*\$$/.test(regex.source)) {
|
||||
return regex; // already anchored
|
||||
}
|
||||
|
||||
var flags = "";
|
||||
if (regex.global) {
|
||||
if (typeof console !== 'undefined') {
|
||||
console.warn("attribute validation regex should not be global");
|
||||
}
|
||||
}
|
||||
|
||||
if (regex.ignoreCase) { flags += "i"; }
|
||||
if (regex.multiline) { flags += "m"; }
|
||||
if (regex.sticky) { throw "Invalid attribute validation regex - cannot be sticky"; }
|
||||
|
||||
return new RegExp("^" + regex.source + "$", flags);
|
||||
}
|
||||
|
||||
Discourse.Markdown = {
|
||||
|
||||
/**
|
||||
Whitelist class for only a certain tag
|
||||
Add to the attribute whitelist for a certain HTML tag.
|
||||
|
||||
@param {String} tagName to whitelist
|
||||
@param {String} attribName to whitelist
|
||||
@param {String} value to whitelist
|
||||
@param {String} tagName tag to whitelist the attr for
|
||||
@param {String} attribName attr to whitelist for the tag
|
||||
@param {String | RegExp} [value] whitelisted value for the attribute
|
||||
**/
|
||||
whiteListTag: function(tagName, attribName, value) {
|
||||
if (value instanceof RegExp) {
|
||||
value = anchorRegexp(value);
|
||||
}
|
||||
_validTags[tagName] = _validTags[tagName] || {};
|
||||
_validTags[tagName][attribName] = _validTags[tagName][attribName] || [];
|
||||
_validTags[tagName][attribName].push(value || '*');
|
||||
@ -238,26 +295,19 @@ Discourse.Markdown = {
|
||||
RSVP.EventTarget.mixin(Discourse.Markdown);
|
||||
|
||||
Discourse.Markdown.whiteListTag('a', 'class', 'attachment');
|
||||
Discourse.Markdown.whiteListTag('a', 'target', '_blank');
|
||||
Discourse.Markdown.whiteListTag('a', 'class', 'onebox');
|
||||
Discourse.Markdown.whiteListTag('a', 'class', 'mention');
|
||||
|
||||
Discourse.Markdown.whiteListTag('a', 'target', '_blank');
|
||||
Discourse.Markdown.whiteListTag('a', 'rel', 'nofollow');
|
||||
Discourse.Markdown.whiteListTag('a', 'data-bbcode');
|
||||
Discourse.Markdown.whiteListTag('a', 'name');
|
||||
|
||||
Discourse.Markdown.whiteListTag('img', 'src', /^data:image.*/i);
|
||||
Discourse.Markdown.whiteListTag('img', 'src', /^data:image.*$/i);
|
||||
|
||||
Discourse.Markdown.whiteListTag('div', 'class', 'title');
|
||||
Discourse.Markdown.whiteListTag('div', 'class', 'quote-controls');
|
||||
|
||||
// explicitly whitelist classes we need allowed through for
|
||||
// syntax highlighting, grabbed from highlight.js
|
||||
hljs.listLanguages().forEach(function (language) {
|
||||
Discourse.Markdown.whiteListTag('code', 'class', language);
|
||||
});
|
||||
Discourse.Markdown.whiteListTag('code', 'class', 'text');
|
||||
Discourse.Markdown.whiteListTag('code', 'class', 'lang-auto');
|
||||
|
||||
Discourse.Markdown.whiteListTag('span', 'class', 'mention');
|
||||
Discourse.Markdown.whiteListTag('span', 'class', 'spoiler');
|
||||
Discourse.Markdown.whiteListTag('div', 'class', 'spoiler');
|
||||
@ -273,3 +323,4 @@ Discourse.Markdown.whiteListTag('span', 'bbcode-s');
|
||||
Discourse.Markdown.whiteListTag('span', 'class', 'excerpt');
|
||||
|
||||
Discourse.Markdown.whiteListIframe(/^(https?:)?\/\/www\.google\.com\/maps\/embed\?.+/i);
|
||||
Discourse.Markdown.whiteListIframe(/^(https?:)?\/\/www\.openstreetmap\.org\/export\/embed.html\?.+/i);
|
||||
|
||||
@ -65,8 +65,8 @@ Discourse.Post = Discourse.Model.extend({
|
||||
postElementId: Discourse.computed.fmt('post_number', 'post_%@'),
|
||||
|
||||
canViewRawEmail: function() {
|
||||
return Discourse.User.currentProp('staff');
|
||||
}.property(),
|
||||
return this.get("user_id") === Discourse.User.currentProp("id") || Discourse.User.currentProp('staff');
|
||||
}.property("user_id"),
|
||||
|
||||
bookmarkedChanged: function() {
|
||||
Discourse.Post.bookmark(this.get('id'), this.get('bookmarked'))
|
||||
|
||||
@ -31,6 +31,8 @@ function finderFor(filter, params) {
|
||||
}
|
||||
|
||||
Discourse.TopicList = Discourse.Model.extend({
|
||||
canLoadMore: Em.computed.notEmpty("more_topics_url"),
|
||||
|
||||
forEachNew: function(topics, callback) {
|
||||
var topicIds = [];
|
||||
_.each(this.get('topics'),function(topic) {
|
||||
@ -68,7 +70,6 @@ Discourse.TopicList = Discourse.Model.extend({
|
||||
|
||||
var moreUrl = this.get('more_topics_url');
|
||||
if (moreUrl) {
|
||||
|
||||
var self = this;
|
||||
this.set('loadingMore', true);
|
||||
|
||||
@ -84,7 +85,11 @@ Discourse.TopicList = Discourse.Model.extend({
|
||||
topics.pushObject(t);
|
||||
});
|
||||
|
||||
self.setProperties({ loadingMore: false, more_topics_url: result.topic_list.more_topics_url });
|
||||
self.setProperties({
|
||||
loadingMore: false,
|
||||
more_topics_url: result.topic_list.more_topics_url
|
||||
});
|
||||
|
||||
Discourse.Session.currentProp('topicList', self);
|
||||
return self.get('more_topics_url');
|
||||
}
|
||||
|
||||
@ -13,6 +13,13 @@ export default Discourse.Route.extend({
|
||||
}
|
||||
},
|
||||
|
||||
afterModel: function(model) {
|
||||
var self = this;
|
||||
return Discourse.UserBadge.findByBadgeId(model.get('id')).then(function(userBadges) {
|
||||
self.userBadges = userBadges;
|
||||
});
|
||||
},
|
||||
|
||||
titleToken: function() {
|
||||
var model = this.modelFor('badges.show');
|
||||
if (model) {
|
||||
@ -21,10 +28,7 @@ export default Discourse.Route.extend({
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
Discourse.UserBadge.findByBadgeId(model.get('id')).then(function(userBadges) {
|
||||
controller.set('userBadges', userBadges);
|
||||
controller.set('userBadgesLoaded', true);
|
||||
});
|
||||
controller.set('model', model);
|
||||
controller.set('userBadges', this.userBadges);
|
||||
}
|
||||
});
|
||||
|
||||
@ -40,14 +40,12 @@ export default function(filter, extras) {
|
||||
},
|
||||
|
||||
setupController: function(controller, model, trans) {
|
||||
|
||||
if (trans) {
|
||||
controller.setProperties(Em.getProperties(trans, _.keys(queryParams).map(function(v){
|
||||
return 'queryParams.' + v;
|
||||
})));
|
||||
}
|
||||
|
||||
|
||||
var periods = this.controllerFor('discovery').get('periods'),
|
||||
periodId = model.get('for_period') || (filter.indexOf('/') > 0 ? filter.split('/')[1] : '');
|
||||
|
||||
|
||||
@ -24,17 +24,13 @@ Discourse.DiscoveryRoute = Discourse.Route.extend(Discourse.ScrollTop, Discourse
|
||||
|
||||
// If we're already loading don't do anything
|
||||
if (controller.get('loading')) { return; }
|
||||
|
||||
controller.set('loading', true);
|
||||
controller.set('scheduledSpinner', Ember.run.later(controller, function() {
|
||||
this.set('loadingSpinner', true);
|
||||
},500));
|
||||
return true;
|
||||
},
|
||||
|
||||
loadingComplete: function() {
|
||||
var controller = this.controllerFor('discovery');
|
||||
Ember.run.cancel(controller.get('scheduledSpinner'));
|
||||
controller.setProperties({ loading: false, loadingSpinner: false });
|
||||
controller.set('loading', false);
|
||||
if (!Discourse.Session.currentProp('topicListScrollPosition')) {
|
||||
this._scrollTop();
|
||||
}
|
||||
|
||||
1
app/assets/javascripts/discourse/routes/loading.js.es6
Normal file
1
app/assets/javascripts/discourse/routes/loading.js.es6
Normal file
@ -0,0 +1 @@
|
||||
export default Ember.Route.extend();
|
||||
@ -4,7 +4,7 @@ export default Discourse.RestrictedUserRoute.extend({
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render({ into: 'user', outlet: 'userOutlet' });
|
||||
this.render({ into: 'user' });
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
@ -14,7 +14,7 @@ export default Discourse.RestrictedUserRoute.extend({
|
||||
// A bit odd, but if we leave to /preferences we need to re-render that outlet
|
||||
deactivate: function() {
|
||||
this._super();
|
||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||
this.render('preferences', { into: 'user', controller: 'preferences' });
|
||||
},
|
||||
|
||||
actions: {
|
||||
|
||||
@ -4,13 +4,13 @@ export default Discourse.RestrictedUserRoute.extend({
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
return this.render('user/badge-title', { into: 'user', outlet: 'userOutlet' });
|
||||
return this.render('user/badge-title', { into: 'user' });
|
||||
},
|
||||
|
||||
// A bit odd, but if we leave to /preferences we need to re-render that outlet
|
||||
deactivate: function() {
|
||||
this._super();
|
||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||
this.render('preferences', { into: 'user', controller: 'preferences' });
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
|
||||
@ -4,13 +4,13 @@ export default Discourse.RestrictedUserRoute.extend({
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
return this.render({ into: 'user', outlet: 'userOutlet' });
|
||||
return this.render({ into: 'user' });
|
||||
},
|
||||
|
||||
// A bit odd, but if we leave to /preferences we need to re-render that outlet
|
||||
deactivate: function() {
|
||||
this._super();
|
||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||
this.render('preferences', { into: 'user', controller: 'preferences' });
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
|
||||
@ -4,7 +4,7 @@ export default Discourse.RestrictedUserRoute.extend({
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render({ into: 'user', outlet: 'userOutlet' });
|
||||
this.render({ into: 'user' });
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
@ -14,7 +14,7 @@ export default Discourse.RestrictedUserRoute.extend({
|
||||
// A bit odd, but if we leave to /preferences we need to re-render that outlet
|
||||
deactivate: function() {
|
||||
this._super();
|
||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||
this.render('preferences', { into: 'user', controller: 'preferences' });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
export default Discourse.RestrictedUserRoute.extend({
|
||||
renderTemplate: function() {
|
||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||
this.render('preferences', { into: 'user', controller: 'preferences' });
|
||||
}
|
||||
});
|
||||
|
||||
@ -4,13 +4,13 @@ export default Discourse.RestrictedUserRoute.extend({
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
return this.render({ into: 'user', outlet: 'userOutlet' });
|
||||
return this.render({ into: 'user' });
|
||||
},
|
||||
|
||||
// A bit odd, but if we leave to /preferences we need to re-render that outlet
|
||||
deactivate: function() {
|
||||
this._super();
|
||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||
this.render('preferences', { into: 'user', controller: 'preferences' });
|
||||
},
|
||||
|
||||
setupController: function(controller, user) {
|
||||
|
||||
@ -4,7 +4,11 @@ export default Discourse.Route.extend({
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
this.controllerFor('user').set('indexStream', false);
|
||||
this.controllerFor('user').setProperties({
|
||||
indexStream: false,
|
||||
datasource: "badges",
|
||||
});
|
||||
|
||||
if (this.controllerFor('user_activity').get('content')) {
|
||||
this.controllerFor('user_activity').set('userActionType', -1);
|
||||
}
|
||||
@ -12,6 +16,6 @@ export default Discourse.Route.extend({
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render('user/badges', {into: 'user', outlet: 'userOutlet'});
|
||||
this.render('user/badges', {into: 'user'});
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
export default Discourse.Route.extend({
|
||||
|
||||
beforeModel: function() {
|
||||
this.controllerFor('user').set('indexStream', true);
|
||||
return this.replaceWith('userActivity');
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
export default Discourse.Route.extend({
|
||||
renderTemplate: function() {
|
||||
this.render({ into: 'user', outlet: 'userOutlet' });
|
||||
this.render({ into: 'user' });
|
||||
},
|
||||
|
||||
model: function() {
|
||||
|
||||
@ -5,15 +5,20 @@ export default Discourse.Route.extend({
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
this.controllerFor('user').set('indexStream', false);
|
||||
this.controllerFor('user').setProperties({
|
||||
indexStream: false,
|
||||
datasource: "notifications"
|
||||
});
|
||||
|
||||
if (this.controllerFor('user_activity').get('content')) {
|
||||
this.controllerFor('user_activity').set('userActionType', -1);
|
||||
}
|
||||
|
||||
controller.set('model', model);
|
||||
controller.set('user', this.modelFor('user'));
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render('user-notification-history', {into: 'user', outlet: 'userOutlet'});
|
||||
this.render('user-notification-history', {into: 'user'});
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,12 +1,4 @@
|
||||
/**
|
||||
The base route for showing an activity stream.
|
||||
|
||||
@class UserActivityStreamRoute
|
||||
@extends Discourse.Route
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.UserActivityStreamRoute = Discourse.Route.extend({
|
||||
var UserActivityStreamRoute = Discourse.Route.extend({
|
||||
model: function() {
|
||||
return this.modelFor('user').get('stream');
|
||||
},
|
||||
@ -16,14 +8,17 @@ Discourse.UserActivityStreamRoute = Discourse.Route.extend({
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render('user_stream', {into: 'user', outlet: 'userOutlet'});
|
||||
this.render('user_stream');
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
controller.set('model', model);
|
||||
this.controllerFor('user_activity').set('userActionType', this.get('userActionType'));
|
||||
|
||||
this.controllerFor('user').set('indexStream', !this.get('userActionType'));
|
||||
this.controllerFor('user').setProperties({
|
||||
indexStream: !this.get('userActionType'),
|
||||
datasource: "stream"
|
||||
});
|
||||
},
|
||||
|
||||
actions: {
|
||||
@ -48,7 +43,7 @@ Discourse.UserActivityStreamRoute = Discourse.Route.extend({
|
||||
|
||||
// Build all activity stream routes
|
||||
['bookmarks', 'edits', 'likes_given', 'likes_received', 'replies', 'posts', 'index'].forEach(function (userAction) {
|
||||
Discourse["UserActivity" + userAction.classify() + "Route"] = Discourse.UserActivityStreamRoute.extend({
|
||||
Discourse["UserActivity" + userAction.classify() + "Route"] = UserActivityStreamRoute.extend({
|
||||
userActionType: Discourse.UserAction.TYPES[userAction]
|
||||
});
|
||||
});
|
||||
|
||||
@ -14,7 +14,7 @@ function createAdminPostRoute (filter) {
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render("user/posts", { into: "user", outlet: "userOutlet" });
|
||||
this.render("user/posts", { into: "user" });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,10 +1,13 @@
|
||||
Discourse.UserTopicListRoute = Discourse.Route.extend({
|
||||
renderTemplate: function() {
|
||||
this.render('user_topics_list', {into: 'user', outlet: 'userOutlet'});
|
||||
this.render('user_topics_list');
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
this.controllerFor('user').set('indexStream', false);
|
||||
this.controllerFor('user').setProperties({
|
||||
indexStream: false,
|
||||
datasource: "topic_list"
|
||||
});
|
||||
this.controllerFor('user-activity').set('userActionType', this.get('userActionType'));
|
||||
this.controllerFor('user_topics_list').setProperties({
|
||||
model: model,
|
||||
@ -30,7 +33,8 @@ function createPMRoute(viewName, path) {
|
||||
});
|
||||
this.controllerFor('user').setProperties({
|
||||
pmView: viewName,
|
||||
indexStream: false
|
||||
indexStream: false,
|
||||
datasource: "topic_list"
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@ -62,3 +62,5 @@
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
{{custom-html "footer"}}
|
||||
|
||||
@ -19,3 +19,5 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{{custom-html "footer"}}
|
||||
|
||||
@ -35,12 +35,10 @@
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{#if canLoadMore}}
|
||||
{{loading-spinner}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{#unless userBadgesLoaded}}
|
||||
{{loading-spinner}}
|
||||
|
||||
{{loading-spinner condition=canLoadMore}}
|
||||
{{#unless canLoadMore}}
|
||||
{{custom-html "footer"}}
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{{#if loaded}}
|
||||
{{#loading-spinner condition=loading}}
|
||||
{{#if topics}}
|
||||
<table class="topic-list">
|
||||
<thead>
|
||||
@ -17,36 +17,36 @@
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{{#grouped-each topic in topics}}
|
||||
{{#each topics}}
|
||||
<tr {{bind-attr class="archived"}}>
|
||||
<td class='main-link'>
|
||||
{{topic-status topic=topic}}
|
||||
<a class='title' href="{{unbound topic.lastUnreadUrl}}">{{{unbound topic.fancy_title}}}</a>
|
||||
{{topic-post-badges unread=topic.unread
|
||||
newPosts=topic.new_posts
|
||||
unseen=topic.unseen
|
||||
url=topic.lastUnreadUrl}}
|
||||
{{topic-status topic=this}}
|
||||
<a class='title' href="{{unbound lastUnreadUrl}}">{{{unbound fancy_title}}}</a>
|
||||
{{topic-post-badges unread=unread
|
||||
newPosts=new_posts
|
||||
unseen=unseen
|
||||
url=lastUnreadUrl}}
|
||||
</td>
|
||||
|
||||
{{raw "list/category-column" hideCategory=controller.hideCategory category=topic.category}}
|
||||
{{raw "list/category-column" hideCategory=controller.hideCategory category=category}}
|
||||
|
||||
{{posts-count-column topic=topic class="num" action="clickedPosts"}}
|
||||
{{posts-count-column topic=this class="num" action="clickedPosts"}}
|
||||
|
||||
{{#if controller.showParticipants}}
|
||||
<td class='participants'>
|
||||
{{#each topic.participants}}
|
||||
<a href="{{user.path}}" class="{{extras}}">{{avatar this usernamePath="user.username" imageSize="small"}}</a>
|
||||
{{#each participants}}
|
||||
<a href="{{unbound user.path}}" data-user-card="{{unbound user.username}}" class="{{unbound extras}}">{{avatar this usernamePath="user.username" imageSize="small"}}</a>
|
||||
{{/each}}
|
||||
</td>
|
||||
{{/if}}
|
||||
|
||||
<td {{bind-attr class=":num :views topic.viewsHeat"}}>
|
||||
{{number topic.views numberKey="views_long"}}
|
||||
<td {{bind-attr class=":num :views viewsHeat"}}>
|
||||
{{number views numberKey="views_long"}}
|
||||
</td>
|
||||
|
||||
{{raw "list/activity-column" topic=topic class="num" tagName="td"}}
|
||||
{{raw "list/activity-column" topic=this class="num" tagName="td"}}
|
||||
</tr>
|
||||
{{/grouped-each}}
|
||||
{{/each}}
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
@ -55,6 +55,4 @@
|
||||
{{i18n choose_topic.none_found}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{loading-spinner}}
|
||||
{{/if}}
|
||||
{{/loading-spinner}}
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
{{#if condition}}
|
||||
<div {{bind-attr class=":spinner size"}}></div>
|
||||
{{else}}
|
||||
{{yield}}
|
||||
{{/if}}
|
||||
@ -33,20 +33,26 @@
|
||||
<dd>{{location.phone}}</dd>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<div class="spinner"></div>
|
||||
{{loading-spinner size="small"}}
|
||||
{{/if}}
|
||||
|
||||
<dt>{{i18n ip_lookup.other_accounts}}</dt>
|
||||
<dd>
|
||||
{{#if other_accounts_loading}}
|
||||
<div class="spinner"></div>
|
||||
{{else}}
|
||||
{{#each other_accounts}}
|
||||
{{#link-to "adminUser" this}}{{avatar this usernamePath="user.username" imageSize="small"}}{{/link-to}}
|
||||
<dt>{{i18n ip_lookup.other_accounts}} <strong>{{other_accounts.length}}</strong></dt>
|
||||
<dd class="other-accounts">
|
||||
{{#loading-spinner size="small" condition=otherAccountsLoading}}
|
||||
{{#if other_accounts}}
|
||||
<ul>
|
||||
{{#each other_accounts}}
|
||||
<li>
|
||||
{{#link-to "adminUser" this}}{{avatar this usernamePath="user.username" imageSize="small"}} {{username}}{{/link-to}}
|
||||
({{trustLevel.name}}),
|
||||
<strong>{{i18n ip_lookup.read_time}}</strong> {{time_read}},
|
||||
<strong>{{i18n ip_lookup.topics_entered}}</strong> {{topics_entered}}
|
||||
</li>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
{{i18n ip_lookup.no_other_accounts}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/loading-spinner}}
|
||||
<dd>
|
||||
</dl>
|
||||
<button class="btn close" {{action "hide"}}>{{i18n close}}</button>
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<h3><i class='fa fa-envelope'></i> {{i18n private_message_info.title}}</h3>
|
||||
<div class='participants clearfix'>
|
||||
{{#grouped-each details.allowed_groups}}
|
||||
{{#each details.allowed_groups}}
|
||||
<div class='user group'>
|
||||
#{{unbound name}}
|
||||
</div>
|
||||
{{/grouped-each}}
|
||||
{{#grouped-each details.allowed_users}}
|
||||
{{/each}}
|
||||
{{#each details.allowed_users}}
|
||||
<div class='user'>
|
||||
{{#link-to 'user' this}}
|
||||
{{avatar this imageSize="small"}}
|
||||
@ -17,7 +17,7 @@
|
||||
<a class='remove-invited' {{action "removeAllowedUser" this}}><i class="fa fa-times"></i></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/grouped-each}}
|
||||
{{/each}}
|
||||
</div>
|
||||
{{#if details.can_invite_to}}
|
||||
<div class='controls'>
|
||||
|
||||
@ -46,7 +46,9 @@
|
||||
{{/if}}
|
||||
{{#if showPosterAvatar}}
|
||||
<li {{bind-attr class=":avatars mapCollapsed::hidden"}}>
|
||||
{{#grouped-each participant in details.fewParticipants}}{{topic-participant participant=participant}}{{/grouped-each}}
|
||||
{{#each details.fewParticipants}}
|
||||
{{topic-participant participant=this}}
|
||||
{{/each}}
|
||||
</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
@ -54,14 +56,16 @@
|
||||
|
||||
{{#unless mapCollapsed}}
|
||||
<section class='avatars clearfix'>
|
||||
{{#grouped-each participant in details.participants}}{{topic-participant participant=participant}}{{/grouped-each}}
|
||||
{{#each details.participants}}
|
||||
{{topic-participant participant=this}}
|
||||
{{/each}}
|
||||
</section>
|
||||
|
||||
{{#if infoLinks}}
|
||||
<section class='links'>
|
||||
|
||||
<table class='topic-links'>
|
||||
{{#grouped-each infoLinks}}
|
||||
{{#each infoLinks}}
|
||||
<tr>
|
||||
<td>
|
||||
<span class='badge badge-notification clicks' title='{{i18n topic_map.clicks count=clicks}}'>{{clicks}}</span>
|
||||
@ -73,7 +77,7 @@
|
||||
{{link-domain this}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/grouped-each}}
|
||||
{{/each}}
|
||||
</table>
|
||||
|
||||
{{#if showAllLinksControls}}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
{{loading-spinner}}
|
||||
<div class='composer-loading'>
|
||||
{{loading-spinner}}
|
||||
</div>
|
||||
|
||||
<div class='contents'>
|
||||
|
||||
@ -77,7 +79,7 @@
|
||||
<div class="composer-bottom-right">
|
||||
<a href="#" {{action "togglePreview"}} class='toggle-preview'>{{{model.toggleText}}}</a>
|
||||
<div id="file-uploading" {{bind-attr class="view.isUploading::hidden"}}>
|
||||
<i class='fa fa-spinner fa-spin'></i> {{i18n upload_selector.uploading}} {{view.uploadProgress}}% <a id="cancel-file-upload">{{i18n cancel}}</a>
|
||||
{{loading-spinner size="small"}} {{i18n upload_selector.uploading}} {{view.uploadProgress}}% <a id="cancel-file-upload">{{i18n cancel}}</a>
|
||||
</div>
|
||||
{{#if site.mobileView}}
|
||||
<a {{bind-attr class=":mobile-file-upload view.isUploading:hidden"}}>{{i18n upload}}</a>
|
||||
|
||||
@ -10,12 +10,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div {{bind-attr class="loadingSpinner::hidden"}}>
|
||||
{{loading-spinner}}
|
||||
</div>
|
||||
{{loading-spinner condition=loading}}
|
||||
|
||||
|
||||
<div {{bind-attr class=":container :list-container loadingSpinner:hidden"}}>
|
||||
<div {{bind-attr class=":container :list-container loading:hidden"}}>
|
||||
<div class="row">
|
||||
<div class="full-width">
|
||||
<div id='header-list-area'>
|
||||
@ -23,7 +20,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="full-width">
|
||||
<div id='list-area'>
|
||||
@ -32,3 +28,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{#if loadedAllItems}}
|
||||
{{custom-html "footer"}}
|
||||
{{/if}}
|
||||
|
||||
@ -71,9 +71,7 @@
|
||||
</div>
|
||||
|
||||
<footer class='topic-list-bottom'>
|
||||
{{#if loadingMore}}
|
||||
{{loading-spinner}}
|
||||
{{/if}}
|
||||
{{loading-spinner condition=loadingMore}}
|
||||
{{#if allLoaded}}
|
||||
{{#if showDismissRead}}
|
||||
<button title="{{i18n topics.bulk.dismiss_topics_tooltip}}" id='dismiss-topics' class='btn dismiss-read' {{action "dismissRead" "topics"}}>{{i18n topics.bulk.dismiss_topics}}</button>
|
||||
|
||||
@ -16,9 +16,7 @@
|
||||
{{#each buttonData in enabledButtons}}
|
||||
<button class="btn {{unbound buttonData.classes}}" {{action buttonData.action}}>{{boundI18n buttonData.key}}</button>
|
||||
{{/each}}
|
||||
{{#if loading}}
|
||||
<i class="fa fa-spin fa-spinner"></i>
|
||||
{{/if}}
|
||||
{{loading-spinner condition=loading}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -4,23 +4,25 @@
|
||||
<li {{bind-attr class="showingIndex:active"}}>
|
||||
{{#link-to 'group.index' model}}{{i18n groups.posts}}
|
||||
<span class='count'>({{counts.posts}})</span>
|
||||
<span class='fa fa-chevron-right'></span>{{/link-to}}
|
||||
{{/link-to}}
|
||||
</li>
|
||||
<li {{bind-attr class="showingMembers:active"}}>
|
||||
{{#link-to 'group.members' model}}{{i18n groups.members}}
|
||||
<span class='count'>({{counts.members}})</span>
|
||||
<span class='fa fa-chevron-right'></span>{{/link-to}}
|
||||
{{/link-to}}
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class='user-main'>
|
||||
<section class='about group'>
|
||||
<div class='details'>
|
||||
<h1>{{name}}</h1>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{{outlet}}
|
||||
<section class='user-right groups'>
|
||||
<section class='about group'>
|
||||
<div class='details'>
|
||||
<h1>{{name}}</h1>
|
||||
</div>
|
||||
</section>
|
||||
{{outlet}}
|
||||
</section>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
<span class="title">
|
||||
<a href="{{unbound url}}">{{unbound title}}</a>
|
||||
</span>
|
||||
<span class="category">{{category-link category}}</span>
|
||||
{{#if byName}}
|
||||
<span class="name">
|
||||
{{unbound byName}}
|
||||
|
||||
@ -1,16 +1,17 @@
|
||||
{{#if loaded}}
|
||||
{{#loading-spinner condition=loading}}
|
||||
{{#if topics}}
|
||||
<table class="topic-list">
|
||||
{{#grouped-each topic in topics}}
|
||||
<tbody>
|
||||
{{#each topics}}
|
||||
<tr {{bind-attr class="archived"}}>
|
||||
<td>
|
||||
<div class='main-link clearfix'>
|
||||
{{topic-status topic=this}}
|
||||
{{topic-link this}}
|
||||
{{topic-post-badges unread=unread
|
||||
newPosts=topic.new_posts
|
||||
unseen=topic.unseen
|
||||
url=topic.lastUnreadUrl}}
|
||||
newPosts=new_posts
|
||||
unseen=unseen
|
||||
url=lastUnreadUrl}}
|
||||
|
||||
{{#if hasExcerpt}}
|
||||
<div class="topic-excerpt">
|
||||
@ -26,8 +27,8 @@
|
||||
</div>
|
||||
<div class="topic-item-stats clearfix">
|
||||
<div class="pull-right">
|
||||
{{posts-count-column topic=topic tagName="div" class="num posts" action="clickedPosts"}}
|
||||
{{raw "list/activity-column" topic=topic tagName="div" class="num activity last"}}
|
||||
{{posts-count-column topic=this tagName="div" class="num posts" action="clickedPosts"}}
|
||||
{{raw "list/activity-column" topic=this tagName="div" class="num activity last"}}
|
||||
</div>
|
||||
{{#unless controller.hideCategory}}
|
||||
<div class='category'>
|
||||
@ -36,8 +37,8 @@
|
||||
{{/unless}}
|
||||
{{#if controller.showParticipants}}
|
||||
<div class='participants'>
|
||||
{{#each topic.participants}}
|
||||
<a href="{{user.path}}" class="{{extras}}">{{avatar this usernamePath="user.username" imageSize="small"}}</a>
|
||||
{{#each participants}}
|
||||
<a href="{{unbound user.path}}" class="{{unbound extras}}">{{avatar this usernamePath="user.username" imageSize="small"}}</a>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
@ -45,13 +46,11 @@
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{/grouped-each}}
|
||||
</table>
|
||||
{{else}}
|
||||
<div class='alert alert-info'>
|
||||
{{i18n choose_topic.none_found}}
|
||||
{{/each}}
|
||||
</table>
|
||||
{{else}}
|
||||
<div class='alert alert-info'>
|
||||
{{i18n choose_topic.none_found}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{loading-spinner}}
|
||||
{{/if}}
|
||||
{{/loading-spinner}}
|
||||
|
||||
@ -24,9 +24,7 @@
|
||||
</div>
|
||||
|
||||
<footer class='topic-list-bottom'>
|
||||
{{#if loadingMore}}
|
||||
{{loading-spinner}}
|
||||
{{/if}}
|
||||
{{loading-spinner condition=loadingMore}}
|
||||
{{#if allLoaded}}
|
||||
{{#if showDismissRead}}
|
||||
<button title="{{i18n topics.bulk.dismiss_topics_tooltip}}" id='dismiss-topics' class='btn dismiss-read' {{action "dismissRead" "topics"}}>{{i18n topics.bulk.dismiss_topics}}</button>
|
||||
|
||||
@ -88,13 +88,11 @@
|
||||
{{#if showCreateForm}}
|
||||
<div class="modal-footer">
|
||||
<button class='btn btn-large btn-primary' {{bind-attr disabled="submitDisabled"}} {{action "createAccount"}}>{{i18n create_account.title}}</button>
|
||||
{{#if formSubmitted}}
|
||||
<i class='fa fa-spinner fa-spin'></i>
|
||||
{{else}}
|
||||
{{#loading-spinner condition=formSubmitted size="small"}}
|
||||
<button class="btn btn-large" id="login-link" {{action "showLogin"}}>
|
||||
{{i18n log_in}}
|
||||
</button>
|
||||
{{/if}}
|
||||
{{/loading-spinner}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
|
||||
@ -30,4 +30,5 @@
|
||||
{{#if canDeleteSpammer}}
|
||||
<button class="btn btn-danger" {{action "deleteSpammer" userDetails}} {{bind-attr disabled="submitDisabled"}} title="{{i18n flagging.delete_spammer}}"><i class="fa fa-exclamation-triangle"></i> {{i18n flagging.delete_spammer}}</button>
|
||||
{{/if}}
|
||||
<span class="hint">{{{i18n flagging.private_reminder}}}</span>
|
||||
</div>
|
||||
|
||||
@ -4,11 +4,9 @@
|
||||
<button title="{{i18n post.revisions.controls.first}}" {{bind-attr class=":btn :standard :no-text displayGoToFirst::invisible" disabled=loading}} {{action "loadFirstVersion"}}><i class="fa fa-fast-backward"></i></button>
|
||||
<button title="{{i18n post.revisions.controls.previous}}" {{bind-attr class=":btn :standard :no-text displayGoToPrevious::invisible" disabled=loading}} {{action "loadPreviousVersion"}}><i class="fa fa-backward"></i></button>
|
||||
<div id="revision-numbers" {{bind-attr class="displayRevisions::invisible"}}>
|
||||
{{#if loading}}
|
||||
<div id='revision-loading'><i class='fa fa-spinner fa-spin'></i>{{i18n loading}}</div>
|
||||
{{else}}
|
||||
{{#loading-spinner condition=loading size="small"}}
|
||||
{{boundI18n revisionsTextKey previousBinding="previousVersion" currentBinding="current_version" totalBinding="version_count"}}
|
||||
{{/if}}
|
||||
{{/loading-spinner}}
|
||||
</div>
|
||||
<button title="{{i18n post.revisions.controls.next}}" {{bind-attr class=":btn :standard :no-text displayGoToNext::invisible" disabled=loading}} {{action "loadNextVersion"}}><i class="fa fa-forward"></i></button>
|
||||
<button title="{{i18n post.revisions.controls.last}}" {{bind-attr class=":btn :standard :no-text displayGoToLast::invisible" disabled=loading}} {{action "loadLastVersion"}}><i class="fa fa-fast-forward"></i></button>
|
||||
|
||||
@ -38,6 +38,7 @@
|
||||
<h4>{{i18n keyboard_shortcuts_help.actions.title}}</h4>
|
||||
<ul>
|
||||
<li>{{{i18n keyboard_shortcuts_help.actions.star}}}</li>
|
||||
<li>{{{i18n keyboard_shortcuts_help.actions.pin_unpin_topic}}}</li>
|
||||
<li>{{{i18n keyboard_shortcuts_help.actions.share_topic}}}</li>
|
||||
<li>{{{i18n keyboard_shortcuts_help.actions.share_post}}}</li>
|
||||
<li>{{{i18n keyboard_shortcuts_help.actions.reply_as_new_topic}}}</li>
|
||||
|
||||
@ -56,7 +56,5 @@
|
||||
{{i18n login.authenticating}}
|
||||
{{/if}}
|
||||
|
||||
{{#if showSpinner}}
|
||||
<i class='fa fa-spinner fa-spin'></i>
|
||||
{{/if}}
|
||||
{{loading-spinner condition=showSpinner size="small"}}
|
||||
</div>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<section class="d-dropdown" id="notifications-dropdown">
|
||||
{{#unless loadingNotifications}}
|
||||
{{#loading-spinner condition=loadingNotifications}}
|
||||
{{#if content}}
|
||||
<ul>
|
||||
{{#each itemController="notification"}}
|
||||
@ -12,7 +12,5 @@
|
||||
{{else}}
|
||||
<div class="none">{{i18n notifications.none}}</div>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<div class='loading'><i class='fa fa-spinner fa-spin'></i></div>
|
||||
{{/unless}}
|
||||
{{/loading-spinner}}
|
||||
</section>
|
||||
|
||||
@ -50,16 +50,16 @@
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if wiki}}
|
||||
<div class="post-info wiki" title="{{i18n post.wiki.about}}" {{action "editPost" this}}><i class="fa fa-pencil-square-o"></i></div>
|
||||
<div class="post-info wiki" title="{{i18n post.wiki.about}}" {{action "editPost" this}}>{{fa-icon "pencil-square-o"}}</div>
|
||||
{{/if}}
|
||||
{{#if via_email}}
|
||||
{{#if canViewRawEmail}}
|
||||
<div class="post-info via-email raw-email" title="{{i18n post.via_email}}" {{action "showRawEmail" this}}><i class="fa fa-envelope-o"></i></div>
|
||||
<div class="post-info via-email raw-email" title="{{i18n post.via_email}}" {{action "showRawEmail" this}}>{{fa-icon "envelope-o"}}</div>
|
||||
{{else}}
|
||||
<div class="post-info via-email" title="{{i18n post.via_email}}"><i class="fa fa-envelope-o"></i></div>
|
||||
<div class="post-info via-email" title="{{i18n post.via_email}}">{{fa-icon "envelope-o"}}</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
<div {{bind-attr class=":read-state read"}} title="{{i18n post.unread}}"><i class='fa fa-circle'></i></div>
|
||||
<div {{bind-attr class=":read-state read"}} title="{{i18n post.unread}}">{{fa-icon "circle"}}</div>
|
||||
</div>
|
||||
|
||||
<div {{bind-attr class=":select-posts controller.multiSelect::hidden"}}>
|
||||
@ -84,7 +84,15 @@
|
||||
{{/if}}
|
||||
{{view 'post-menu' post=this adminMenu=view.adminMenu}}
|
||||
</div>
|
||||
{{view 'replies' content=replies}}
|
||||
|
||||
{{#if replies}}
|
||||
<section class='embedded-posts bottom'>
|
||||
{{#each reply in replies}}
|
||||
{{view 'embedded-post' content=reply}}
|
||||
{{/each}}
|
||||
</section>
|
||||
{{/if}}
|
||||
|
||||
{{discourse-action-history post=this}}
|
||||
{{view 'topic-map-container' post=this topic=controller.model}}
|
||||
</div>
|
||||
|
||||
@ -7,3 +7,5 @@
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{custom-html "footer"}}
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
</div>
|
||||
|
||||
{{#if postStream.loaded}}
|
||||
|
||||
{{#if postStream.firstPostPresent}}
|
||||
<div id='topic-title'>
|
||||
<div class='container'>
|
||||
@ -43,7 +42,6 @@
|
||||
</a>
|
||||
{{/if}}
|
||||
|
||||
|
||||
{{#if details.can_edit}}
|
||||
<a href='#' {{action "editTopic"}} class='edit-topic' title='{{i18n edit}}'>{{fa-icon pencil}}</a>
|
||||
{{/if}}
|
||||
@ -72,9 +70,7 @@
|
||||
|
||||
{{render 'topic-progress'}}
|
||||
|
||||
{{#if postStream.loadingAbove}}
|
||||
{{loading-spinner}}
|
||||
{{/if}}
|
||||
{{loading-spinner condition=postStream.loadingAbove}}
|
||||
|
||||
{{#unless postStream.loadingFilter}}
|
||||
{{cloaked-collection cloakView="post"
|
||||
@ -89,15 +85,11 @@
|
||||
offsetFixedBottom="#reply-control"}}
|
||||
{{/unless}}
|
||||
|
||||
{{#if postStream.loadingBelow}}
|
||||
{{loading-spinner}}
|
||||
{{/if}}
|
||||
{{loading-spinner condition=postStream.loadingBelow}}
|
||||
</div>
|
||||
<div id='topic-bottom'></div>
|
||||
|
||||
{{#if postStream.loadingFilter}}
|
||||
<div class='spinner small'></div>
|
||||
{{else}}
|
||||
{{#loading-spinner condition=postStream.loadingFilter}}
|
||||
{{#if postStream.loadedAllPosts}}
|
||||
|
||||
{{view 'topic-closing' topic=model}}
|
||||
@ -112,40 +104,38 @@
|
||||
<h3>{{{view.browseMoreMessage}}}</h3>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/loading-spinner}}
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{{else}}
|
||||
{{#if hasError}}
|
||||
<div class='container'>
|
||||
{{#if notFoundHtml}}
|
||||
{{{notFoundHtml}}}
|
||||
{{else}}
|
||||
<div class="topic-error">
|
||||
<div>{{message}}</div>
|
||||
{{#if noRetry}}
|
||||
{{#unless currentUser}}
|
||||
<button {{action "showLogin"}} class='btn btn-primary topic-retry'>{{fa-icon user}} {{i18n log_in}}</button>
|
||||
{{/unless}}
|
||||
{{else}}
|
||||
<button class="btn btn-primary topic-retry" {{action "retryLoading"}}><i class="fa fa-refresh"></i> {{i18n errors.buttons.again}}</button>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{#if retrying}}
|
||||
{{loading-spinner}}
|
||||
<div class='container'>
|
||||
{{#loading-spinner condition=noErrorYet}}
|
||||
{{#if notFoundHtml}}
|
||||
{{{notFoundHtml}}}
|
||||
{{else}}
|
||||
<div class="topic-error">
|
||||
<div>{{message}}</div>
|
||||
{{#if noRetry}}
|
||||
{{#unless currentUser}}
|
||||
<button {{action "showLogin"}} class='btn btn-primary topic-retry'>{{fa-icon user}} {{i18n log_in}}</button>
|
||||
{{/unless}}
|
||||
{{else}}
|
||||
<button class="btn btn-primary topic-retry" {{action "retryLoading"}}>{{fa-icon "refresh"}} {{i18n errors.buttons.again}}</button>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{loading-spinner condition=retrying}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{else}}
|
||||
<div class='container'>
|
||||
{{loading-spinner}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/loading-spinner}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if postStream.loadedAllPosts}}
|
||||
{{custom-html "footer"}}
|
||||
{{/if}}
|
||||
|
||||
{{render "share"}}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user