diff --git a/.cloud66/manifest.yml b/.cloud66/manifest.yml index 48edce71c..ba6a15581 100644 --- a/.cloud66/manifest.yml +++ b/.cloud66/manifest.yml @@ -11,8 +11,6 @@ development: region: us-east-1 size: m3.medium root_disk_size: 50 - extra_packages: - - jpegoptim postgresql: configuration: version: 9.6.3 @@ -48,8 +46,6 @@ staging: region: us-east-1 size: m3.medium root_disk_size: 50 - extra_packages: - - jpegoptim postgresql: configuration: version: 9.6.3 @@ -85,8 +81,6 @@ production: region: us-east-1 size: c4.xlarge root_disk_size: 50 - extra_packages: - - jpegoptim postgresql: configuration: version: 9.6.3 diff --git a/.cloud66/scripts/db_seed.sh b/.cloud66/scripts/db_seed.sh index fa75ee304..869d9a2f9 100644 --- a/.cloud66/scripts/db_seed.sh +++ b/.cloud66/scripts/db_seed.sh @@ -1,4 +1,4 @@ #!/bin/bash cd $STACK_PATH -bundle exec rake db:seed cortex:create_categories cortex:onet:fetch_and_provision +bundle exec rake db:seed diff --git a/.codeclimate.yml b/.codeclimate.yml index c36550f2e..6c609bf38 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -41,34 +41,8 @@ exclude_paths: - vendor/ - app/interactors/ - app/api/ -- app/assets/javascripts/legacy/ -- app/assets/javascripts/legacy_application.js -- app/assets/legacy_templates/ -- app/assets/stylesheets/legacy/ -- app/assets/stylesheets/legacy_application.scss -- app/controllers/legacy_controller.rb -- app/views/legacy/ - app/models/abilities/ -- app/models/observers/ -- app/models/media_types/ -- app/models/post_types/ -- app/models/onet/ -- app/models/concerns/searchable* - app/models/application.rb -- app/models/author.rb -- app/models/bulk_job.rb -- app/models/category.rb -- app/models/document.rb - app/models/locale.rb - app/models/localization.rb -- app/models/media.rb -- app/models/onet.rb -- app/models/post.rb -- app/models/snippet.rb -- app/models/webpage.rb -- app/jobs/bulk_create_media_job.rb -- app/jobs/bulk_create_users_job.rb -- app/jobs/cache_bust_webpage_job.rb -- app/jobs/youtube_media_job.rb -- app/jobs/youtube_media_job.rb - lib/tasks/cortex.rake diff --git a/.env.example b/.env.example index 80c02d03b..76e14a973 100644 --- a/.env.example +++ b/.env.example @@ -5,14 +5,12 @@ DEVISE_SECRET= # # Asset Host Configuration # -FOG_HOST=http://localhost:3000 HOST_ALIAS= # S3 S3_ACCESS_KEY_ID= S3_SECRET_ACCESS_KEY= S3_BUCKET_NAME= -S3_PROTOCOL= S3_REGION= # @@ -32,16 +30,6 @@ SMTP_USERNAME= SMTP_PASSWORD= SMTP_STARTTLS=true -# -# ONET version to use for `rake cortex:onet:fetch_and_provision` -# -ONET_VERSION=18.1 - -# -# Maximum media filesize -# -MEDIA_MAX_SIZE_MB=100 - # # CORS Configuration # @@ -56,9 +44,6 @@ CORS_ALLOWED_ORIGINS_REGEX= # External Services # -# APIs -YOUTUBE_API_KEY= - # Vendor/3rd Party Script Configuration GOOGLE_ANALYTICS_ID= QUALTRICS_ID= diff --git a/.gitignore b/.gitignore index c19fd93b4..5b872a734 100644 --- a/.gitignore +++ b/.gitignore @@ -9,12 +9,7 @@ /vendor/bundle /vendor/assets -/public/asset_field_types/ /public/assets/ -/public/media/ -/public/youtubes/ -/public/bulk_jobs/ -/public/content-snippets-edit /public/uploads/ # Ignore the default SQLite database. @@ -53,9 +48,6 @@ pickle-email-*.html .env /.cloud66/stack.json -# Test Artifacts -/media - # these should all be checked in to normalise the environment: # Gemfile.lock, .ruby-version, .ruby-gemset diff --git a/Brewfile b/Brewfile index 0d1195a3e..424822a5f 100644 --- a/Brewfile +++ b/Brewfile @@ -5,5 +5,4 @@ Caskroom/cask/java elasticsearch phantomjs imagemagick -jpegoptim ghostscript diff --git a/Gemfile b/Gemfile index 19c345602..115164d0c 100644 --- a/Gemfile +++ b/Gemfile @@ -28,11 +28,7 @@ gem 'rolify', '~> 5.1' gem 'pundit', '~> 1.1' # Data -gem 'rails-observers', git: 'https://github.com/triloch/rails-observers.git' -gem 'awesome_nested_set', git: 'https://github.com/cortex-cms/awesome_nested_set.git' -gem 'paperclip', '~> 5.1.0' -gem 'paperclip-optimizer', '~> 2.0' -gem 'image_optim_pack', '~> 0.4.0' +gem 'awesome_nested_set', '~> 3.1.3' gem 'acts-as-taggable-on', '~> 4.0' gem 'bcrypt', '~> 3.1.11' gem 'kaminari', '~> 0.17.0' @@ -51,23 +47,20 @@ gem 'deep_cloneable', '~> 2.2.2' gem 'rack-cors', '~> 0.4.1', require: 'rack/cors' # Utility -gem 'excon', '~> 0.55.0' gem 'hashie', '~> 3.5.5' gem 'hashr', '~> 2.0.1' -gem 'mime-types', '~> 3.1.0' -gem 'interactor-rails', '~> 2.0' +gem 'mimemagic', '~> 0.3.2' gem 'virtus', '~> 1.0.5' -gem 'rubyzip', '~> 1.2.1' +gem 'interactor-rails', '~> 2.1' gem 'addressable', '~> 2.5.1' gem 'json' # External Services -gem 'yt', '~> 0.30.1' gem 'aws-sdk', '~> 2.9' # Jobs gem 'sidekiq', '~> 5.0.0' -#gem 'sidekiq-failures', '~> 0.4.5' # Disabled until it supports sidekiq 5.x +gem 'sidekiq-failures', '~> 1.0.0' gem 'sinatra', '~> 2.0.0.rc', require: false # Pipeline @@ -75,8 +68,6 @@ gem 'sprockets-rails', '3.2.0', require: 'sprockets/railtie' gem 'sprockets', '3.7.1' gem 'uglifier', '~> 3.2.0' gem 'non-stupid-digest-assets', '~> 1.0.9' -gem 'angular-rails-templates', '~> 1.0.2' -gem 'ngannotate-rails', '~> 1.2.2' # View gem 'haml', '~> 5.0' @@ -99,7 +90,6 @@ gem 'turbolinks', '~> 5.0.1' gem 'jquery-rails', '~> 4.3.1' gem 'jquery-turbolinks', '~> 2.1' gem 'jquery-ui-rails', '~> 6.0.1' -gem 'ng-rails-csrf', '~> 0.1.0' gem 'bootstrap-tagsinput-rails', '~> 0.4.2' gem 'dialog-polyfill-rails', '~> 0.4.5' @@ -169,7 +159,6 @@ end group :test, :development do gem 'factory_girl_rails', '~> 4.8' gem 'faker', '~> 1.7' - gem 'fog-local', '~> 0.3.1' gem 'phantomjs', '~> 2.1.1' gem 'jasmine-rails', '~> 0.14' end diff --git a/Gemfile.lock b/Gemfile.lock index 402ebf964..4d128d29d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,53 +1,39 @@ -GIT - remote: https://github.com/cortex-cms/awesome_nested_set.git - revision: d3bad27fa959788e403becc411f6db9d1aac1dfb - specs: - awesome_nested_set (3.1.2) - activerecord (>= 4.0.0, < 5.1) - -GIT - remote: https://github.com/triloch/rails-observers.git - revision: ea30390cb07b4a37dd2f9d03966c89c1372f9dbe - specs: - rails-observers (0.1.3.alpha) - activemodel (>= 4.0, < 5.1) - GEM remote: https://rubygems.org/ specs: - actioncable (5.0.2) - actionpack (= 5.0.2) + actioncable (5.0.4) + actionpack (= 5.0.4) nio4r (>= 1.2, < 3.0) websocket-driver (~> 0.6.1) - actionmailer (5.0.2) - actionpack (= 5.0.2) - actionview (= 5.0.2) - activejob (= 5.0.2) + actionmailer (5.0.4) + actionpack (= 5.0.4) + actionview (= 5.0.4) + activejob (= 5.0.4) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.0.2) - actionview (= 5.0.2) - activesupport (= 5.0.2) + actionpack (5.0.4) + actionview (= 5.0.4) + activesupport (= 5.0.4) rack (~> 2.0) rack-test (~> 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.0.2) - activesupport (= 5.0.2) + actionview (5.0.4) + activesupport (= 5.0.4) builder (~> 3.1) erubis (~> 2.7.0) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.0.2) - activesupport (= 5.0.2) + activejob (5.0.4) + activesupport (= 5.0.4) globalid (>= 0.3.6) - activemodel (5.0.2) - activesupport (= 5.0.2) - activerecord (5.0.2) - activemodel (= 5.0.2) - activesupport (= 5.0.2) + activemodel (5.0.4) + activesupport (= 5.0.4) + activerecord (5.0.4) + activemodel (= 5.0.4) + activesupport (= 5.0.4) arel (~> 7.0) - activesupport (5.0.2) + activesupport (5.0.4) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (~> 0.7) minitest (~> 5.1) @@ -56,22 +42,20 @@ GEM activerecord (>= 4.0) addressable (2.5.1) public_suffix (~> 2.0, >= 2.0.2) - angular-rails-templates (1.0.2) - railties (>= 4.2, < 6) - sprockets (>= 3.0, < 5) - tilt ansi (1.5.0) arel (7.1.4) attr_required (1.0.1) - autoprefixer-rails (6.7.7.2) + autoprefixer-rails (7.1.2.1) execjs - aws-sdk (2.9.14) - aws-sdk-resources (= 2.9.14) - aws-sdk-core (2.9.14) + awesome_nested_set (3.1.3) + activerecord (>= 4.0.0, < 5.2) + aws-sdk (2.10.9) + aws-sdk-resources (= 2.10.9) + aws-sdk-core (2.10.9) aws-sigv4 (~> 1.0) jmespath (~> 1.0) - aws-sdk-resources (2.9.14) - aws-sdk-core (= 2.9.14) + aws-sdk-resources (2.10.9) + aws-sdk-core (= 2.10.9) aws-sigv4 (1.0.0) axiom-types (0.1.1) descendants_tracker (~> 0.0.4) @@ -94,14 +78,14 @@ GEM breadcrumbs_on_rails (3.0.1) builder (3.2.3) byebug (9.0.6) - capybara (2.13.0) + capybara (2.14.4) addressable mime-types (>= 1.16) nokogiri (>= 1.3.3) rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (~> 2.0) - cells (4.1.6) + cells (4.1.7) declarative-builder (< 0.2.0) declarative-option (< 0.2.0) tilt (>= 1.4, < 3) @@ -109,16 +93,13 @@ GEM cells-haml (0.0.10) cells (>= 4.0.1, <= 6.0.0) haml (>= 4.1.0.beta.1) - cells-rails (0.0.7) + cells-rails (0.0.8) actionpack (>= 3.0) cells (>= 4.1.6, < 5.0.0) - childprocess (0.6.3) + childprocess (0.7.1) ffi (~> 1.0, >= 1.0.11) choice (0.2.0) - climate_control (0.1.0) cliver (0.3.2) - cocaine (0.5.8) - climate_control (>= 0.0.3, < 1.0) codeclimate-test-reporter (0.6.0) simplecov (>= 0.7.1, < 1.0.0) coderay (1.1.1) @@ -139,8 +120,8 @@ GEM rails (>= 4) react_on_rails (~> 6) shrine (~> 2.6) - database_cleaner (1.5.3) - debug_inspector (0.0.2) + database_cleaner (1.6.1) + debug_inspector (0.0.3) declarative-builder (0.1.0) declarative-option (< 0.2.0) declarative-option (0.1.0) @@ -157,13 +138,13 @@ GEM dialog-polyfill-rails (0.4.5.1) diff-lcs (1.3) docile (1.1.5) - doorkeeper (4.2.5) + doorkeeper (4.2.6) railties (>= 4.2) dotenv (2.2.1) dotenv-rails (2.2.1) dotenv (= 2.2.1) railties (>= 3.2, < 5.2) - down (2.5.1) + down (4.0.1) elasticsearch (5.0.4) elasticsearch-api (= 5.0.4) elasticsearch-transport (= 5.0.4) @@ -181,21 +162,19 @@ GEM elasticsearch-transport (5.0.4) faraday multi_json - email_spec (2.1.0) + email_spec (2.1.1) htmlentities (~> 4.3.3) launchy (~> 2.1) - mail (~> 2.6.3) + mail (~> 2.6) equalizer (0.0.11) erubis (2.7.0) - excon (0.55.0) execjs (2.7.0) - exifr (1.2.5) factory_girl (4.8.0) activesupport (>= 3.0.0) factory_girl_rails (4.8.0) factory_girl (~> 4.8.0) railties (>= 3.0.0) - faker (1.7.3) + faker (1.8.2) i18n (~> 0.5) faraday (0.12.1) multipart-post (>= 1.2, < 3) @@ -210,18 +189,11 @@ GEM flipper (~> 0.10.2) rack (>= 1.4, < 3) rack-protection (>= 1.5.3, < 2.1.0) - fog-core (1.44.1) - builder - excon (~> 0.49) - formatador (~> 0.2) - fog-local (0.3.1) - fog-core (~> 1.27) font-awesome-sass (4.7.0) sass (>= 3.2) foreman (0.84.0) thor (~> 0.19.1) formatador (0.2.5) - fspath (3.1.0) globalid (0.4.0) activesupport (>= 4.2.0) gon (6.1.0) @@ -269,7 +241,7 @@ GEM guard (~> 2.1) guard-compat (~> 1.1) rspec (>= 2.99.0, < 4.0) - haml (5.0.0) + haml (5.0.1) temple (>= 0.8.0) tilt hashie (3.5.5) @@ -278,30 +250,19 @@ GEM hashr (2.0.1) htmlentities (4.3.4) httpclient (2.8.3) - i18n (0.8.1) + i18n (0.8.6) ice_nine (0.11.2) - image_optim (0.24.2) - exifr (~> 1.2, >= 1.2.2) - fspath (~> 3.0) - image_size (~> 1.5) - in_threads (~> 1.3) - progress (~> 3.0, >= 3.0.1) - image_optim_pack (0.4.0) - fspath (>= 2.1, < 4) - image_optim (~> 0.19) - image_processing (0.4.1) - image_size (1.5.0) - in_threads (1.4.0) + image_processing (0.4.4) interactor (3.1.0) - interactor-rails (2.0.2) + interactor-rails (2.1.1) interactor (~> 3.0) - rails (>= 3, < 5.1) + rails (>= 4.2, < 5.2) jasmine (2.6.0) jasmine-core (>= 2.6.0, < 3.0.0) phantomjs rack (>= 1.2.1) rake - jasmine-core (2.6.1) + jasmine-core (2.6.4) jasmine-rails (0.14.1) jasmine-core (>= 1.3, < 3.0) phantomjs (>= 1.9) @@ -318,7 +279,7 @@ GEM jquery-ui-rails (6.0.1) railties (>= 3.2.16) json (2.1.0) - json_spec (1.1.4) + json_spec (1.1.5) multi_json (~> 1.0) rspec (>= 2.0, < 4.0) jsonb_accessor (1.0.0.beta.6) @@ -337,23 +298,23 @@ GEM ruby_dep (~> 1.2) loofah (2.0.3) nokogiri (>= 1.5.9) - lumberjack (1.0.11) - mail (2.6.5) + lumberjack (1.0.12) + mail (2.6.6) mime-types (>= 1.16, < 4) - material_design_lite-sass (1.3.0) - autoprefixer-rails (~> 6.0) - sass (~> 3.3) + material_design_lite-sass (1.3.0.1) + autoprefixer-rails (>= 6.5) + sass (>= 3.3) metaclass (0.0.4) method_source (0.8.2) mime-types (3.1) mime-types-data (~> 3.2015) mime-types-data (3.2016.0521) mimemagic (0.3.2) - mini_magick (4.7.0) - mini_portile2 (2.1.0) + mini_magick (4.8.0) + mini_portile2 (2.2.0) mini_racer (0.1.9) libv8 (~> 5.3) - minitest (5.10.1) + minitest (5.10.2) mocha (1.2.1) metaclass (~> 0.0.1) multi_json (1.12.1) @@ -363,39 +324,25 @@ GEM mustermann-grape (1.0.0) mustermann (~> 1.0.0) nenv (0.3.0) - newrelic_rpm (4.1.0.333) - ng-rails-csrf (0.1.0) - ngannotate-rails (1.2.2) - execjs - rails (>= 3.1) - nio4r (2.0.0) - nokogiri (1.7.1) - mini_portile2 (~> 2.1.0) + newrelic_rpm (4.2.0.334) + nio4r (2.1.0) + nokogiri (1.8.0) + mini_portile2 (~> 2.2.0) non-stupid-digest-assets (1.0.9) sprockets (>= 2.0) notiffany (0.1.1) nenv (~> 0.1) shellany (~> 0.0) orm_adapter (0.5.0) - paperclip (5.1.0) - activemodel (>= 4.2.0) - activesupport (>= 4.2.0) - cocaine (~> 0.5.5) - mime-types - mimemagic (~> 0.3.0) - paperclip-optimizer (2.0.0) - image_optim (~> 0.19) - paperclip (>= 3.4) paranoia (2.3.1) activerecord (>= 4.0, < 5.2) pg (0.20.0) phantomjs (2.1.1.0) - poltergeist (1.14.0) + poltergeist (1.15.0) capybara (~> 2.1) cliver (~> 0.3.1) websocket-driver (>= 0.2.0) pomona (0.7.0) - progress (3.3.1) pry (0.10.4) coderay (~> 1.1.0) method_source (~> 0.8.1) @@ -414,7 +361,7 @@ GEM puma (3.8.2) pundit (1.1.0) activesupport (>= 3.0.0) - rack (2.0.1) + rack (2.0.3) rack-accept (0.4.5) rack (>= 0.4) rack-cors (0.4.1) @@ -424,44 +371,44 @@ GEM httpclient (>= 2.4) multi_json (>= 1.3.6) rack (>= 1.1) - rack-protection (2.0.0.rc2) + rack-protection (2.0.0) rack rack-test (0.6.3) rack (>= 1.0) - rails (5.0.2) - actioncable (= 5.0.2) - actionmailer (= 5.0.2) - actionpack (= 5.0.2) - actionview (= 5.0.2) - activejob (= 5.0.2) - activemodel (= 5.0.2) - activerecord (= 5.0.2) - activesupport (= 5.0.2) + rails (5.0.4) + actioncable (= 5.0.4) + actionmailer (= 5.0.4) + actionpack (= 5.0.4) + actionview (= 5.0.4) + activejob (= 5.0.4) + activemodel (= 5.0.4) + activerecord (= 5.0.4) + activesupport (= 5.0.4) bundler (>= 1.3.0, < 2.0) - railties (= 5.0.2) + railties (= 5.0.4) sprockets-rails (>= 2.0.0) - rails-dom-testing (2.0.2) - activesupport (>= 4.2.0, < 6.0) - nokogiri (~> 1.6) - rails-erd (1.5.0) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-erd (1.5.2) activerecord (>= 3.2) activesupport (>= 3.2) choice (~> 0.2.0) ruby-graphviz (~> 1.2) rails-html-sanitizer (1.0.3) loofah (~> 2.0) - railties (5.0.2) - actionpack (= 5.0.2) - activesupport (= 5.0.2) + railties (5.0.4) + actionpack (= 5.0.4) + activesupport (= 5.0.4) method_source rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) rainbow (2.2.2) rake rake (12.0.0) - rb-fsevent (0.9.8) - rb-inotify (0.9.8) - ffi (>= 0.5.0) + rb-fsevent (0.10.2) + rb-inotify (0.9.10) + ffi (>= 0.5.0, < 2) react_on_rails (6.5.1) addressable connection_pool @@ -473,7 +420,7 @@ GEM actionpack (>= 4.0, < 6) redis-rack (>= 1, < 3) redis-store (>= 1.1.0, < 1.4.0) - redis-activesupport (5.0.2) + redis-activesupport (5.0.3) activesupport (>= 3, < 6) redis-store (~> 1.3.0) redis-namespace (1.5.3) @@ -492,62 +439,63 @@ GEM actionpack (>= 4.2.0, < 5.3) railties (>= 4.2.0, < 5.3) rolify (5.1.0) - rspec (3.5.0) - rspec-core (~> 3.5.0) - rspec-expectations (~> 3.5.0) - rspec-mocks (~> 3.5.0) - rspec-core (3.5.4) - rspec-support (~> 3.5.0) - rspec-expectations (3.5.0) + rspec (3.6.0) + rspec-core (~> 3.6.0) + rspec-expectations (~> 3.6.0) + rspec-mocks (~> 3.6.0) + rspec-core (3.6.0) + rspec-support (~> 3.6.0) + rspec-expectations (3.6.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.5.0) - rspec-mocks (3.5.0) + rspec-support (~> 3.6.0) + rspec-mocks (3.6.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.5.0) - rspec-rails (3.5.2) + rspec-support (~> 3.6.0) + rspec-rails (3.6.0) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 3.5.0) - rspec-expectations (~> 3.5.0) - rspec-mocks (~> 3.5.0) - rspec-support (~> 3.5.0) - rspec-sidekiq (3.0.1) + rspec-core (~> 3.6.0) + rspec-expectations (~> 3.6.0) + rspec-mocks (~> 3.6.0) + rspec-support (~> 3.6.0) + rspec-sidekiq (3.0.3) rspec-core (~> 3.0, >= 3.0.0) sidekiq (>= 2.4.0) - rspec-support (3.5.0) + rspec-support (3.6.0) ruby-graphviz (1.2.3) ruby-prof (0.16.2) ruby_dep (1.5.0) - rubyzip (1.2.1) - sass (3.4.23) + sass (3.4.25) sass-rails (5.0.6) railties (>= 4.0.0, < 6) sass (~> 3.1) sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) - sentry-raven (2.4.0) + sentry-raven (2.5.3) faraday (>= 0.7.6, < 1.0) shellany (0.0.1) shoulda-matchers (3.1.1) activesupport (>= 4.0.0) shrine (2.6.1) down (>= 2.3.6) - sidekiq (5.0.0) + sidekiq (5.0.4) concurrent-ruby (~> 1.0) connection_pool (~> 2.2, >= 2.2.0) rack-protection (>= 1.5.0) redis (~> 3.3, >= 3.3.3) + sidekiq-failures (1.0.0) + sidekiq (>= 4.0.0) simplecov (0.14.1) docile (~> 1.1.0) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) - simplecov-html (0.10.0) - sinatra (2.0.0.rc2) - mustermann (= 1.0.0) + simplecov-html (0.10.1) + sinatra (2.0.0) + mustermann (~> 1.0) rack (~> 2.0) - rack-protection (= 2.0.0.rc2) + rack-protection (= 2.0.0) tilt (~> 2.0) six (0.2.0) slop (3.6.0) @@ -562,11 +510,11 @@ GEM thor (0.19.4) thread_safe (0.3.6) tilt (2.0.7) - timecop (0.8.1) + timecop (0.9.1) transitions (1.2.1) turbolinks (5.0.1) turbolinks-source (~> 5) - turbolinks-source (5.0.0) + turbolinks-source (5.0.3) tzinfo (1.2.3) thread_safe (~> 0.1) uber (0.1.0) @@ -582,12 +530,8 @@ GEM websocket-driver (0.6.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.2) - xpath (2.0.0) + xpath (2.1.0) nokogiri (~> 1.3) - yt (0.30.1) - activesupport - yt-support (>= 0.1) - yt-support (0.1.2) PLATFORMS ruby @@ -595,8 +539,7 @@ PLATFORMS DEPENDENCIES acts-as-taggable-on (~> 4.0) addressable (~> 2.5.1) - angular-rails-templates (~> 1.0.2) - awesome_nested_set! + awesome_nested_set (~> 3.1.3) aws-sdk (~> 2.9) bcrypt (~> 3.1.11) better_errors @@ -624,13 +567,11 @@ DEPENDENCIES elasticsearch-model (~> 5.0) elasticsearch-rails (~> 5.0) email_spec - excon (~> 0.55.0) factory_girl_rails (~> 4.8) faker (~> 1.7) flipper (~> 0.10) flipper-active_record (~> 0.10) flipper-ui (~> 0.10) - fog-local (~> 0.3.1) font-awesome-sass (~> 4.7.0) foreman gon (~> 6.1.0) @@ -644,8 +585,7 @@ DEPENDENCIES hashie (~> 3.5.5) hashie-forbidden_attributes (~> 0.1.1) hashr (~> 2.0.1) - image_optim_pack (~> 0.4.0) - interactor-rails (~> 2.0) + interactor-rails (~> 2.1) jasmine-core (~> 2.5) jasmine-rails (~> 0.14) jquery-rails (~> 4.3.1) @@ -655,16 +595,12 @@ DEPENDENCIES json_spec (~> 1.1) kaminari (~> 0.17.0) material_design_lite-sass (~> 1.3.0) - mime-types (~> 3.1.0) + mimemagic (~> 0.3.2) mini_racer mocha (~> 1.2) newrelic_rpm - ng-rails-csrf (~> 0.1.0) - ngannotate-rails (~> 1.2.2) nokogiri non-stupid-digest-assets (~> 1.0.9) - paperclip (~> 5.1.0) - paperclip-optimizer (~> 2.0) paranoia (~> 2.3) pg (~> 0.20.0) phantomjs (~> 2.1.1) @@ -680,18 +616,17 @@ DEPENDENCIES rack-oauth2 (~> 1.6.1) rails (~> 5.0.2) rails-erd - rails-observers! react_on_rails (< 6.6) redis-namespace redis-rails (~> 5.0) rolify (~> 5.1) rspec-rails (~> 3.5) rspec-sidekiq (~> 3.0) - rubyzip (~> 1.2.1) sass-rails (~> 5.0) sentry-raven shoulda-matchers (~> 3.1) sidekiq (~> 5.0.0) + sidekiq-failures (~> 1.0.0) simplecov (~> 0.14) sinatra (~> 2.0.0.rc) six (~> 0.2.0) @@ -702,7 +637,6 @@ DEPENDENCIES turbolinks (~> 5.0.1) uglifier (~> 3.2.0) virtus (~> 1.0.5) - yt (~> 0.30.1) RUBY VERSION ruby 2.4.1p111 diff --git a/Guardfile b/Guardfile index 4b37cdbf3..40991e35b 100644 --- a/Guardfile +++ b/Guardfile @@ -13,8 +13,7 @@ guard :rspec, cmd: "bundle exec rspec" do watch(%r{^app/interactors/(.+)\.rb$}) { |m| "spec/interactors/#{m[1]}_Spec.rb" } watch(%r{^spec/support/(.+)\.rb$}) { "spec" } watch(%r{^spec/factories/(.+)\.rb$}) { "spec" } - watch('app/controllers/application_controller.rb') { ["spec/controllers", "spec/api"] } - watch('app/controllers/api_controller.rb') { "spec/api" } + watch('app/controllers/application_controller.rb') { ["spec/controllers"] } end guard 'jasmine', :server_mount => '/specs', :server_env => :test, :server => :webrick do diff --git a/README.md b/README.md index ba87c0e9b..9f3c40191 100644 --- a/README.md +++ b/README.md @@ -23,24 +23,10 @@ Cortex follows a decentralized, API-only architecture - it is *not* built like W - [Running Test Suite](#running-test-suite) - [API](#api) - [Documentation](#documentation) - - [Resources](#resources) - - [Tenants](#tenants) - - [Users](#users) - - [Media](#media) - - [Posts](#posts) - - [Categories](#categories) - - [Occupations](#occupations) - - [Localizations](#localizations) - - [Applications](#applications) - - [Bulk Jobs](#bulk_jobs) - - [Documents](#documents) - - [Snippets](#snippets) - - [Webpages](#webpages) - [Consuming Cortex](#consuming-cortex) - [Authorization](#authorization) - [Content](#content) - [Localizations](#localizations) - - [Webpages and Snippets](#webpages-and-snippets) - [Exceptions](#exceptions) - [Applications Using Cortex](#applications-using-cortex) - [Troubleshooting](#troubleshooting) @@ -58,7 +44,6 @@ For a rudimentary setup, these variables should be configured: * Execute `$ bundle exec rails secret` twice to generate both an `APP_SECRET` and `DEVISE_SECRET` * If the superuser isn't used for the app databases, the `DATABASE_USERNAME` and `DATABASE_PASSWORD` should be set accordingly. -* Set `HOST` to the local Web server's root URL to properly configure Fog (local asset storage) ### Dependencies @@ -153,12 +138,10 @@ $ bundle exec rake db:create $ bundle exec rake db:schema:load ``` -* Seed database with a top-level tenant, the superuser, Advice & Resources categories, ONET occupation/industry codes, and Custom Content data, then rebuild the ElasticSearch index: +* Seed database with a top-level tenant, the superuser and Custom Content data, then rebuild the ElasticSearch index: ```sh $ bundle exec rake db:seed -$ bundle exec rake cortex:create_categories -$ bundle exec rake cortex:onet:fetch_and_provision $ bundle exec rake cortex:core:db:reseed $ bundle exec rake cortex:rebuild_indexes ``` @@ -196,7 +179,7 @@ This will configure various things, such as [dotenv](https://github.com/bkeepers Initialize the test database: ```sh -$ RAILS_ENV=test bundle exec rake db:schema:load db:seed cortex:create_categories cortex:onet:fetch_and_provision cortex:core:db:reseed +$ RAILS_ENV=test bundle exec rake db:schema:load db:seed cortex:core:db:reseed $ RAILS_ENV=test bundle exec rake cortex:rebuild_indexes ``` @@ -217,69 +200,6 @@ SwaggerUI is provided at [http://docs.api.cbcortex.com/](http://docs.api.cbcorte Swagger Endpoints are available at [http://api.cbcortex.com/api/v1/swagger_doc.json](http://api.cbcortex.com/api/v1/swagger_doc.json). -### Resources - -Note: most resources are treated as 'paranoid' - that is, data is never truly deleted in the system - only archived. - -#### [Tenants](http://docs.api.cbcortex.com/#!/tenants) - -Tenants act as a nested set and are the foundation of the channel-focused content distribution mechanism of Cortex, and allow data to be segregated throughout the system. Tenancy is currently very limited in scope. For example, users are directly tied to a tenant, and content can only be associated with a tenant via an inflexible `content -> user -> tenant` relationship. This will be expanded soon. - -#### [Users](http://docs.api.cbcortex.com/#!/users) - -Users are for authorization and authentication. They currently lack roles, except for the ability to enable/disable admin access. - -#### [Media](http://docs.api.cbcortex.com/#!/media) - -Media covers any potential file-type to be stored in or linked to by the Cortex. This includes: - -* Images -* Audio -* Video -* Youtube Links -* Documents -* Text - -When Media is consumed anywhere within the system, the two pieces of content become tied, and the Media cannot be deleted without the reference removed in the consuming piece of content. - -#### [Posts](http://docs.api.cbcortex.com/#!/posts) - -Posts serve as a packaged distribution medium consisting of other content. They can be categorized, assigned to an occupation, and contain media of any format. - -The posts endpoint also includes other posts-specific functionality, such as post filters and post tags. - -#### [Categories](http://docs.api.cbcortex.com/#!/categories) - -Categories act as a nested set, living in a tree-like structure with parents and children. Cortex's API provides both this hierarchy and a flat list of categories, with a minimum depth as an optional parameter. These are currently unable to be manipulated via the admin interface, only directly within the database. - -#### [Occupations](http://docs.api.cbcortex.com/#!/occupations) - -Occupations act as a nested set of Industries with specific Occupations (with SOC codes) beneath them. They utilize the ONET database, and are intended to eventually power intelligent content recommendations. See the `cortex:onet` rake task for specifics. - -#### [Localizations](http://docs.api.cbcortex.com/#!/localizations) - -Localizations/locales provide YAML/JSON-formatted translations for consuming applications. - -#### [Applications](http://docs.api.cbcortex.com/#!/applications) - -Applications contain credentials for OAuth applications that consume Cortex. - -#### [Bulk Jobs](http://docs.api.cbcortex.com/#!/bulk_jobs) - -Bulk Jobs is the generic interface for uploads processed in bulk for any compatible resource, i.e. `users`, `posts` and `media`. - -#### [Documents](http://docs.api.cbcortex.com/#!/documents) - -Documents are an incredibly generic piece of content, consisting only of raw text. They are intended to be made more specific by other resources, i.e. `snippets` and `webpages`. - -#### [Snippets](http://docs.api.cbcortex.com/#!/snippets) - -Snippets build ontop of a generic Document, and are intended to be HTML sections on a webpage. - -#### [Webpages](http://docs.api.cbcortex.com/#!/webpages) - -Webpages group together `snippets`, and correspond to a destination URL, and contain various additional metadata to power a dynamic, editable webpage. - ## Consuming Cortex ### Authorization @@ -298,10 +218,6 @@ Content can be consumed from a feed or via the resource's endpoint directly. Use Localizations can be consumed via the client or via [i18n-backend-cortex](https://github.com/cortex-cms/i18n-backend-cortex), which allows easy localization for Rails applications. -### Webpages and Snippets - -Webpages/Snippets can be consumed via the client or via the [content-snippets-view](https://github.com/cortex-cms/content-snippets-view) and [content-snippets](https://github.com/cortex-cms/content-snippets) libraries, which need to be configured and hosted in order to be consumed. - ### Exceptions If a consuming or companion application would like to produce Cortex-equivalent exceptions, use the [cortex-exceptions](https://github.com/cb-talent-development/cortex-exceptions) gem. @@ -328,6 +244,6 @@ Cortex utilizes the Apache 2.0 License. See [LICENSE](LICENSE.md) for details. ## Copyright -Copyright (c) 2016 CareerBuilder, LLC. +Copyright (c) 2017 CareerBuilder, LLC. [cb-ce-github]: https://github.com/cb-talent-development "Content Enablement on GitHub" diff --git a/app/api/v1/api.rb b/app/api/v1/api.rb index 00cbfa3be..83bc043c1 100644 --- a/app/api/v1/api.rb +++ b/app/api/v1/api.rb @@ -6,29 +6,16 @@ class API < Grape::API content_type :json, 'application/json' version 'v1', using: :path - mount ::V1::Resources::Categories - mount ::V1::Resources::Posts - mount ::V1::Resources::Media - mount ::V1::Resources::Tenants - mount ::V1::Resources::Users - mount ::V1::Resources::Occupations mount ::V1::Resources::Localizations mount ::V1::Resources::Locales mount ::V1::Resources::Applications mount ::V1::Resources::Credentials - mount ::V1::Resources::BulkJobs - mount ::V1::Resources::Documents - mount ::V1::Resources::Snippets - mount ::V1::Resources::Webpages mount ::V1::Resources::ContentTypes mount ::V1::Resources::ContentItems add_swagger_documentation(base_path: '/api', hide_format: true, api_version: 'v1', - models: [::V1::Entities::Post, ::V1::Entities::Category, ::V1::Entities::Media, - ::V1::Entities::Tenant, ::V1::Entities::Occupation, ::V1::Entities::User, - ::V1::Entities::Localization, ::V1::Entities::Locale, + models: [::V1::Entities::Localization, ::V1::Entities::Locale, ::V1::Entities::Application, ::V1::Entities::Credential, - ::V1::Entities::BulkJob, ::V1::Entities::Document, ::V1::Entities::Snippet, - ::V1::Entities::Webpage, ::V1::Entities::ContentType, ::V1::Entities::ContentItem]) + ::V1::Entities::ContentType, ::V1::Entities::ContentItem]) end end diff --git a/app/api/v1/entities/author.rb b/app/api/v1/entities/author.rb deleted file mode 100644 index 971dc4d9c..000000000 --- a/app/api/v1/entities/author.rb +++ /dev/null @@ -1,18 +0,0 @@ -module V1 - module Entities - class Author < Grape::Entity - expose :firstname, documentation: { type: "String", desc: "First Name" } - expose :lastname, documentation: { type: "String", desc: "Last Name" } - expose :email, documentation: { type: "String", desc: "Email" } - expose :title, documentation: { type: "String", desc: "Title" } - expose :bio, documentation: { type: "String", desc: "Bio" } - expose :personal, documentation: { type: "String", desc: "Personal Website" } - expose :twitter, documentation: { type: "String", desc: "Twitter Profile" } - expose :facebook, documentation: { type: "String", desc: "Facebook Profile" } - expose :google, documentation: { type: "String", desc: "Google Profile" } - expose :avatars, documentation: { type: "String", desc: "Avatar" } - expose :fullname, documentation: { type: "String", desc: "Full Name" } - expose :id, documentation: { type: "Integer", desc: "Author ID" } - end - end -end diff --git a/app/api/v1/entities/bulk_job.rb b/app/api/v1/entities/bulk_job.rb deleted file mode 100644 index 290095912..000000000 --- a/app/api/v1/entities/bulk_job.rb +++ /dev/null @@ -1,15 +0,0 @@ -module V1 - module Entities - class BulkJob < Grape::Entity - expose :id, documentation: { type: 'UUID', desc: 'Bulk upload job UUID', required: true } - expose :content_type, documentation: { type: 'String', desc: 'Type of content being processed. Types supported: Media (/media/bulk_job), Users (/users/bulk_job)' } - expose :status, documentation: { type: 'String', desc: 'Bulk upload job status' } - expose :log, documentation: { type: 'Text', is_array: true, desc: 'Full log as Array for bulk upload job' } - expose :created_at, documentation: { type: 'dateTime', desc: 'Created date'} - expose :updated_at, documentation: { type: 'dateTime', desc: 'Updated date'} - expose :user, with: '::V1::Entities::User', as: :creator, documentation: { type: 'User', desc: 'Owner' } - expose :metadata, documentation: { type: 'String', desc: 'Bulk metadata (CSV) URL', required: true } - expose :assets, documentation: { type: 'String', desc: 'Assets to be uploaded (ZIP) URL' }, if: lambda { |bulkJob, _| bulkJob.assets_file_name.present? } - end - end -end diff --git a/app/api/v1/entities/category.rb b/app/api/v1/entities/category.rb deleted file mode 100644 index 2b514f102..000000000 --- a/app/api/v1/entities/category.rb +++ /dev/null @@ -1,9 +0,0 @@ -module V1 - module Entities - class Category < Grape::Entity - expose :id, documentation: { type: "Integer", desc: "Category ID" } - expose :name, documentation: { type: "String", desc: "Category Name"} - expose :children, if: lambda { |instance, options| options[:children] }, documentation: { type: "Category", is_array: true, desc: "Child Categories" } - end - end -end diff --git a/app/api/v1/entities/document.rb b/app/api/v1/entities/document.rb deleted file mode 100644 index e40f5830b..000000000 --- a/app/api/v1/entities/document.rb +++ /dev/null @@ -1,11 +0,0 @@ -module V1 - module Entities - class Document < Grape::Entity - expose :id, documentation: { type: 'Integer', desc: 'Document ID', required: true } - expose :name, documentation: { type: 'String', desc: 'Document Name', required: true } - expose :body, documentation: { type: 'String', desc: 'Body Text', required: true } - expose :created_at, documentation: { type: 'dateTime', desc: 'Created Date'} - expose :updated_at, documentation: { type: 'dateTime', desc: 'Updated Date'} - end - end -end diff --git a/app/api/v1/entities/media.rb b/app/api/v1/entities/media.rb deleted file mode 100644 index e0a9fc0fc..000000000 --- a/app/api/v1/entities/media.rb +++ /dev/null @@ -1,45 +0,0 @@ -module V1 - module Entities - class Media < Grape::Entity - expose :id, documentation: { type: "Integer", desc: "Media ID", required: true } - expose :name, documentation: { type: "String", desc: "Media Name", required: true } - expose :alt, documentation: { type: "String", desc: "Alt-text for Media" } - expose :taxon, documentation: { type: "String", desc: "Taxon string" } - expose :dimensions, documentation: { type: "Integer", is_array: true, desc: "Array of [Width, Height]" } - expose :url, documentation: { type: "String", desc: "URL of Media" } - expose :type, documentation: { type: "String", desc: "Media Type" } - expose :created_at, documentation: { type: 'dateTime', desc: "Created Date"} - expose :updated_at, documentation: { type: 'dateTime', desc: "Updated Date"} - expose :attachment_file_name, documentation: { type: "String", desc: "Filename" } - expose :content_type, documentation: { type: "String", desc: "Media type" } - expose :description, documentation: { type: "String", desc: "Description of the media" } - expose :active, documentation: { type: "Boolean", desc: "Media active" } - expose :tag_list, documentation: {type: "String", is_array: true, desc: "Tags"} - - expose :user, with: '::V1::Entities::User', as: :creator, documentation: { type: "User", desc: "Owner" } - - ## Thumbnails - expose :attachment, using: '::V1::Entities::MediaThumbnails', as: :thumbs, if: lambda { |media, _| media.can_thumb? }, documentation: { type: "MediaThumbnails", desc: "Thumbnails of the media"} - - ## Youtube Specific - with_options if: lambda { |media, _| media.content_type == 'youtube' } do - expose :duration, documentation: { type: "Integer", desc: "Video duration in seconds"} - expose :title, documentation: { type: "String", desc: "Video Title"} - expose :authors, documentation: { type: "String", desc: "String representing array of video's Youtube authors"} - expose :video_description, documentation: { type: "String", desc: "Youtube video description"} - expose :video_id, documentation: { type: "String", desc: "Youtube video ID"} - end - - # Full Only - with_options if: { full: true } do - expose :deactive_at, documentation: { type: 'dateTime', desc: "Deactivate Date"} - expose :deleted_at, documentation: { type: 'dateTime', desc: "Deleted Date"} - - ## Aliases - expose :attachment_file_size, documentation: { type: "Integer", desc: "Filesize in bytes" } - expose :attachment_content_type, documentation: { type: "String", desc: "Attachment Mime Type" } - expose :consumed?, as: :consumed, documentation: { type: "Boolean", desc: "Is the media consumed?" } - end - end - end -end diff --git a/app/api/v1/entities/media_thumbnails.rb b/app/api/v1/entities/media_thumbnails.rb deleted file mode 100644 index 247f15527..000000000 --- a/app/api/v1/entities/media_thumbnails.rb +++ /dev/null @@ -1,12 +0,0 @@ -module V1 - module Entities - class MediaThumbnails < Grape::Entity - expose :large, documentation: {desc: "Large thumbnail"} do |attachment| attachment.url(:large) end - expose :medium, documentation: {desc: "Medium thumbnail"} do |attachment| attachment.url(:medium) end - expose :default, documentation: {desc: "Default thumbnail"} do |attachment| attachment.url(:default) end - expose :mini, documentation: {desc: "Mini thumbnail"} do |attachment| attachment.url(:mini) end - expose :micro, documentation: {desc: "Micro thumbnail"} do |attachment| attachment.url(:micro) end - expose :ar_post, documentation: {desc: "Media resized for A&R post page"} do |attachment| attachment.url(:ar_post) end - end - end -end diff --git a/app/api/v1/entities/occupation.rb b/app/api/v1/entities/occupation.rb deleted file mode 100644 index 99bab15da..000000000 --- a/app/api/v1/entities/occupation.rb +++ /dev/null @@ -1,10 +0,0 @@ -module V1 - module Entities - class Occupation < Grape::Entity - expose :id, documentation: { type: "Integer", desc: "Occupation ID" } - expose :soc, documentation: { type: "String", desc: "SOC code" } - expose :title, documentation: { type: "String", desc: "Occupation Title" } - expose :description, documentation: { type: "String", desc: "Occupation Description" } - end - end -end diff --git a/app/api/v1/entities/post.rb b/app/api/v1/entities/post.rb deleted file mode 100644 index 7f55ca809..000000000 --- a/app/api/v1/entities/post.rb +++ /dev/null @@ -1,71 +0,0 @@ -module V1 - module Entities - class Post < Grape::Entity - expose :id, documentation: {type: "Integer", desc: "Post ID", required: true} - expose :title, documentation: {desc: "Post Title", type: "String" , required: true} - expose :type, documentation: {desc: "Post Type", type: "String", enum: ["ArticlePost", "VideoPost", "InfographicPost", "PromoPost"], required: true} - expose :draft, documentation: {desc: "Draft status", type: "Boolean"} - expose :is_wysiwyg, documentation: {desc: "Post needs a WYSIWYG editor", type: "Boolean"} - expose :comment_count, documentation: {desc: "Number of comments", type: "Integer"} - expose :short_description, documentation: {desc: "Short description of the post", type: "String", required: true} - expose :job_phase, documentation: {desc: "Job Phase", type: "String", enum: ["discovery", "find_the_job", "get_the_job", "on_the_job"], required: true} - expose :slug, documentation: {desc: "Slug", type: "String", required: true} - expose :created_at, documentation: { type: 'dateTime', desc: "Created Date"} - expose :updated_at, documentation: { type: 'dateTime', desc: "Last Updated Date"} - expose :published_at, documentation: { type: 'dateTime', desc: "Publish Date"} - expose :expired_at, documentation: { type: 'dateTime', desc: "Expiration Date"} - expose :copyright_owner, documentation: { type: "String", desc: "Copyright Owner"} - expose :notes, documentation: {type: "String", desc: "Notes about this post"} - expose :seo_title, documentation: {type: "String", desc: "SEO-specific title for this post"} - expose :seo_description, documentation: {type: "String", desc: "SEO-specific description for this post"} - expose :seo_keyword_list, documentation: {type: "String", is_array: true, desc: "SEO-specific keywords for this post"} - expose :primary_category_id, documentation: {type: "Integer", desc: "Primary Category ID"} - expose :primary_industry_id, documentation: {type: "Integer", desc: "Primary Industry ID"} - expose :tag_list, documentation: {type: "String", is_array: true, desc: "Tags"} - expose :body, documentation: {desc: "Body of the post", type: "String"} - - expose :categories, using: '::V1::Entities::Category', documentation: {type: 'Category', is_array: true, desc: "Categories"} - expose :featured_media, using: '::V1::Entities::Media', documentation: {type: 'Media', is_array: false, desc: "Featured Media for this post"} - expose :tile_media, using: '::V1::Entities::Media', documentation: {type: 'Media', is_array: false, desc: "Tile Media for this post"} - expose :industries, using: '::V1::Entities::Occupation', documentation: {type: 'Industry', is_array: true, desc: "Industries"} - - # This runtime exposure is necessary to correctly resolve the enum value - expose :display, {documentation: { type: "String", desc: "Post Display Size"}} do |post| - post.display - end - - expose :is_published, documentation: { type: "Boolean", desc: "If this post if active and published"} do |post| - post.published? - end - - expose :custom_author, documentation: {desc: "Author's name", type: "String", required: true} do |post, options| - if post.author - post.author.fullname - elsif options[:type] == true - nil - else - post[:custom_author] - end - end - - with_options if: lambda { |post, _| post.type == 'PromoPost' } do - expose :destination_url, { documentation: { type: "String", desc: "Destination URL for a Promo Post"} } - expose :call_to_action, { documentation: { type: "String", desc: "Call to Action for a Promo Post"} } - end - - with_options if: { full: true } do - represent :media, with: '::V1::Entities::Media', full: true, documentation: {type: "Media", is_array: true, desc: "All Media for this post"} - expose :user, with: '::V1::Entities::User' - expose :author, using: '::V1::Entities::Author' - end - - expose :noindex, documentation: { type: 'Boolean', desc: "SEO No Index Robots Setting" } - expose :nofollow, documentation: { type: 'Boolean', desc: "SEO No Follow Robots Setting" } - expose :noodp, documentation: { type: 'Boolean', desc: "SEO No ODP Setting" } - expose :nosnippet, documentation: { type: 'Boolean', desc: "SEO No Snippet Robots Setting" } - expose :noarchive, documentation: { type: 'Boolean', desc: "SEO No Archive Setting" } - expose :noimageindex, documentation: { type: 'Boolean', desc: "SEO No Image Index Robots Setting" } - expose :is_sticky, documentation: { type: 'Boolean', desc: "Is this Post Sticky?" } - end - end -end diff --git a/app/api/v1/entities/snippet.rb b/app/api/v1/entities/snippet.rb deleted file mode 100644 index 7ca4b07da..000000000 --- a/app/api/v1/entities/snippet.rb +++ /dev/null @@ -1,10 +0,0 @@ -module V1 - module Entities - class Snippet < Grape::Entity - expose :id, documentation: { type: 'Integer', desc: 'Snippet ID', required: true } - expose :created_at, documentation: { type: 'dateTime', desc: 'Created Date'} - expose :updated_at, documentation: { type: 'dateTime', desc: 'Updated Date'} - expose :document, with: '::V1::Entities::Document', documentation: {type: 'Document', desc: 'Associated Document'} - end - end -end diff --git a/app/api/v1/entities/tag.rb b/app/api/v1/entities/tag.rb deleted file mode 100644 index f9fdd59b4..000000000 --- a/app/api/v1/entities/tag.rb +++ /dev/null @@ -1,9 +0,0 @@ -module V1 - module Entities - class Tag < Grape::Entity - expose :id, documentation: { type: "Integer", desc: "Tag ID" } - expose :name, documentation: { type: "String", desc: "Tag Name" } - expose :count, documentation: { type: "Integer", desc: "Tag Count" } - end - end -end diff --git a/app/api/v1/entities/webpage.rb b/app/api/v1/entities/webpage.rb deleted file mode 100644 index 04466ae8f..000000000 --- a/app/api/v1/entities/webpage.rb +++ /dev/null @@ -1,37 +0,0 @@ -module V1 - module Entities - class Webpage < Grape::Entity - expose :id, documentation: { type: 'Integer', desc: 'Webpage ID', required: true } - expose :name, documentation: { type: 'String', desc: 'Webpage Name', required: true } - expose :created_at, documentation: { type: 'dateTime', desc: 'Created Date'} - expose :updated_at, documentation: { type: 'dateTime', desc: 'Updated Date'} - expose :snippets, with: '::V1::Entities::Snippet', documentation: {type: 'Snippet', is_array: true, desc: 'All associated Snippets for this Webpage'} - - expose :seo_title, documentation: { type: 'String', desc: "SEO Meta Tag Title" } - expose :seo_description, documentation: { type: 'String', desc: "SEO Meta Tag Description" } - expose :seo_keyword_list, documentation: {type: "String", is_array: true, desc: "SEO-specific keywords"} - expose :noindex, documentation: { type: 'Boolean', desc: "SEO No Index Robots Setting" } - expose :nofollow, documentation: { type: 'Boolean', desc: "SEO No Follow Robots Setting" } - expose :noodp, documentation: { type: 'Boolean', desc: "SEO No ODP Setting" } - expose :nosnippet, documentation: { type: 'Boolean', desc: "SEO No Snippet Robots Setting" } - expose :noarchive, documentation: { type: 'Boolean', desc: "SEO No Archive Setting" } - expose :noimageindex, documentation: { type: 'Boolean', desc: "SEO No Image Index Robots Setting" } - - expose :dynamic_yield_sku, documentation: { type: 'String', desc: "Dynamic Yield Webpage SKU/ID" } - expose :dynamic_yield_category, documentation: { type: 'String', desc: "Dynamic Yield Webpage Category" } - - expose :tables_widget_json, documentation: {type: 'Hash', is_array: true, desc: 'Tables Widget Data as JSON'} - expose :charts_widget_json, documentation: {type: 'Hash', is_array: true, desc: 'Charts Widget Data as JSON'} - expose :accordion_group_widget_json, documentation: {type: 'Hash', is_array: true, desc: 'Accordion Group Widget Data as JSON'} - - with_options if: { full: true } do - expose :user, with: '::V1::Entities::User', documentation: {type: 'User', desc: 'Owner'} - expose :url, documentation: { type: 'String', desc: 'URL of Webpage' } - - expose :tables_widget_yaml, documentation: {type: 'Hash', is_array: true, desc: 'Tables Widget Data as YAML'} - expose :accordion_group_widget_yaml, documentation: {type: 'Hash', is_array: true, desc: 'Accordion Group Widget Data as YAML'} - expose :charts_widget_yaml, documentation: {type: 'Hash', is_array: true, desc: 'Charts Widget Data as YAML'} - end - end - end -end diff --git a/app/api/v1/helpers/bulk_jobs_helper.rb b/app/api/v1/helpers/bulk_jobs_helper.rb deleted file mode 100644 index f49282851..000000000 --- a/app/api/v1/helpers/bulk_jobs_helper.rb +++ /dev/null @@ -1,13 +0,0 @@ -module V1 - module Helpers - module BulkJobsHelper - def bulk_job - @bulk_job ||= ::BulkJob.find_by_id(params[:id]) - end - - def bulk_job! - bulk_job || not_found! - end - end - end -end diff --git a/app/api/v1/helpers/documents_helper.rb b/app/api/v1/helpers/documents_helper.rb deleted file mode 100644 index 0741c7f90..000000000 --- a/app/api/v1/helpers/documents_helper.rb +++ /dev/null @@ -1,13 +0,0 @@ -module V1 - module Helpers - module DocumentsHelper - def document - @document ||= Document.find_by_id(params[:id]) - end - - def document! - document || not_found! - end - end - end -end diff --git a/app/api/v1/helpers/media_helper.rb b/app/api/v1/helpers/media_helper.rb deleted file mode 100644 index 8d9b12b08..000000000 --- a/app/api/v1/helpers/media_helper.rb +++ /dev/null @@ -1,13 +0,0 @@ -module V1 - module Helpers - module MediaHelper - def media - @media ||= ::GetSingleMedia.call(id: params[:id], tenant: current_tenant.id).media - end - - def media! - media || not_found! - end - end - end -end diff --git a/app/api/v1/helpers/posts_helper.rb b/app/api/v1/helpers/posts_helper.rb deleted file mode 100644 index 0e9f68e76..000000000 --- a/app/api/v1/helpers/posts_helper.rb +++ /dev/null @@ -1,27 +0,0 @@ -module V1 - module Helpers - module PostsHelper - include ActsAsTaggableOn::TagsHelper - - def post - @post ||= ::GetPost.call(id: params[:id], tenant: current_tenant.id).post - end - - def reload_post - @post = ::GetPost.call(id: params[:id], tenant: current_tenant.id).post - end - - def published_post - @post = ::GetPost.call(id: params[:id], tenant: current_tenant.id, published: true).post - end - - def post! - post || not_found! - end - - def published_post! - published_post || not_found! - end - end - end -end diff --git a/app/api/v1/helpers/shared_params_helper.rb b/app/api/v1/helpers/shared_params_helper.rb index dda441245..ef7edab3a 100644 --- a/app/api/v1/helpers/shared_params_helper.rb +++ b/app/api/v1/helpers/shared_params_helper.rb @@ -11,21 +11,6 @@ module SharedParamsHelper params :search do optional :q, type: String, desc: 'Query string' end - - params :post_metadata do - optional :categories, type: String, desc: 'Categories' - optional :industries, type: String, desc: 'Industries' - optional :job_phase, type: String, desc: 'Job Phase' - optional :post_type, type: String, desc: 'Post Type' - optional :author, type: String, desc: 'Post Author' - optional :tags, type: String, desc: 'Tags' - end - - params :post_associations do - optional :featured_media_id, type: Integer, desc: 'Featured Media ID' - optional :tile_media_id, type: Integer, desc: 'Tile Media ID' - optional :author_id, type: Integer, desc: 'Author ID' - end end end end diff --git a/app/api/v1/helpers/snippets_helper.rb b/app/api/v1/helpers/snippets_helper.rb deleted file mode 100644 index 593f22196..000000000 --- a/app/api/v1/helpers/snippets_helper.rb +++ /dev/null @@ -1,13 +0,0 @@ -module V1 - module Helpers - module SnippetsHelper - def snippet - @snippet ||= Snippet.find_by_id(params[:id]) - end - - def snippet! - snippet || not_found! - end - end - end -end diff --git a/app/api/v1/helpers/tenants_helper.rb b/app/api/v1/helpers/tenants_helper.rb deleted file mode 100644 index 654531856..000000000 --- a/app/api/v1/helpers/tenants_helper.rb +++ /dev/null @@ -1,13 +0,0 @@ -module V1 - module Helpers - module TenantsHelper - def tenant - @tenant ||= Tenant.find_by_id(params[:id]) - end - - def tenant! - tenant || not_found! - end - end - end -end diff --git a/app/api/v1/helpers/users_helper.rb b/app/api/v1/helpers/users_helper.rb deleted file mode 100644 index faadb3ed3..000000000 --- a/app/api/v1/helpers/users_helper.rb +++ /dev/null @@ -1,13 +0,0 @@ -module V1 - module Helpers - module UsersHelper - def user - @user ||= User.find(params[:user_id]) - end - - def user! - user || not_found! - end - end - end -end diff --git a/app/api/v1/helpers/webpages_helper.rb b/app/api/v1/helpers/webpages_helper.rb deleted file mode 100644 index 73a4c14af..000000000 --- a/app/api/v1/helpers/webpages_helper.rb +++ /dev/null @@ -1,13 +0,0 @@ -module V1 - module Helpers - module WebpagesHelper - def webpage - @webpage ||= Webpage.find_by_id(params[:id]) - end - - def webpage! - webpage || not_found! - end - end - end -end diff --git a/app/api/v1/resources/bulk_jobs.rb b/app/api/v1/resources/bulk_jobs.rb deleted file mode 100644 index 8d4d4a7e2..000000000 --- a/app/api/v1/resources/bulk_jobs.rb +++ /dev/null @@ -1,30 +0,0 @@ -module V1 - module Resources - class BulkJobs < Grape::API - resource :bulk_jobs do - include Grape::Kaminari - helpers ::V1::Helpers::BulkJobsHelper - - paginate per_page: 25 - - desc 'Show all bulk jobs', { entity: ::V1::Entities::BulkJob, nickname: 'showAllBulkJobs' } - get do - authorize! :view, ::BulkJob - require_scope! 'view:bulk_jobs' - - @bulk_job = ::BulkJob.order(created_at: :desc) - - ::V1::Entities::BulkJob.represent paginate(@bulk_job) - end - - desc 'Get bulk job', { entity: ::V1::Entities::BulkJob, nickname: 'showBulkJob' } - get ':id' do - require_scope! 'view:bulk_jobs' - authorize! :view, bulk_job! - - present bulk_job, with: ::V1::Entities::BulkJob - end - end - end - end -end diff --git a/app/api/v1/resources/categories.rb b/app/api/v1/resources/categories.rb deleted file mode 100644 index 85696740f..000000000 --- a/app/api/v1/resources/categories.rb +++ /dev/null @@ -1,26 +0,0 @@ -module V1 - module Resources - class Categories < Grape::API - resource :categories do - desc 'Show all categories', { entity: ::V1::Entities::Category, nickname: "showAllCategories" } - params do - optional :depth, default: 1, type: Integer, desc: "Minimum category depth" - end - get do - authorize! :view, Category - present Category.where("depth >= ?", params[:depth]), with: ::V1::Entities::Category - end - - desc 'Show category hierarchy', { entity: ::V1::Entities::Category, nickname: "showCategoryHierarchy" } - get :hierarchy do - authorize! :view, Category - if params[:roots_only] == 'false' - present Category.all, with: ::V1::Entities::Category - else - present Category.roots, with: ::V1::Entities::Category, children: true - end - end - end - end - end -end diff --git a/app/api/v1/resources/documents.rb b/app/api/v1/resources/documents.rb deleted file mode 100644 index 9bca9fa1c..000000000 --- a/app/api/v1/resources/documents.rb +++ /dev/null @@ -1,72 +0,0 @@ -module V1 - module Resources - class Documents < Grape::API - resource :documents do - include Grape::Kaminari - helpers ::V1::Helpers::DocumentsHelper - - paginate per_page: 25 - - desc 'Show all documents', { entity: ::V1::Entities::Document, nickname: 'showAllDocument' } - get do - authorize! :view, ::Document - require_scope! 'view:documents' - - @document = ::Document.order(created_at: :desc) - ::V1::Entities::Document.represent paginate(@document) - end - - desc 'Get document', { entity: ::V1::Entities::Document, nickname: 'showDocument' } - get ':id' do - require_scope! 'view:documents' - authorize! :view, document! - - present document, with: ::V1::Entities::Document - end - - desc 'Create document', { entity: ::V1::Entities::Document, params: ::V1::Entities::Document.documentation, nickname: 'createDocument' } - post do - require_scope! 'modify:documents' - authorize! :create, ::Document - - document_params = params[:document] || params - - @document = ::Document.new(declared(document_params, { include_missing: false }, ::V1::Entities::Document.documentation.keys)) - document.user = current_user! - document.save! - - present document, with: ::V1::Entities::Document - end - - desc 'Update document', { entity: ::V1::Entities::Document, params: ::V1::Entities::Document.documentation, nickname: 'updateDocument' } - put ':id' do - require_scope! 'modify:documents' - authorize! :update, document! - - document_params = params[:document] || params - - document.update!(declared(document_params, { include_missing: false }, ::V1::Entities::Document.documentation.keys)) - - present document, with: ::V1::Entities::Document - end - - desc 'Delete document', { nickname: 'deleteDocument' } - delete ':id' do - require_scope! 'modify:documents' - authorize! :delete, document! - - begin - document.destroy - rescue Cortex::Exceptions::ResourceConsumed => e - error = error!({ - error: 'Conflict', - message: e.message, - status: 409 - }, 409) - error - end - end - end - end - end -end diff --git a/app/api/v1/resources/media.rb b/app/api/v1/resources/media.rb deleted file mode 100644 index 139bcc780..000000000 --- a/app/api/v1/resources/media.rb +++ /dev/null @@ -1,136 +0,0 @@ -module V1 - module Resources - class Media < Grape::API - helpers ::V1::Helpers::SharedParamsHelper - helpers ::V1::Helpers::ParamsHelper - - resource :media do - include Grape::Kaminari - helpers ::V1::Helpers::MediaHelper - helpers ::V1::Helpers::BulkJobsHelper - - paginate per_page: 25 - - desc 'Show all media', { entity: ::V1::Entities::Media, nickname: 'showAllMedia' } - params do - use :search - end - get do - authorize! :view, ::Media - require_scope! 'view:media' - - @media = ::GetMultipleMedia.call(params: declared(clean_params(params), include_missing: false), tenant: current_tenant).media - ::V1::Entities::Media.represent paginate(@media).records - end - - desc 'Show media tags' - params do - optional :s - end - get 'tags' do - require_scope! 'view:media' - authorize! :view, ::Media - - tags = params[:s] \ - ? ::Media.tag_counts_on(:tags).where('name ILIKE ?', "%#{params[:s]}%") \ - : ::Media.tag_counts_on(:tags) - - if params[:popular] - tags = tags.order('count DESC').limit(20) - end - - present tags, with: ::V1::Entities::Tag - end - - desc 'Get media', { entity: ::V1::Entities::Media, nickname: 'showMedia' } - get ':id' do - require_scope! 'view:media' - authorize! :view, media! - - present media, with: ::V1::Entities::Media, full: true - end - - desc 'Create media', { entity: ::V1::Entities::Media, params: ::V1::Entities::Media.documentation, nickname: 'createMedia' } - params do - optional :attachment - end - post do - require_scope! 'modify:media' - authorize! :create, ::Media - - media_params = params[:media] || params - - @media = ::Media.new(declared(media_params, { include_missing: false }, ::V1::Entities::Media.documentation.keys)) - media.user = current_user! - if params[:tag_list] - media.tag_list = params[:tag_list] - end - media.save! - - present media, with: ::V1::Entities::Media, full: true - end - - desc 'Update media', { entity: ::V1::Entities::Media, params: ::V1::Entities::Media.documentation, nickname: 'updateMedia' } - params do - optional :attachment - end - put ':id' do - require_scope! 'modify:media' - authorize! :update, media! - - media_params = params[:media] || params - - allowed_params = [:name, :alt, :description, :tag_list, :status, :deactive_at, :attachment] - - if params[:tag_list] - media.tag_list = params[:tag_list] - end - media.update!(declared(media_params, { include_missing: false }, allowed_params)) - - present media, with: ::V1::Entities::Media, full: true - end - - desc 'Delete media', { nickname: 'deleteMedia' } - delete ':id' do - require_scope! 'modify:media' - authorize! :delete, media! - - begin - media.destroy - rescue Cortex::Exceptions::ResourceConsumed => e - error = error!({ - error: 'Conflict', - message: e.message, - status: 409 - }, 409) - error - end - end - - desc 'Bulk create media', { entity: ::V1::Entities::BulkJob, nickname: 'bulkCreateMedia' } - params do - group :bulkJob, type: Hash do - requires :assets - end - end - post :bulk_job do - require_scope! 'modify:media' - require_scope! 'modify:bulk_jobs' - authorize! :create, ::Media - authorize! :create, ::BulkJob - - bulk_job_params = params[:bulkJob] || params - - @bulk_job = ::BulkJob.new(declared(bulk_job_params, { include_missing: false }, ::V1::Entities::BulkJob.documentation.keys)) - bulk_job.content_type = 'Media' - bulk_job.user = current_user! - bulk_job.save! - - BulkCreateMediaJob.perform_later(bulk_job, current_user!) - - present bulk_job, with: ::V1::Entities::BulkJob - end - end - end - end -end diff --git a/app/api/v1/resources/occupations.rb b/app/api/v1/resources/occupations.rb deleted file mode 100644 index bd20735ce..000000000 --- a/app/api/v1/resources/occupations.rb +++ /dev/null @@ -1,17 +0,0 @@ -module V1 - module Resources - class Occupations < Grape::API - resource :occupations do - desc 'Show all occupations', { entity: ::V1::Entities::Occupation, nickname: "showAllOccupations" } - get do - present ::Onet::Occupation.all, with: ::V1::Entities::Occupation - end - - desc 'Show all industries', { entity: ::V1::Entities::Occupation, nickname: "showAllIndustries" } - get :industries do - present ::Onet::Occupation.industries, with: ::V1::Entities::Occupation - end - end - end - end -end diff --git a/app/api/v1/resources/posts.rb b/app/api/v1/resources/posts.rb deleted file mode 100644 index c2f9ef86a..000000000 --- a/app/api/v1/resources/posts.rb +++ /dev/null @@ -1,175 +0,0 @@ -module V1 - module Resources - class Posts < Grape::API - helpers ::V1::Helpers::SharedParamsHelper - helpers ::V1::Helpers::ParamsHelper - - resource :posts do - include Grape::Kaminari - helpers ::V1::Helpers::PostsHelper - - paginate per_page: 25 - - desc 'Show all posts', { entity: ::V1::Entities::Post, nickname: "showAllPosts" } - params do - use :search - use :post_metadata - use :pagination - end - get do - require_scope! 'view:posts' - authorize! :view, ::Post - @posts = ::GetPosts.call(params: declared(clean_params(params), include_missing: false), tenant: current_tenant).posts - ::V1::Entities::Post.represent paginate(@posts).records - end - - desc 'Show published posts', { entity: ::V1::Entities::Post, nickname: "postFeed" } - params do - use :search - use :post_metadata - use :pagination - end - get 'feed' do - require_scope! 'view:posts' - authorize! :view, ::Post - last_updated_at = Post.last_updated_at - params_hash = Digest::MD5.hexdigest(declared(params).to_s) - cache_key = "feed-#{last_updated_at}-#{current_tenant.id}-#{params_hash}" - - posts = ::Rails.cache.fetch(cache_key, expires_in: 30.minutes, race_condition_ttl: 10) do - posts = ::GetPosts.call(params: declared(clean_params(params), include_missing: false), tenant: current_tenant, published: true).posts - paginated_posts = paginate(posts).records.to_a - {records: paginated_posts, headers: header} - end - - header.merge!(posts[:headers]) - ::V1::Entities::Post.represent posts[:records] - end - - desc 'Show all published posts', { entity: ::V1::Entities::Post, nickname: "allPostFeed" } - paginate per_page: 10000 - get 'feed/all_posts' do - require_scope! 'view:posts' - authorize! :view, ::Post - - posts = ::GetPosts.call(params: declared(clean_params(params), include_missing: false), tenant: current_tenant, published: true).posts - ::V1::Entities::Post.represent paginate(posts).records - end - - desc 'Show published post authors' - get 'feed/authors' do - present Author.published.distinct, with: ::V1::Entities::Author - end - - desc 'Show related published posts', { entity: ::V1::Entities::Post, nickname: "relatedPosts" } - paginate per_page: 5 - get 'feed/:id/related' do - require_scope! 'view:posts' - post = GetPost.call(id: params[:id], published: true).post - not_found! unless post - authorize! :view, post - - @posts = ::GetRelatedPosts.call(post: post, params: declared(clean_params(params), include_missing: false), tenant: current_tenant, published: true).posts - ::V1::Entities::Post.represent paginate(@posts).records - end - - desc 'Show a published post', { entity: ::V1::Entities::Post, nickname: "showFeedPost" } - get 'feed/*id' do - @post = ::GetPost.call(id: params[:id], published: true, tenant: current_tenant.id).post - not_found! unless @post - authorize! :view, @post - present @post, with: ::V1::Entities::Post, full: true - end - - desc 'Show post tags' - params do - optional :s - end - get 'tags' do - require_scope! 'view:posts' - authorize! :view, Post - - tags = params[:s] \ - ? ::Post.tag_counts_on(:tags).where('name ILIKE ?', "%#{params[:s]}%") \ - : ::Post.tag_counts_on(:tags) - - if params[:popular] - tags = tags.order('count DESC').limit(20) - end - - present tags, with: ::V1::Entities::Tag - end - - desc 'Show all filters/facets for posts', { nickname: "showFilters" } - params do - optional :depth, default: 1, desc: "Minimum depth of filters" - end - get 'filters' do - require_scope! 'view:posts' - authorize! :view, Post - present :industries, ::Onet::Occupation.industries, with: ::V1::Entities::Occupation - present :categories, ::Category.where('depth >= ?', params[:depth]), with: ::V1::Entities::Category - present :job_phases, ::Category.roots, with: ::V1::Entities::Category, children: true - end - - desc 'Show a post', { entity: ::V1::Entities::Post, nickname: "showPost" } - get ':id' do - require_scope! 'view:posts' - @post = ::GetPost.call(id: params[:id], tenant: current_tenant.id).post - not_found! unless @post - authorize! :view, @post - present @post, with: ::V1::Entities::Post, full: true - end - - desc 'Create a post', { entity: ::V1::Entities::Post, params: ::V1::Entities::Post.documentation, nickname: "createPost" } - params do - use :post_associations - end - post do - require_scope! 'modify:posts' - authorize! :create, Post - - allowed_params = remove_params(::V1::Entities::Post.documentation.keys, :featured_media, :tile_media, :media, :industries, :categories, :is_published) + [:category_ids, :industry_ids, :author_id] - - @post = ::Post.new(declared(params, {include_missing: false}, allowed_params)) - post.user = params[:user] ? User.find(params[:user]) : current_user - post.save! - present post, with: ::V1::Entities::Post, full: true - end - - desc 'Update a post', { entity: ::V1::Entities::Post, params: ::V1::Entities::Post.documentation, nickname: "updatePost" } - params do - use :post_associations - end - put ':id' do - require_scope! 'modify:posts' - authorize! :update, post! - - allowed_params = remove_params(::V1::Entities::Post.documentation.keys, :featured_media, :tile_media, :media, :industries, :categories, :is_published) + [:category_ids, :industry_ids, :author_id] - - if params[:type] - post.update!({type: params[:type]}) if params[:type] - reload_post - end - if params[:tag_list] - post.tag_list = params[:tag_list] - end - if params[:seo_keyword_list] - post.seo_keyword_list = params[:seo_keyword_list] - end - post.update!(declared(params, {include_missing: false}, allowed_params)) - - present post, with: ::V1::Entities::Post, full: true - end - - desc 'Delete a post', { nickname: "deletePost" } - delete ':id' do - require_scope! 'modify:posts' - authorize! :delete, post! - - post.destroy - end - end - end - end -end diff --git a/app/api/v1/resources/snippets.rb b/app/api/v1/resources/snippets.rb deleted file mode 100644 index 32443dbc9..000000000 --- a/app/api/v1/resources/snippets.rb +++ /dev/null @@ -1,72 +0,0 @@ -module V1 - module Resources - class Snippets < Grape::API - resource :snippets do - include Grape::Kaminari - helpers ::V1::Helpers::SnippetsHelper - - paginate per_page: 25 - - desc 'Show all snippets', { entity: ::V1::Entities::Snippet, nickname: 'showAllSnippet' } - get do - authorize! :view, ::Snippet - require_scope! 'view:snippets' - - @snippet = ::Snippet.order(created_at: :desc) - ::V1::Entities::Snippet.represent paginate(@snippet) - end - - desc 'Get snippet', { entity: ::V1::Entities::Snippet, nickname: 'showSnippet' } - get ':id' do - require_scope! 'view:snippets' - authorize! :view, snippet! - - present snippet, with: ::V1::Entities::Snippet - end - - desc 'Create snippet', { entity: ::V1::Entities::Snippet, params: ::V1::Entities::Snippet.documentation, nickname: 'createSnippet' } - post do - require_scope! 'modify:snippets' - authorize! :create, ::Snippet - - snippet_params = params[:snippet] || params - - @snippet = ::Snippet.new(declared(snippet_params, { include_missing: false }, ::V1::Entities::Snippet.documentation.keys)) - snippet.user = current_user! - snippet.save! - - present snippet, with: ::V1::Entities::Snippet - end - - desc 'Update snippet', { entity: ::V1::Entities::Snippet, params: ::V1::Entities::Snippet.documentation, nickname: 'updateSnippet' } - put ':id' do - require_scope! 'modify:snippets' - authorize! :update, snippet! - - snippet_params = params[:snippet] || params - - snippet.update!(declared(snippet_params, { include_missing: false }, ::V1::Entities::Snippet.documentation.keys)) - - present snippet, with: ::V1::Entities::Snippet - end - - desc 'Delete snippet', { nickname: 'deleteSnippet' } - delete ':id' do - require_scope! 'modify:snippets' - authorize! :delete, snippet! - - begin - snippet.destroy - rescue Cortex::Exceptions::ResourceConsumed => e - error = error!({ - error: 'Conflict', - message: e.message, - status: 409 - }, 409) - error - end - end - end - end - end -end diff --git a/app/api/v1/resources/tenants.rb b/app/api/v1/resources/tenants.rb deleted file mode 100644 index ed8df6699..000000000 --- a/app/api/v1/resources/tenants.rb +++ /dev/null @@ -1,92 +0,0 @@ -module V1 - module Resources - class Tenants < Grape::API - helpers ::V1::Helpers::SharedParamsHelper - helpers ::V1::Helpers::ParamsHelper - - resource :tenants do - include Grape::Kaminari - helpers ::V1::Helpers::TenantsHelper - - paginate per_page: 25 - - desc 'Show all tenants', { entity: ::V1::Entities::Tenant, nickname: "showAllTenants" } - get do - require_scope! 'view:tenants' - authorize! :view, Tenant - - ::V1::Entities::Tenant.represent paginate(Tenant.all), children: params[:include_children] - end - - desc 'Show tenant hierarchy', { entity: ::V1::Entities::Tenant, nickname: "showTenantHierarchy" } - get :hierarchy do - require_scope! 'view:tenants' - authorize! :view, Tenant - - present Tenant.roots, using: ::V1::Entities::Tenant, children: true - end - - desc 'Show a tenant', { entity: ::V1::Entities::Tenant, nickname: "showTenant" } - get ':id' do - present tenant!, with: ::V1::Entities::Tenant, children: false - end - - desc 'Create a tenant', { entity: ::V1::Entities::Tenant, params: ::V1::Entities::Tenant.documentation, nickname: "createTenant" } - params do - optional :name, type: String, desc: "Tenant Name" - end - post do - require_scope! 'modify:tenants' - authorize! :create, Tenant - - allowed_params = remove_params(::V1::Entities::Tenant.documentation.keys, :children) - - @tenant = ::Tenant.new(declared(params, { include_missing: true }, allowed_params)) - tenant.owner = current_user - tenant.save! - present tenant, with: ::V1::Entities::Tenant - end - - desc 'Update a tenant', { entity: ::V1::Entities::Tenant, params: ::V1::Entities::Tenant.documentation, nickname: "updateTenant" } - put ':id' do - require_scope! 'modify:tenants' - authorize! :update, tenant! - - allowed_params = remove_params(::V1::Entities::Tenant.documentation.keys, :children) - - tenant.update!(declared(params, { include_missing: false }, allowed_params)) - present tenant, with: ::V1::Entities::Tenant - end - - desc 'Delete a tenant', { nickname: "deleteTenant" } - delete ':id' do - require_scope! 'modify:tenants' - authorize! :delete, tenant! - - tenant.destroy - end - - segment '/:id' do - resource :users do - include Grape::Kaminari - helpers ::V1::Helpers::UsersHelper - - paginate per_page: 25 - - desc 'Show all users belonging to a tenant', { entity: ::V1::Entities::User, nickname: "showAllTenantUsers" } - params do - use :search - end - get do - authorize! :view, User - require_scope! 'view:users' - - @users = ::GetUsers.call(params: declared(clean_params(params), include_missing: false), tenant_id: params[:id]).users - ::V1::Entities::User.represent paginate(@users).records, full: true - end - end - end - end - end - end -end diff --git a/app/api/v1/resources/users.rb b/app/api/v1/resources/users.rb deleted file mode 100644 index 31f424fad..000000000 --- a/app/api/v1/resources/users.rb +++ /dev/null @@ -1,141 +0,0 @@ -module V1 - module Resources - class Users < Grape::API - resource :users do - helpers ::V1::Helpers::UsersHelper - helpers ::V1::Helpers::BulkJobsHelper - - desc 'Get the current user', { entity: ::V1::Entities::User, nickname: 'currentUser' } - get :me do - authorize! :view, current_user! - present current_user, with: ::V1::Entities::User, full: true - end - - desc "Fetch a user's author info" - get ':user_id/author' do - require_scope! 'view:users' - authorize! :view, user! - - present user.author || not_found!, with: ::V1::Entities::Author - end - - desc "Save a user's author info" - params do - optional :email - optional :firstname - optional :lastname - optional :personal - optional :facebook - optional :twitter - optional :google - optional :bio - end - put ':user_id/author' do - require_scope! 'modify:users' - authorize! :update, user! - - author = Author.find_or_create_by(user_id: params[:user_id]) - author.update_attributes!(declared(params, {include_missing: false})) - author.save! - - present author, with: ::V1::Entities::Author - end - - desc 'Create a new user' - params do - optional :email - optional :firstname - optional :lastname - optional :tenant_id - optional :password - optional :password_confirmation - end - post do - require_scope! 'modify:users' - authorize! :create, User - - allowed_params = [:password, :password_confirmation, :firstname, :lastname, :email, :tenant_id, :admin] - - @user = User.create!(declared(params, {include_missing: false}, allowed_params)) - - present @user, with: ::V1::Entities::User, full: true - end - - desc "Save a user's info" - params do - optional :current_password - optional :password - optional :password_confirmation - optional :firstname - optional :lastname - optional :email - optional :admin - end - put ':user_id' do - require_scope! 'modify:users' - authorize! :update, user! - - allowed_params = [:firstname, :lastname] - - # Extract into permission concerns - if current_user.is_admin? - allowed_params += [:email, :admin] - elsif user == current_user - forbidden! unless user.valid_password?(params[:current_password]) - allowed_params += [:password, :password_confirmation] - render_api_error!('Requires both password and password_confirmation fields', 422) unless params[:password] && params[:password_confirmation] - else - forbidden! - end - - user.update!(declared(params, {include_missing: false}, allowed_params)) - - present user, with: ::V1::Entities::User, full: true - end - - desc 'Show a user', {nickname: 'showUser'} - get ':user_id' do - require_scope! 'view:users' - authorize! :view, user! - - present user, with: ::V1::Entities::User, full: true - end - - desc 'Delete a user', {nickname: 'deleteUser'} - delete ':user_id' do - require_scope! 'modify:users' - authorize! :delete, user! - - begin - user.destroy - rescue Cortex::Exceptions::ResourceConsumed => e - error!({ - error: 'Conflict', - message: e.message, - status: 409 - }, 409) - end - end - - desc 'Bulk create users', { entity: ::V1::Entities::BulkJob, nickname: 'bulkCreateUsers' } - post :bulk_job do - require_scope! 'modify:users' - require_scope! 'modify:bulk_jobs' - authorize! :create, ::User - authorize! :create, ::BulkJob - - bulk_job_params = params[:bulkJob] || params - - @bulk_job = ::BulkJob.new(declared(bulk_job_params, { include_missing: false }, ::V1::Entities::BulkJob.documentation.keys)) - bulk_job.content_type = 'Users' - bulk_job.user = current_user! - bulk_job.save! - - BulkCreateUsersJob.perform_later(bulk_job) - - present bulk_job, with: ::V1::Entities::BulkJob - end - end - end - end -end diff --git a/app/api/v1/resources/webpages.rb b/app/api/v1/resources/webpages.rb deleted file mode 100644 index e59c1a996..000000000 --- a/app/api/v1/resources/webpages.rb +++ /dev/null @@ -1,99 +0,0 @@ -module V1 - module Resources - class Webpages < Grape::API - helpers ::V1::Helpers::ParamsHelper - - resource :webpages do - include Grape::Kaminari - helpers ::V1::Helpers::WebpagesHelper - paginate per_page: 25 - - desc 'Show all webpages', { entity: ::V1::Entities::Webpage, nickname: 'showAllWebpages' } - params do - optional :q, type: String - end - get do - authorize! :view, ::Webpage - require_scope! 'view:webpages' - - @webpages = ::GetWebpages.call(params: declared(clean_params(params), include_missing: false), tenant: current_tenant).webpages - ::V1::Entities::Webpage.represent paginate(@webpages).records, full: true - end - - desc 'Show Webpage Snippets as public feed by URL', { entity: ::V1::Entities::Webpage, nickname: 'showWebpageFeed' } - params do - requires :url, type: String - end - get 'feed' do - require_scope! 'view:webpages' - @webpage = ::GetWebpageFeed.call(params: declared(clean_params(params), include_missing: false), tenant: current_tenant).webpage - not_found! unless @webpage - authorize! :view, @webpage - present @webpage, with: ::V1::Entities::Webpage - end - - desc 'Get webpage', { entity: ::V1::Entities::Webpage, nickname: 'showWebpage' } - get ':id' do - require_scope! 'view:webpages' - authorize! :view, webpage! - - present webpage, with: ::V1::Entities::Webpage, full: true - end - - desc 'Create webpage', { entity: ::V1::Entities::Webpage, params: ::V1::Entities::Webpage.documentation, nickname: 'createWebpage' } - post do - require_scope! 'modify:webpages' - authorize! :create, ::Webpage - - webpage_params = params[:webpage] || params - - @webpage = ::Webpage.new(declared(webpage_params, { include_missing: false }, ::V1::Entities::Webpage.documentation.keys)) - webpage.user = current_user! - webpage.save! - - present webpage, with: ::V1::Entities::Webpage, full: true - end - - desc 'Update webpage', { entity: ::V1::Entities::Webpage, params: ::V1::Entities::Webpage.documentation, nickname: 'updateWebpage' } - put ':id' do - require_scope! 'modify:webpages' - authorize! :update, webpage! - - webpage_params = params[:webpage] || params - allowed_params = remove_params(::V1::Entities::Webpage.documentation.keys, :user) + [:snippets_attributes] - update_params = declared(webpage_params, { include_missing: false }, allowed_params) - update_params[:snippets_attributes].each {|snippet| - snippet.user = current_user! - snippet[:document_attributes].user = current_user! - } - - if params[:seo_keyword_list] - webpage.seo_keyword_list = params[:seo_keyword_list] - end - - webpage.update!(update_params.to_hash) - CacheBustWebpageJob.perform_later(webpage.url) - - present webpage, with: ::V1::Entities::Webpage, full: true - end - - desc 'Delete webpage', { nickname: 'deleteWebpage' } - delete ':id' do - require_scope! 'modify:webpages' - authorize! :delete, webpage! - - begin - webpage.destroy - rescue Cortex::Exceptions::ResourceConsumed => e - error = error!({ - error: 'Conflict', - message: e.message, - status: 409 - }, 409) - error - end - end - end - end - end -end diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 41c2b55dc..7d79a6e97 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -8,7 +8,7 @@ //= require bootstrap-tagsinput //= require clipboard //= require dialog-polyfill -//= require moment +//= require momentjs //= require cortex-plugins-core/application //= require webpack-bundle diff --git a/app/assets/javascripts/authentication.js b/app/assets/javascripts/authentication.js index 6cbbcb1d4..d71aa5d15 100644 --- a/app/assets/javascripts/authentication.js +++ b/app/assets/javascripts/authentication.js @@ -5,6 +5,5 @@ //= require material //= require base -//= require authentication/login // require turbolinks # temporarily disabled diff --git a/app/assets/javascripts/authentication/login.js b/app/assets/javascripts/authentication/login.js deleted file mode 100644 index 097ad78fc..000000000 --- a/app/assets/javascripts/authentication/login.js +++ /dev/null @@ -1,15 +0,0 @@ -var login_tab_change = function() { - $('.login_tab').on('click', function(ev) { - var value = this.text; - $('#user_email').focus(); - - if (value === 'Legacy') { - $('.legacy_value').val(1) - } else { - $('.legacy_value').val(0) - } - }); -}; - -$(document).ready(login_tab_change); -$(document).on('page:load', login_tab_change); diff --git a/app/assets/javascripts/legacy/controllers/applications/grid.js b/app/assets/javascripts/legacy/controllers/applications/grid.js deleted file mode 100644 index de1f19b87..000000000 --- a/app/assets/javascripts/legacy/controllers/applications/grid.js +++ /dev/null @@ -1,77 +0,0 @@ -angular.module('cortex.controllers.applications.grid', [ - 'ui.router.state', - 'ngTable', - 'ui.bootstrap', - 'angular-flash.service', - 'cortex.services.cortex', - 'cortex.filters' -]) - - .controller('ApplicationsGridCtrl', function($scope, $window, $state, ngTableParams, cortex, flash) { - $scope.data = { - totalServerItems: 0, - applications: [], - query: null - }; - - $scope.applicationsTableParams = new ngTableParams({ - page: 1, - count: 10, - sorting: { - created_at: 'desc' - } - }, { - total: 0, - getData: function ($defer, params) { - cortex.applications.searchPaged({page: params.page(), per_page: params.count()}, - function (applications, headers, paging) { - params.total(paging.total); - $defer.resolve(applications); - }, - function (data) { - $defer.reject(data); - } - ); - } - }); - - $scope.newApplication = function() { - var application = new cortex.applications(); - var name = $window.prompt("Provide a name for the application"); - if (name !== null && name !== '') { - application.name = name; - application.$save(function() { - flash.success = "Successfully created new application " + name; - $scope.applicationsTableParams.reload(); - }, - function () { - flash.error = "Could not create new application, please try again."; - }); - } - }; - - $scope.editApplication = function(application) { - var name = $window.prompt("Provide a new name for the application"); - if (name !== null && name !== '') { - application.name = name; - application.$save(function() { - flash.success = "Successfully renamed application " + name; - $scope.applicationsTableParams.reload(); - }, - function () { - flash.error = "Could not rename application, please try again."; - }); - } - }; - - $scope.deleteApplication = function (application) { - if ($window.confirm('Are you sure you want to delete "' + application.name + '?"')) { - cortex.applications.delete({id: application.id}, function () { - flash.warn = application.name + ' deleted.'; - $scope.applicationsTableParams.reload(); - }, function () { - flash.error = application.name + ' could not be deleted due to an error.'; - }); - } - }; - }); diff --git a/app/assets/javascripts/legacy/controllers/bulk_jobs/grid.js b/app/assets/javascripts/legacy/controllers/bulk_jobs/grid.js deleted file mode 100644 index f3708ab57..000000000 --- a/app/assets/javascripts/legacy/controllers/bulk_jobs/grid.js +++ /dev/null @@ -1,40 +0,0 @@ -angular.module('cortex.controllers.bulk_jobs.grid', [ - 'ngTable', - 'ui.bootstrap', - 'angular-flash.service', - 'cortex.services.cortex', - 'cortex.filters' -]) - - .controller('BulkJobsGridCtrl', function ($scope, ngTableParams, flash, cortex) { - $scope.data = { - totalServerItems: 0, - bulk_jobs: [], - query: null - }; - - $scope.bulkJobDataParams = new ngTableParams({ - page: 1, - count: 10, - sorting: { - created_at: 'desc' - } - }, { - total: 0, - getData: function ($defer, params) { - cortex.bulk_jobs.searchPaged({page: params.page(), per_page: params.count()}, - function (bulk_jobs, headers, paging) { - params.total(paging.total); - $defer.resolve(bulk_jobs); - }, - function (data) { - $defer.reject(data); - } - ); - } - }); - - $scope.displayLog = function(bulkJob) { - alert(bulkJob.log.join('\n')); - }; - }); diff --git a/app/assets/javascripts/legacy/controllers/credentials/edit.js b/app/assets/javascripts/legacy/controllers/credentials/edit.js deleted file mode 100644 index d3faa0366..000000000 --- a/app/assets/javascripts/legacy/controllers/credentials/edit.js +++ /dev/null @@ -1,30 +0,0 @@ -angular.module('cortex.controllers.credentials.edit', [ - 'ui.router.state', - 'angular-flash.service', - 'cortex.services.cortex', - 'cortex.util' -]) - - .controller('CredentialsEditCtrl', function ($scope, $state, $stateParams, $anchorScroll, flash, cortex, util) { - $scope.data = $scope.data || {}; - - $scope.data.credentials = cortex.credentials.get({application_id: $stateParams.applicationId, - credentials_id: $stateParams.credentialsId}); - - $scope.saveCredentials = function() { - $scope.data.credentials.$save({application_id: $stateParams.applicationId, - credentials_id: $stateParams.credentialsId}, function() { - flash.success = "Successfully saved " + $scope.data.credentials.name; - $state.go('^'); - }, function(res) { - if (res.status === 402) { - flash.error = "Could not save " + $scope.data.credentials.name + " - " + res.data.errors[0]; - } else { - flash.error = "Could not save " + $scope.data.credentials.name; - } - }); - }; - $scope.cancel = function() { - $state.go('^'); - } - }); diff --git a/app/assets/javascripts/legacy/controllers/credentials/grid.js b/app/assets/javascripts/legacy/controllers/credentials/grid.js deleted file mode 100644 index 76e5c450e..000000000 --- a/app/assets/javascripts/legacy/controllers/credentials/grid.js +++ /dev/null @@ -1,48 +0,0 @@ -angular.module('cortex.controllers.credentials.grid', [ - 'ui.router.state', - 'ngTable', - 'ui.bootstrap', - 'angular-flash.service', - 'cortex.services.cortex', - 'cortex.filters' -]) - - .controller('CredentialsGridCtrl', function($scope, $window, $state, $stateParams, ngTableParams, cortex, flash) { - $scope.data = { - totalServerItems: 0, - credentials: [], - query: null - }; - - $scope.credentialsTableParams = new ngTableParams({ - page: 1, - count: 10, - sorting: { - created_at: 'desc' - } - }, { - total: 0, - getData: function ($defer, params) { - cortex.credentials.searchPaged({application_id: $stateParams.applicationId, page: params.page(), per_page: params.count()}, - function (applications, headers, paging) { - params.total(paging.total); - $defer.resolve(applications); - }, - function (data) { - $defer.reject(data); - } - ); - } - }); - - $scope.deleteCredential = function (credential) { - if ($window.confirm('Are you sure you want to delete "' + credential.name + '?"')) { - cortex.credentials.delete({application_id: $stateParams.applicationId, credential_id: credential.id}, function () { - flash.warn = credential.name + ' deleted.'; - $scope.credentialsTableParams.reload(); - }, function () { - flash.error = credential.name + ' could not be deleted due to an error.'; - }); - } - }; - }); diff --git a/app/assets/javascripts/legacy/controllers/credentials/new.js b/app/assets/javascripts/legacy/controllers/credentials/new.js deleted file mode 100644 index 3ab931a1b..000000000 --- a/app/assets/javascripts/legacy/controllers/credentials/new.js +++ /dev/null @@ -1,28 +0,0 @@ -angular.module('cortex.controllers.credentials.new', [ - 'ui.router.state', - 'angular-flash.service', - 'cortex.services.cortex', - 'cortex.util' -]) - - .controller('CredentialsNewCtrl', function ($scope, $state, $stateParams, flash, cortex, util) { - $scope.data = $scope.data || {}; - - $scope.data.credentials = new cortex.credentials(); - - $scope.saveCredentials = function() { - $scope.data.credentials.$save({application_id: $stateParams.applicationId}, function() { - flash.success = "Successfully saved " + $scope.data.credentials.name; - $state.go('^'); - }, function(res) { - if (res.status === 402) { - flash.error = "Could not save " + $scope.data.credentials.name + " - " + res.data.errors[0]; - } else { - flash.error = "Could not save " + $scope.data.credentials.name; - } - }); - }; - $scope.cancel = function() { - $state.go('^'); - } - }); diff --git a/app/assets/javascripts/legacy/controllers/locales/edit.js b/app/assets/javascripts/legacy/controllers/locales/edit.js deleted file mode 100644 index c0a2c0422..000000000 --- a/app/assets/javascripts/legacy/controllers/locales/edit.js +++ /dev/null @@ -1,39 +0,0 @@ -angular.module('cortex.controllers.locales.edit', [ - 'ui.router.state', - 'angular-flash.service', - 'cortex.services.cortex', - 'cortex.util' -]) - -.controller('LocalesEditCtrl', function ($scope, $state, $stateParams, $anchorScroll, flash, cortex, util) { - $scope.data = $scope.data || {}; - var saveParams = {}; - - if (util.isEmpty($stateParams.localeName)) { - saveParams = {localization_id: $stateParams.localizationId}; - $scope.data.locale = new cortex.locales(); - } - else { - saveParams = {localization_id: $stateParams.localizationId, locale_name: $stateParams.localeName}; - $scope.data.locale = cortex.locales.get(saveParams); - } - - $scope.cancel = function () { - $state.go('^.edit'); - }; - - $scope.saveLocale = function () { - delete $scope.data.locale.json; - $scope.data.locale.$save(saveParams).then( - function () { - $anchorScroll(); - flash.success = 'Saved locale information'; - $state.go('^.edit'); - }, - function () { - $anchorScroll(); - flash.error = 'Error while saving locale information'; - } - ); - }; -}); diff --git a/app/assets/javascripts/legacy/controllers/locales/grid.js b/app/assets/javascripts/legacy/controllers/locales/grid.js deleted file mode 100644 index 59f841bd1..000000000 --- a/app/assets/javascripts/legacy/controllers/locales/grid.js +++ /dev/null @@ -1,70 +0,0 @@ -angular.module('cortex.controllers.locales.grid', [ - 'ui.router.state', - 'ngTable', - 'ui.bootstrap', - 'angular-flash.service', - 'cortex.services.cortex', - 'cortex.filters' -]) - - .controller('LocalesGridCtrl', function ($scope, $window, $state, $stateParams, ngTableParams, cortex, flash) { - $scope.data = { - totalServerItems: 0, - locales: [], - query: null - }; - - $scope.localeDataParams = new ngTableParams({ - page: 1, - count: 10, - sorting: { - created_at: 'desc' - } - }, { - total: 0, - getData: function ($defer, params) { - cortex.locales.searchPaged({localization_id: $stateParams.localizationId, - page: params.page(), per_page: params.count()}, - function (locales, headers, paging) { - params.total(paging.total); - $defer.resolve(locales); - }, - function (data) { - $defer.reject(data); - } - ); - } - }); - - $scope.editLocale = function(locale) { - $state.go('cortex.localizations.localization.edit_locale', {localeName: locale.name}); - }; - - $scope.deleteLocale = function (locale) { - if ($window.confirm('Are you sure you want to delete "' + locale.name + '?"')) { - cortex.locales.delete({localization_id: $stateParams.localizationId, locale_name: locale.name}, function () { - flash.warn = locale.name + ' deleted.'; - $scope.localeDataParams.reload(); - }, function () { - flash.error = locale.name + ' could not be deleted due to an error.'; - }); - } - }; - - $scope.duplicateLocale = function (locale) { - if ($window.confirm('Are you sure you want to duplicate "' + locale.name + '?"')) { - var duplicate = new cortex.locales(locale); - delete duplicate.id; - delete duplicate.json; - duplicate.name += ' - Copy'; - duplicate.$save({localization_id: $stateParams.localizationId}).then( - function () { - flash.success = locale.name + ' duplicated.'; - $scope.localeDataParams.reload(); - }, - function () { - flash.error = locale.name + ' could not be duplicated due to an error.'; - }); - } - }; - }); diff --git a/app/assets/javascripts/legacy/controllers/localizations/edit.js b/app/assets/javascripts/legacy/controllers/localizations/edit.js deleted file mode 100644 index f4ce0a56c..000000000 --- a/app/assets/javascripts/legacy/controllers/localizations/edit.js +++ /dev/null @@ -1,35 +0,0 @@ -angular.module('cortex.controllers.localizations.edit', [ - 'ui.router.state', - 'angular-flash.service', - 'cortex.services.cortex', - 'cortex.util' -]) - -.controller('LocalizationsEditCtrl', function ($scope, $state, $stateParams, $anchorScroll, flash, cortex, util) { - $scope.data = $scope.data || {}; - - if (util.isEmpty($stateParams.localizationId)) { - $scope.data.localization = new cortex.localizations(); - } - else { - $scope.data.localization = cortex.localizations.get({id: $stateParams.localizationId}); - } - - $scope.cancel = function () { - $state.go('cortex.localizations.manage'); - }; - - $scope.saveLocalization = function () { - $scope.data.localization.$save().then( - function () { - $anchorScroll(); - flash.success = 'Saved localization information'; - $state.go('cortex.localizations.manage'); - }, - function () { - $anchorScroll(); - flash.error = 'Error while saving localization information'; - } - ); - }; -}); diff --git a/app/assets/javascripts/legacy/controllers/localizations/grid.js b/app/assets/javascripts/legacy/controllers/localizations/grid.js deleted file mode 100644 index 3bc7a57d1..000000000 --- a/app/assets/javascripts/legacy/controllers/localizations/grid.js +++ /dev/null @@ -1,69 +0,0 @@ -angular.module('cortex.controllers.localizations.grid', [ - 'ui.router.state', - 'ngTable', - 'ui.bootstrap', - 'angular-flash.service', - 'cortex.services.cortex', - 'cortex.filters' -]) - - .controller('LocalizationsGridCtrl', function ($scope, $window, $state, ngTableParams, flash, cortex) { - $scope.data = { - totalServerItems: 0, - localizations: [], - query: null - }; - - $scope.localizationDataParams = new ngTableParams({ - page: 1, - count: 10, - sorting: { - created_at: 'desc' - } - }, { - total: 0, - getData: function ($defer, params) { - cortex.localizations.searchPaged({page: params.page(), per_page: params.count()}, - function (localizations, headers, paging) { - params.total(paging.total); - $defer.resolve(localizations); - }, - function (data) { - $defer.reject(data); - } - ); - } - }); - - $scope.editLocalization = function(localization) { - $state.go('^.localization.edit', {localizationId: localization.id}); - }; - - $scope.deleteLocalization = function (localization) { - if ($window.confirm('Are you sure you want to delete "' + localization.name + '?"')) { - cortex.localizations.delete({id: localization.id}, function () { - flash.warn = localization.name + ' deleted.'; - $scope.localizationDataParams.reload(); - }, function () { - flash.error = localization.name + ' could not be deleted due to an error.'; - }); - } - }; - - $scope.duplicateLocalization = function (localization) { - if ($window.confirm('Are you sure you want to duplicate "' + localization.name + '?"')) { - var duplicate = new cortex.localizations(localization); - delete duplicate.id; - duplicate.locales = _.map(duplicate.locales, function(locale) { return _.omit(locale, 'json'); }); - duplicate.name += ' - Copy'; - duplicate.$save().then( - function () { - flash.success = localization.name + ' duplicated.'; - $scope.localizationDataParams.reload(); - }, - function () { - flash.error = localization.name + ' could not be duplicated due to an error.'; - }); - } - }; - }); diff --git a/app/assets/javascripts/legacy/controllers/media/bulk.js b/app/assets/javascripts/legacy/controllers/media/bulk.js deleted file mode 100644 index 085d7f679..000000000 --- a/app/assets/javascripts/legacy/controllers/media/bulk.js +++ /dev/null @@ -1,85 +0,0 @@ -angular.module('cortex.controllers.media.bulk', [ - 'ui.router.state', - 'ui.bootstrap.progressbar', - 'angular-flash.service', - 'angularFileUpload', - 'cortex.settings', - 'cortex.services.cortex', - 'cortex.directives.fileSelector' -]) - - .controller('MediaBulkCtrl', function ($scope, $timeout, $upload, $state, $q, flash, cortex, settings) { - $scope.data = $scope.data || {}; - $scope.data.mediaBulk = new cortex.media.bulkJob(); - $scope.data.upload = { - progress: 0 - }; - - function saveBulkJob() { - var d = $q.defer(); - - if (!$scope.data.mediaBulk.metadata) { - d.reject('No metadata present.'); - } - else { - var uploadError = false; - var httpConfig = { - url: settings.cortex_base_url + '/media/bulk_job', - method: 'POST', - fields: {bulkJob: $scope.data.mediaBulk}, - formDataAppender: function (formData, key, value) { - if (key === 'bulkJob') { - angular.forEach(value, function (v, k) { - formData.append('bulkJob[' + k + ']', v); - }); - } - } - }; - - $scope.data.upload.progress = 1; - $scope.data.upload = $upload.upload(httpConfig) - .then( - function (bulkJob) { //Success - d.resolve(); - }, - function (error, status) { //Error - uploadError = true; - $scope.data.upload.progress = 0; - $scope.data.upload.file = null; - - if (status === 422) { - d.reject('Selected file type is not supported. Please choose a different file.'); - } else if (status === 502) { - d.reject('The server is taking too long to respond. Please reduce the file size of the content you are uploading and try again.') - } - else { - d.reject('Unhandled error: ' + error.data.errors[0]); - } - }, - function (e) { //Progress - if (uploadError) { - return; - } - $scope.data.upload.progress = parseInt(100.0 * e.loaded / e.total); - } - ); - } - - return d.promise; - } - - $scope.saveMediaBulk = function () { - saveBulkJob().then( - function () { - flash.success = 'Bulk job created'; - $state.go('cortex.bulk_jobs.manage'); - }, - function (error) { - flash.error = error; - }); - }; - - $scope.cancel = function () { - $state.go('^.manage.components'); - }; - }); diff --git a/app/assets/javascripts/legacy/controllers/media/edit.js b/app/assets/javascripts/legacy/controllers/media/edit.js deleted file mode 100644 index a6e7c1616..000000000 --- a/app/assets/javascripts/legacy/controllers/media/edit.js +++ /dev/null @@ -1,171 +0,0 @@ -angular.module('cortex.controllers.media.edit', [ - 'ui.router.state', - 'ui.bootstrap.datepicker', - 'ui.bootstrap.progressbar', - 'ui.bootstrap.tabs', - 'ui.bootstrap.dropdown', - 'angular-flash.service', - 'angularFileUpload', - 'ngTagsInput', - 'cortex.settings', - 'cortex.filters', - 'cortex.services.cortex', - 'cortex.directives.fileSelector', - 'cortex.directives.youtubeSelector', - 'cortex.directives.showErrors' -]) - - .controller('MediaEditCtrl', function ($scope, $timeout, $upload, $state, $stateParams, $q, flash, cortex, settings) { - $scope.data = $scope.data || {}; - $scope.data.currentTab = 'file'; - if ($stateParams.mediaId) { - $scope.data.media = cortex.media.get({id: $stateParams.mediaId}); - } - else { - $scope.data.media = new cortex.media(); - } - $scope.data.media.tag_list = []; - $scope.data.upload = { - progress: 0 - }; - - // angular-bootstrap datepicker settings - $scope.datepicker = { - format: 'yyyy/MM/dd', - expireAtOpen: false, - open: function (datepicker) { - $timeout(function () { - $scope.datepicker[datepicker] = true; - }); - } - }; - - function saveFile() { - var d = $q.defer(), - httpMethod, httpUrlSuffix = ''; - - $scope.data.media.type = 'Media'; - - if ($stateParams.mediaId) { - httpMethod = 'PUT'; - httpUrlSuffix = '/' + $stateParams.mediaId; - } - else { - httpMethod = 'POST'; - } - var uploadError = false, - httpConfig = { - url: settings.cortex_base_url + '/media' + httpUrlSuffix, - method: httpMethod, - fields: {media: $scope.data.media}, - file: $scope.data.media.$file, - fileFormDataName: 'media[attachment]', - formDataAppender: function (formData, key, value) { - if (key === 'media') { - angular.forEach(value, function (v, k) { - formData.append('media[' + k + ']', v); - }); - } - } - }; - - $scope.data.upload.progress = 1; - $scope.data.upload = $upload.upload(httpConfig) - .then( - function (media) { //Success - d.resolve(); - }, - function (error, status) { //Error - uploadError = true; - $scope.data.upload.progress = 0; - $scope.data.upload.file = null; - - if (status === 422) { - d.reject('Selected file type is not supported. Please choose a different file.'); - } else if (status === 502) { - d.reject('The server is taking too long to respond. Please reduce the file size of the content you are uploading and try again.') - } else { - d.reject('Unhandled error'); - } - }, - function (e) { //Progress - if (uploadError) { - return; - } - $scope.data.upload.progress = parseInt(100.0 * e.loaded / e.total); - } - ); - - return d.promise; - } - - // - - function saveYoutube() { - $scope.data.media.type = 'Youtube'; - $scope.data.media.video_id = $scope.data.media.$youtube; - return $scope.data.media.$save(); - } - - function saveWithoutAttachment() { - return $scope.data.media.$save(); - } - - $scope.saveMedia = function () { - var tab = $scope.currentTab; - var save; - - $scope.$broadcast('validateShowErrors'); - - $scope.data.media.tag_list = $scope.data.media.tag_list.map(function (tag) { - return tag.name; - }); - - if (tab === 'file' && $scope.data.media.$file) { - save = saveFile; - } - else if (tab === 'youtube' && $scope.data.media.$youtube) { - save = saveYoutube; - } - else if ($stateParams.mediaId) { - save = saveWithoutAttachment; - } - else { - flash.error = 'No attachment present. An attachment is required.'; - return; - } - - save().then( - function () { - flash.success = $scope.data.media.name + ' saved'; - $state.go('^.manage.components'); - }, - function (error) { - flash.error = error; - }); - }; - - $scope.selectTab = function (tab) { - $scope.currentTab = tab; - }; - - $scope.cancel = function () { - $state.go('^.manage.components'); - }; - - $scope.loadTags = function (search) { - return cortex.media.tags({s: search}).$promise; - }; - - $scope.data.popularTags = cortex.media.tags({popular: true}); - - // Adds a tag to tag_list if it doesn't already exist in array - $scope.addTag = function (tag) { - if (_.some($scope.data.media.tag_list, function (t) { - return t.name == tag.name; - })) { - return; - } - $scope.data.media.tag_list.push({name: tag.name, id: tag.id}); - }; - }); diff --git a/app/assets/javascripts/legacy/controllers/media/grid.js b/app/assets/javascripts/legacy/controllers/media/grid.js deleted file mode 100644 index 54a477b36..000000000 --- a/app/assets/javascripts/legacy/controllers/media/grid.js +++ /dev/null @@ -1,92 +0,0 @@ -angular.module('cortex.controllers.media.grid', [ - 'ui.router.state', - 'ui.bootstrap', - 'placeholders.img', - 'angular-flash.service', - 'cortex.settings', - 'cortex.services.cortex', - 'cortex.services.postBodyEditor', - 'cortex.services.postsPopup', - 'cortex.directives.delayedInput', - 'cortex.filters' -]) - - .controller('MediaGridCtrl', function ($scope, $state, $stateParams, $window, cortex, settings, - mediaSelectType, flash, PostBodyEditorService, - PostsPopupService) { - - $scope.data = {}; - - var updatePage = function (newPage) { - $state.go('.', {page: newPage || $scope.page.page, perPage: $scope.page.perPage, query: $scope.page.query}); - }; - - $scope.page = { - query: $stateParams.query, - page: parseInt($stateParams.page) || 1, - perPage: parseInt($stateParams.perPage) || settings.paging.defaultPerPage, - next: function () { - $scope.page.page++; - updatePage(); - }, - previous: function () { - $scope.page.page--; - updatePage(); - }, - flip: function (page) { - $scope.page.page = page; - updatePage(); - } - }; - - $scope.$watch('page.query', function () { - updatePage(1); - }); - - $scope.$watch('page.perPage', function () { - updatePage(); - }); - - $scope.data.media = cortex.media.searchPaged({ - q: $scope.page.query, - per_page: $scope.page.perPage, - page: $scope.page.page - }, - function (media, headers, paging) { - $scope.data.paging = paging; - }); - - $scope.deleteMedia = function (media) { - if ($window.confirm('Are you sure you want to delete "' + media.name + '?"')) { - cortex.media.delete({id: media.id}, function () { - $scope.data.media = _.reject($scope.data.media, function (m) { - return m.id == media.id; - }); - flash.warn = media.name + " deleted."; - }, function (res) { - flash.error = media.name + " could not be deleted: " + res.data.message; - }); - } - }; - - $scope.selectMedia = function (media) { - if (PostBodyEditorService.mediaSelectType === mediaSelectType.ADD_MEDIA) { - PostBodyEditorService.addMediaToPost(media); - } - else if (PostBodyEditorService.mediaSelectType === mediaSelectType.SET_TILE) { - PostBodyEditorService.media.tile = media; - } - else if (PostBodyEditorService.mediaSelectType === mediaSelectType.SET_FEATURED) { - PostBodyEditorService.media.featured = media; - } - else { - throw 'No mediaSelectType set!'; - } - - PostsPopupService.popupOpen = false; - }; - - $scope.searchMedia = function (keyword) { - $scope.page.query = keyword; - } - }); diff --git a/app/assets/javascripts/legacy/controllers/organizations/manage.js b/app/assets/javascripts/legacy/controllers/organizations/manage.js deleted file mode 100644 index ac852c88c..000000000 --- a/app/assets/javascripts/legacy/controllers/organizations/manage.js +++ /dev/null @@ -1,37 +0,0 @@ -angular.module('cortex.controllers.organizations.manage', [ - 'ui.router.state', - 'angular-flash.service', - 'angular-flash.flash-alert-directive', - 'cortex.services.cortex', - 'cortex.settings' -]) - -.controller('OrganizationsManageCtrl', function($scope, $stateParams, $state, flash, events, cortex, TenantsTreeStatus) { - // Open tenant hierarchy and details panels if an organization is selected - if ($stateParams.organizationId && !$state.includes('cortex.organizations.manage.tenants')) { - $state.go('.tenants'); - } - - $scope.tenantsTreeStatus = TenantsTreeStatus; - - $scope.deleteTenant = function(tenant){ - if (confirm('Are you sure you want to delete "' + tenant.name + '"?')) { - cortex.tenants.delete({id: tenant.id}, function(data) { - var message; - - if (tenant.parent_id) { - $scope.$broadcast(events.TENANT_HIERARCHY_CHANGE); - message = '"' + tenant.name + '" tenant was deleted successfully'; - } - else { - $scope.$emit(events.ORGANIZATIONS_CHANGE); - message = '"' + tenant.name + '" organization was deleted successfully'; - - // Go to org manage if an org tenant was deleted - $state.go('cortex.organizations.manage'); - } - flash.warn = message; - }); - } - }; -}); diff --git a/app/assets/javascripts/legacy/controllers/organizations/organizations.js b/app/assets/javascripts/legacy/controllers/organizations/organizations.js deleted file mode 100644 index 3cfaf812b..000000000 --- a/app/assets/javascripts/legacy/controllers/organizations/organizations.js +++ /dev/null @@ -1,22 +0,0 @@ -angular.module('cortex.controllers.organizations', [ - 'ui.router.state', - 'cortex.settings' -]) - -.controller('OrganizationsCtrl', function ($scope, $stateParams, $state, events, organizations) { - - $scope.data = { - organizations: organizations - }; - - var orgId = $stateParams.organizationId; - if (orgId) { - $scope.data.organization = _.find(organizations, function(o){ - return o.id == orgId; - }); - } - - $scope.$on(events.ORGANIZATIONS_CHANGE, function (event) { - loadOrganizations(); - }); -}); diff --git a/app/assets/javascripts/legacy/controllers/posts/edit.classify.js b/app/assets/javascripts/legacy/controllers/posts/edit.classify.js deleted file mode 100644 index fb945d7a4..000000000 --- a/app/assets/javascripts/legacy/controllers/posts/edit.classify.js +++ /dev/null @@ -1,34 +0,0 @@ -angular.module('cortex.controllers.posts.edit.classify', [ - 'ngTagsInput', - 'cortex.directives.modalShow', - 'cortex.services.cortex' -]) - -.controller('PostsEditClassifyCtrl', function($scope, _, cortex) { - $scope.loadTags = function (search) { - return cortex.posts.tags({s: search}).$promise; - }; - - $scope.data.popularTags = cortex.posts.tags({popular: true}); - - // Adds a tag to tag_list if it doesn't already exist in array - $scope.addTag = function(tag) { - if (_.some($scope.data.post.tag_list, function(t) { return t.name == tag.name; })) { - return; - } - $scope.data.post.tag_list.push({name: tag.name, id: tag.id}); - }; - - $scope.$watch('data.post.job_phase', function(phase) { - if (phase === undefined) { - $scope.data.jobPhaseCategories = []; - return; - } - - var jobPhaseCategory = _.find($scope.data.categoriesHierarchy, function(category) { - return category.name == phase; - }); - - $scope.data.jobPhaseCategories = jobPhaseCategory.children; - }); -}); diff --git a/app/assets/javascripts/legacy/controllers/posts/edit.display.js b/app/assets/javascripts/legacy/controllers/posts/edit.display.js deleted file mode 100644 index 84922b48e..000000000 --- a/app/assets/javascripts/legacy/controllers/posts/edit.display.js +++ /dev/null @@ -1,67 +0,0 @@ -angular.module('cortex.controllers.posts.edit.display', [ - 'cortex.filters', - 'cortex.settings', - 'cortex.services.mediaConstraints', - 'cortex.services.postBodyEditor', - 'cortex.services.postsPopup' -]) - -.controller('PostsEditDisplayCtrl', function($scope, $state, - AddMediaService, mediaSelectType, PostBodyEditorService, PostsPopupService, - featuredMediaConstraintsService, tileMediaConstraintsService) { - $scope.postBodyEditorService = PostBodyEditorService; - $scope.postBodyEditorService.media.featured = $scope.data.post.featured_media; - $scope.postBodyEditorService.media.tile = $scope.data.post.tile_media; - - $scope.media = { - setFeatured: function () { - AddMediaService.setMedia(mediaSelectType.SET_FEATURED, 'Set Featured Media from Media Library'); - }, - removeFeatured: function () { - $scope.data.post.featured_media = {}; - $scope.data.post.featured_media_id = null; - $scope.data.featured_media_too_small = false; - }, - setTile: function () { - AddMediaService.setMedia(mediaSelectType.SET_TILE, 'Set Tile Media from Media Library'); - }, - removeTile: function () { - $scope.data.post.tile_media = {}; - $scope.data.post.tile_media_id = null; - $scope.data.tile_media_too_small = false; - } - }; - - $scope.$watch('postBodyEditorService.media.featured', function (media) { - if (media) { - $scope.data.post.featured_media = media; - $scope.data.post.featured_media_id = media.id; - $scope.data.post.featured_media_warnings = []; - if (!featuredMediaConstraintsService.width(media)) { - if (featuredMediaConstraintsService.totalSize(media)) { - $scope.data.post.featured_media_warnings.push("Warning! Your featured media might appear stretched, as it is smaller than the featured image slot. Try an image at least 1100x600 ") - } - else { - $scope.data.post.featured_media_warnings.push("Warning! Your featured media might appear stretched, as it is smaller than our recommended width of 1100px.") - } - } - if (!featuredMediaConstraintsService.aspectratio(media)) { - $scope.data.post.featured_media_warnings.push("Warning! Your featured media might appear, as it does not match our recommended aspect ratio. Try 16:9"); - } - } - }); - - $scope.$watch('postBodyEditorService.media.tile', function (media) { - if (media) { - $scope.data.post.tile_media = media; - $scope.data.post.tile_media_id = media.id; - $scope.data.post.tile_media_warnings = []; - if (!tileMediaConstraintsService.width(media)) { - $scope.data.post.tile_media_warnings.push("Warning! Your tile media might appear stretched, as it is smaller than our recommended width of 375."); - } - if (!tileMediaConstraintsService.aspectratio(media)) { - $scope.data.post.tile_media_warnings.push("Warning! Your tile media might not display properly, as it does not match our recommended aspect ratio. Try 1:1"); - } - } - }); -}); diff --git a/app/assets/javascripts/legacy/controllers/posts/edit.info.js b/app/assets/javascripts/legacy/controllers/posts/edit.info.js deleted file mode 100644 index 61d8b3b8f..000000000 --- a/app/assets/javascripts/legacy/controllers/posts/edit.info.js +++ /dev/null @@ -1,62 +0,0 @@ -angular.module('cortex.controllers.posts.edit.info', [ - 'cortex.services.cortex', - 'cortex.filters', - 'cortex.util', - 'cortex.directives.showErrors' -]) - -.controller('PostsEditInfoCtrl', function($scope, $filter, cortex, delayedBind, currentUser) { - // Set Slug dirty on form load if it's already been changed from the default - if ($scope.data.post.slug && $scope.data.post.slug !== $filter('slugify')($scope.data.post.title)) { - $scope.$on('$viewContentLoaded', function () { - $scope.postForm.slug.$dirty = true; - }); - } - - // Auto-generate slug when title changed and field isn't dirty - $scope.$watch('data.post.title', function(title) { - var slug = $filter('slugify')(title), - slugOverridden = $scope.postForm.slug.$dirty && $scope.postForm.slug; - - if (slugOverridden) { - return; - } - - $scope.data.post.slug = slug; - }); - - $scope.$watch('data.authorIsUser', function(authorIsUser) { - if (authorIsUser) { - $scope.data.post.custom_author = currentUser.firstname + ' ' + currentUser.lastname; - } - }); - - function slugCheck() { - var slug = $scope.data.post.slug; - if (!slug || !postForm.slug) { - return; - } - - cortex.posts.get({id: slug}, - // Slug already used - function(post) { - - // A post may have its own slug - if (post.id === $scope.data.post.id) { - $scope.postForm.slug.$setValidity('unavailable', true); - $scope.data.postWithDuplicateSlug = null; - } - else { - $scope.postForm.slug.$setValidity('unavailable', false); - $scope.data.postWithDuplicateSlug = post; - } - }, - // Slug unused - function() { - $scope.postForm.slug.$setValidity('unavailable', true); - $scope.data.postWithDuplicateSlug = null; - } - ); - } - delayedBind($scope, 'data.post.slug', 1000, slugCheck); -}); diff --git a/app/assets/javascripts/legacy/controllers/posts/edit.js b/app/assets/javascripts/legacy/controllers/posts/edit.js deleted file mode 100644 index 18cbaa1bf..000000000 --- a/app/assets/javascripts/legacy/controllers/posts/edit.js +++ /dev/null @@ -1,100 +0,0 @@ -angular.module('cortex.controllers.posts.edit', [ - 'ui.router.state', - 'ui.bootstrap.dropdown', - 'ui.bootstrap.buttons', - 'ui.bootstrap.datepicker', - 'ui.bootstrap.datetimepicker', - 'angular-flash.service', - 'angular-redactor', - 'cortex.vendor.underscore', - 'cortex.services.addMedia', - 'cortex.services.imageFit' -]) - -.controller('PostsEditCtrl', function($scope, $state, $timeout, flash, _, - post, filters, currentUserAuthor, categoriesHierarchy, AddMediaService, ImageFitService) { - $scope.data = { - savePost: function() { - $scope.$broadcast('validateShowErrors'); - if ($scope.postForm.$invalid) { - return; - } - $scope.data.post.category_ids = []; - angular.forEach($scope.data.post.postCategories, function(value, key) { - if (value) { - this.push(key); - } - }, $scope.data.post.category_ids); - $scope.data.post.primary_category_id = $scope.data.post.category_ids[0]; - $scope.data.post.industry_ids = [$scope.data.post.primary_industry_id]; - $scope.data.post.tag_list = $scope.data.post.tag_list.map(function(tag) { return tag.name; }); - $scope.data.post.seo_keyword_list = $scope.data.post.seo_keyword_list.map(function(seo_keyword) { return seo_keyword.name; }); - - if ($scope.data.authorIsUser) { - $scope.data.post.custom_author = null; - $scope.data.post.author_id = currentUserAuthor.id; - } else { - $scope.data.post.author_id = null; - } - - $scope.data.post.$save(function(post) { - flash.success = 'Saved "' + post.title + '"'; - $state.go('^.^.^.manage.components'); - }); - }, - cancel: function() { - $state.go('^.^.^.manage.components'); - }, - phases: _.map(filters.job_phases, function(job_phase) { - return job_phase.name; - }), - industries: filters.industries - }; - - AddMediaService.initRedactorMediaPlugin(); - ImageFitService.initRedactorImageFitPlugin(); - - $scope.redactorOptions = { - plugins: ['media', 'imageFit', 'inlinestyle'], - minHeight: 800, - buttonSource: true, - deniedTags: ['html', 'head', 'link', 'body', 'applet'] // Allow script, style - }; - - $scope.isAuthorUser = function(post) { - if (!post.id || post.author) { - return true; - } - else { - return false; - } - }; - - $scope.data.authorIsUser = $scope.isAuthorUser(post); - - if ($state.includes('cortex.posts.*.sections.article')) { - post.type = 'ArticlePost'; - } - else if ($state.includes('cortex.posts.*.sections.video')) { - post.type = 'VideoPost' - } - else if ($state.includes('cortex.posts.*.sections.infographic')) { - post.type = 'InfographicPost' - } - else if ($state.includes('cortex.posts.*.sections.promo')) { - post.type = 'PromoPost' - } - - $scope.data.post = post; - $scope.data.categoriesHierarchy = categoriesHierarchy; - - $scope.datepicker = { - expireAtOpen: false, - publishAtOpen: false, - open: function(datepicker) { - $timeout(function(){ - $scope.datepicker[datepicker] = true; - }); - } - }; -}); diff --git a/app/assets/javascripts/legacy/controllers/posts/edit.seo.js b/app/assets/javascripts/legacy/controllers/posts/edit.seo.js deleted file mode 100644 index 5c7407e61..000000000 --- a/app/assets/javascripts/legacy/controllers/posts/edit.seo.js +++ /dev/null @@ -1,22 +0,0 @@ -angular.module('cortex.controllers.posts.edit.seo', [ - 'cortex.services.cortex', - 'cortex.filters' -]) - -.controller('PostsEditSeoCtrl', function($scope, $filter) { - // SEO Title should be pulled from the post title, unless it's been edited. - $scope.$watch('data.post.title', function(description) { - if ($scope.postForm.seo_title.$dirty && $scope.postForm.seo_title) { - return; - } - $scope.data.post.seo_title = $scope.data.post.title; - }); - - // Ditto SEO Description - $scope.$watch('data.post.short_description', function(description) { - if ($scope.postForm.seo_description.$dirty && $scope.postForm.seo_description) { - return; - } - $scope.data.post.seo_description = $scope.data.post.short_description; - }); -}); diff --git a/app/assets/javascripts/legacy/controllers/posts/grid.js b/app/assets/javascripts/legacy/controllers/posts/grid.js deleted file mode 100644 index 92b494c11..000000000 --- a/app/assets/javascripts/legacy/controllers/posts/grid.js +++ /dev/null @@ -1,39 +0,0 @@ -angular.module('cortex.controllers.posts.grid', [ - 'ngTable', - 'ui.bootstrap', - 'cortex.services.cortex', - 'cortex.filters' -]) - -.controller('PostsGridCtrl', function($scope, ngTableParams, cortex) { - $scope.data = { - totalServerItems: 0, - posts: [], - query: null - }; - - $scope.postDataParams = new ngTableParams({ - page: 1, - count: 10, - sorting: { - created_at: 'desc' - } - }, { - total: 0, - getData: function($defer, params) { - cortex.posts.searchPaged({page: params.page(), per_page: params.count(), q: $scope.data.query}, - function(posts, headers, paging) { - params.total(paging.total); - $defer.resolve(posts); - }, - function(data) { - $defer.reject(data); - } - ); - } - }); - - $scope.$watch('data.query', function() { - $scope.postDataParams.reload(); - }); -}); diff --git a/app/assets/javascripts/legacy/controllers/posts/popup.js b/app/assets/javascripts/legacy/controllers/posts/popup.js deleted file mode 100644 index 7b206048b..000000000 --- a/app/assets/javascripts/legacy/controllers/posts/popup.js +++ /dev/null @@ -1,27 +0,0 @@ -angular.module('cortex.controllers.posts.popup', [ - 'ui.router.state', - 'cortex.filters', - 'cortex.services.postsPopup' -]) - -.controller('PostsPopupCtrl', function ($scope, $timeout, $state, $filter, PostsPopupService) { - $scope.postsPopupService = PostsPopupService; - $scope.postsPopupService.popupOpen = true; - - $scope.$watch('postsPopupService.popupOpen', function (popupOpen) { - if (!popupOpen) { - // We are arbitrary levels deep, so we can't transition relative to our current state. - if ($state.includes('cortex.posts.new')) { - // We need to wait long enough for bootstrap-modal to fade away, otherwise we're stuck with a blocked-out page - $timeout(function () { - $state.go($filter('postNewState')($scope.data.post)); - }, 500); - } - else { - $timeout(function () { - $state.go($filter('postEditState')($scope.data.post, false), {postId: $scope.data.post.id}); - }, 500); - } - } - }); -}); diff --git a/app/assets/javascripts/legacy/controllers/tenants/edit.js b/app/assets/javascripts/legacy/controllers/tenants/edit.js deleted file mode 100644 index 48217068b..000000000 --- a/app/assets/javascripts/legacy/controllers/tenants/edit.js +++ /dev/null @@ -1,97 +0,0 @@ -angular.module('cortex.controllers.tenants.edit', [ - 'ui.router.state', - 'ui.bootstrap.datepicker', - 'angular-flash.service', - 'angularBootstrapNavTree', - 'cortex.directives.tenantSettings', - 'cortex.settings', - 'cortex.util' -]) - -.controller('EditTenantsCtrl', function($scope, $stateParams, $state, $timeout, flash, events, cortex, util) { - - // angular-bootstrap datepicker settings - $scope.datepicker = { - format: 'yyyy/MM/dd', - activateAtOpen: false, - deactivateAtOpen: false, - open: function(datepicker) { - $timeout(function(){ - $scope.datepicker[datepicker] = true; - }); - } - }; - - $scope.levelName = $stateParams.organizationId ? 'tenant' : 'organization'; - $scope.creatingOrganization = util.isEmpty($stateParams.organizationId); - - // Fetch the tenant or create a new resource - if ($stateParams.tenantId) { - $scope.data.tenant = cortex.tenants.get({id: $stateParams.tenantId}); - } - else { - $scope.data.tenant = new cortex.tenants(); - } - - $scope.data.tenant.inherit_from_parent = true; - - // Initialize scope.data properties for organization tree and other directives - $scope.data.tenants = - { - hierarchy: [], - flattened: [], - selected: null - }; - - // Fetch organization hierarchy - if ($stateParams.organizationId) { - cortex.tenants.get({id: $stateParams.organizationId, include_children: true}, function(hierarchy) { - $scope.data.tenants.hierarchy = [hierarchy]; - }); - } - - $scope.creatingTenant = util.isEmpty($stateParams.tenantId); - - $scope.selectParent = function(tenant){ - $scope.data.tenants.selected = tenant; - $scope.data.tenant.parent_id = tenant.id; - }; - - $scope.save = function() { - var tenantIsNew = !$scope.data.tenant.id; - var tenantIsOrg = !$scope.data.tenant.parent_id; - - $scope.data.tenant.$save(function(tenant) { - - var message; - if ($scope.creatingOrganization) { - $scope.$emit(events.ORGANIZATIONS_CHANGE); - - if (tenantIsNew) { - message = 'Created new organization "' + tenant.name + '"'; - $state.go('.', {tenantId: tenant.id}); - } - else { - message = 'Saved organization "' + tenant.name + '"'; - } - } - else { - if (tenantIsNew) { - message = 'Created new tenant "' + tenant.name + '" under "' + $scope.data.tenants.selected.name + '"' ; - $state.go('.', {tenantId: tenant.id, organizationId: $stateParams.organizationId}); - } - else { - if (tenantIsOrg) { - message = 'Saved organization "' + tenant.name + '"'; - $scope.$emit(events.ORGANIZATIONS_CHANGE); - } - else { - message = 'Saved tenant "' + tenant.name + '"'; - } - } - } - - flash.success = message; - }); - }; -}); diff --git a/app/assets/javascripts/legacy/controllers/tenants/manage.js b/app/assets/javascripts/legacy/controllers/tenants/manage.js deleted file mode 100644 index 0e752f99a..000000000 --- a/app/assets/javascripts/legacy/controllers/tenants/manage.js +++ /dev/null @@ -1,54 +0,0 @@ -angular.module('cortex.controllers.tenants.manage', [ - 'ui.router.state', - 'cortex.vendor.underscore', - 'cortex.services.cortex', - 'cortex.directives.tenantSettings', - 'angularBootstrapNavTree', - 'ngAnimate', - 'cortex.settings', - 'cortex.util' - ]) - -.factory('TenantsTreeStatus', function () { - return { - isLoaded: false - }; -}) - -.controller('TenantsTreeCtrl', function($scope, $stateParams, events, cortex, hierarchyUtils, TenantsTreeStatus, _) { - - var loadTenantHierarchy = function() { - TenantsTreeStatus.isLoaded = false; - - cortex.tenants.get({id: $stateParams.organizationId, include_children: true}, function(hierarchy){ - $scope.data.tenants.hierarchy = [hierarchy]; - var flattened = hierarchyUtils.flattenTenantHierarchy([hierarchy]); - $scope.data.tenants.flattened = flattened; - - // Set $scope.data.tenants.selected if tenantId was specified in URL - var tenantId = $stateParams.tenantId; - if (tenantId) { - $scope.data.tenants.selected = _.find(flattened, function(t) { return t.id == tenantId; }); - } - - TenantsTreeStatus.isLoaded = true; - }); - }; - - $scope.data.tenants = - { - hierarchy: [], - flattened: [], - selected: null - }; - - loadTenantHierarchy(); - - $scope.selectTenant = function(tenant){ - $scope.data.tenants.selected = tenant; - }; - - $scope.$on(events.TENANT_HIERARCHY_CHANGE, function (event) { - loadTenantHierarchy(); - }); -}); diff --git a/app/assets/javascripts/legacy/controllers/users/bulk.js b/app/assets/javascripts/legacy/controllers/users/bulk.js deleted file mode 100644 index 2f6bf6178..000000000 --- a/app/assets/javascripts/legacy/controllers/users/bulk.js +++ /dev/null @@ -1,83 +0,0 @@ -angular.module('cortex.controllers.users.bulk', [ - 'ui.router.state', - 'ui.bootstrap.progressbar', - 'angular-flash.service', - 'angularFileUpload', - 'cortex.settings', - 'cortex.services.cortex', - 'cortex.directives.fileSelector' -]) - - .controller('UsersBulkCtrl', function ($scope, $timeout, $upload, $state, $q, flash, cortex, settings) { - $scope.data = $scope.data || {}; - $scope.data.usersBulk = new cortex.users.bulkJob(); - $scope.data.upload = { - progress: 0 - }; - - function saveBulkJob() { - var d = $q.defer(); - - if (!$scope.data.usersBulk.metadata) { - d.reject('No metadata present.'); - } - else { - var uploadError = false; - var httpConfig = { - url: settings.cortex_base_url + '/users/bulk_job', - method: 'POST', - fields: {bulkJob: $scope.data.usersBulk}, - formDataAppender: function (formData, key, value) { - if (key === 'bulkJob') { - angular.forEach(value, function (v, k) { - formData.append('bulkJob[' + k + ']', v); - }); - } - } - }; - - $scope.data.upload.progress = 1; - $scope.data.upload = $upload.upload(httpConfig) - .then( - function (bulkJob) { //Success - d.resolve(); - }, - function (error, status) { //Error - uploadError = true; - $scope.data.upload.progress = 0; - $scope.data.upload.file = null; - - if (status === 422) { - d.reject('Selected file type is not supported. Please choose a different file.'); - } - else { - d.reject('Unhandled error: ' + error.data.errors[0]); - } - }, - function (e) { //Progress - if (uploadError) { - return; - } - $scope.data.upload.progress = parseInt(100.0 * e.loaded / e.total); - } - ); - } - - return d.promise; - } - - $scope.saveUsersBulk = function () { - saveBulkJob().then( - function () { - flash.success = 'Bulk job created'; - $state.go('cortex.bulk_jobs.manage'); - }, - function (error) { - flash.error = error; - }); - }; - - $scope.cancel = function () { - $state.go('^.manage.components'); - }; - }); diff --git a/app/assets/javascripts/legacy/controllers/users/edit.js b/app/assets/javascripts/legacy/controllers/users/edit.js deleted file mode 100644 index d1131b8e6..000000000 --- a/app/assets/javascripts/legacy/controllers/users/edit.js +++ /dev/null @@ -1,27 +0,0 @@ -angular.module('cortex.controllers.users.edit', [ - 'ui.router.state', - 'angular-flash.service', - 'cortex.controllers.users.facets' -]) - -.controller('UsersEditCtrl', function($scope, $timeout, $state, $anchorScroll, flash, user) { - $scope.data = $scope.data || {}; - $scope.data.user = user; - - $scope.cancel = function () { - $state.go('^.facets.grid'); - }; - - $scope.saveUser = function() { - $scope.data.user.$save().then( - function() { - $state.go('^.facets.grid'); - flash.success = 'Saved user information'; - }, - function(res) { - $anchorScroll(); - flash.error = 'Error while saving user information'; - } - ); - }; -}); diff --git a/app/assets/javascripts/legacy/controllers/users/facets.js b/app/assets/javascripts/legacy/controllers/users/facets.js deleted file mode 100644 index 5b90fc2ba..000000000 --- a/app/assets/javascripts/legacy/controllers/users/facets.js +++ /dev/null @@ -1,26 +0,0 @@ -angular.module('cortex.controllers.users.facets', [ - 'ui.router.state', - 'ngAnimate', - 'angularBootstrapNavTree', - 'cortex.util', - 'cortex.services.cortex', - 'cortex.directives.tenantSettings' -]) - - .factory('TenantTree', function () { - return { - selected: null - }; - }) - - .controller('UsersFacetCtrl', function ($scope, $stateParams, cortex, TenantTree) { - $scope.data = { - tenants: { - hierarchy: cortex.tenants.hierarchicalIndex() - } - }; - - $scope.selectTenant = function (tenant) { - TenantTree.selected = tenant; - }; - }); diff --git a/app/assets/javascripts/legacy/controllers/users/grid.js b/app/assets/javascripts/legacy/controllers/users/grid.js deleted file mode 100644 index a7a1d20f5..000000000 --- a/app/assets/javascripts/legacy/controllers/users/grid.js +++ /dev/null @@ -1,68 +0,0 @@ -angular.module('cortex.controllers.users.grid', [ - 'ngTable', - 'ui.router.state', - 'ui.bootstrap', - 'angular-flash.service', - 'cortex.services.cortex', - 'cortex.filters', - 'cortex.controllers.users.facets' -]) - - .controller('UsersGridCtrl', function ($scope, $window, $state, ngTableParams, flash, cortex, TenantTree) { - $scope.data = { - totalServerItems: 0, - users: [], - query: null, - tenantTree: TenantTree - }; - - $scope.userDataParams = new ngTableParams({ - page: 1, - count: 10, - sorting: { - created_at: 'desc' - } - }, { - total: 0, - getData: function ($defer, params) { - if ($scope.data.tenantTree.selected) { - cortex.tenants.usersPaged({page: params.page(), per_page: params.count(), id: $scope.data.tenantTree.selected.id, q: $scope.data.query}, - function (users, headers, paging) { - params.total(paging.total); - $defer.resolve(users); - }, - function (data) { - $defer.reject(data); - } - ); - } - } - }); - - $scope.$watch('data.query', function () { - $scope.userDataParams.reload(); - }); - - $scope.$watch('data.tenantTree.selected', function () { - $scope.userDataParams.reload(); - }); - - $scope.editUser = function(user) { - $state.go('^.^.edit', {userId: user.id}); - }; - - $scope.deleteUser = function (user) { - if ($window.confirm('Are you sure you want to delete "' + user.email + '?"')) { - cortex.users.delete({id: user.id}, function () { - flash.warn = user.email + ' deleted.'; - $scope.userDataParams.reload(); - }, function (res) { - if (res.status === 409) { - flash.error = user.email + " is currently assigned to Content or Media and cannot be deleted"; - } else { - flash.error = user.email + " could not be deleted: " + res.data.message; - } - }); - } - }; - }); diff --git a/app/assets/javascripts/legacy/controllers/users/new.js b/app/assets/javascripts/legacy/controllers/users/new.js deleted file mode 100644 index d469172a7..000000000 --- a/app/assets/javascripts/legacy/controllers/users/new.js +++ /dev/null @@ -1,34 +0,0 @@ -angular.module('cortex.controllers.users.new', [ - 'ui.router.state', - 'angular-flash.service', - 'validation.match', - 'cortex.controllers.users.facets' -]) - -.controller('UsersNewCtrl', function($scope, $timeout, $state, $anchorScroll, flash, user, TenantTree) { - $scope.data = $scope.data || {}; - $scope.data.user = user; - $scope.data.selectedTenant = TenantTree.selected; - - $scope.cancel = function () { - $state.go('^.facets.grid'); - }; - - $scope.saveUser = function() { - $scope.data.user.tenant_id = $scope.data.selectedTenant.id; - $scope.data.user.$save().then( - function() { - $state.go('^.facets.grid'); - flash.success = 'Saved user information'; - }, - function(res) { - $anchorScroll(); - if (res.status === 403) { - flash.error = "Chosen password is invalid"; - } else { - flash.error = 'Error while saving user information'; - } - } - ); - }; -}); diff --git a/app/assets/javascripts/legacy/controllers/users/profile.js b/app/assets/javascripts/legacy/controllers/users/profile.js deleted file mode 100644 index 7d1bedc0f..000000000 --- a/app/assets/javascripts/legacy/controllers/users/profile.js +++ /dev/null @@ -1,41 +0,0 @@ -angular.module('cortex.controllers.users.profile', [ - 'ui.router.state', - 'angular-flash.service' -]) - -.controller('UsersProfileCtrl', function($scope, $timeout, $state, $anchorScroll, flash, user, author) { - $scope.data = $scope.data || {}; - $scope.data.user = user; - $scope.data.author = author; - - $scope.saveAuthor = function() { - $scope.data.author.$save().then( - function() { - $anchorScroll(); - flash.info = 'Saved author information'; - }, - function() { - $anchorScroll(); - flash.error = 'Error while saving author information'; - } - ); - }; - $scope.changePassword = function() { - $scope.data.user.$save().then( - function() { - flash.success = "Successfully updated password, redirecting to login page in 5 seconds..."; - $timeout(function () { $state.go('login') }, 5000); - }, - function(res) { - $anchorScroll(); - if (res.status === 403) { - flash.error = "Current password is invalid"; - } else if (res.data.errors[0] === "password_confirmation doesn't match Password") { - flash.error = "Passwords don't match."; - } else { - flash.error = "Could not change password, please try again'"; - } - } - ); - }; -}); diff --git a/app/assets/javascripts/legacy/controllers/webpages/edit.js b/app/assets/javascripts/legacy/controllers/webpages/edit.js deleted file mode 100644 index 367d907ae..000000000 --- a/app/assets/javascripts/legacy/controllers/webpages/edit.js +++ /dev/null @@ -1,87 +0,0 @@ -angular.module('cortex.controllers.webpages.edit', [ - 'ui.router.state', - 'angular-flash.service', - 'cortex.services.cortex', - 'cortex.filters' - ]) - - .controller('WebpagesEditCtrl', function ($scope, $window, $document, $state, $stateParams, $anchorScroll, flash, cortex) { - $scope.data = $scope.data || {}; - $scope.data.webpage = cortex.webpages.get({id: $stateParams.webpageId}); - - var frameEventListener = function (event) { - switch (event.data.event) { - case 'cancel_editor': - cancel(); - break; - case 'save_webpage': - saveWebpage(event.data.webpage); - break; - case 'get_medias': - getMedias(event.data.page).$promise.then(function (media) { - sendFrameMessage({event: 'medias_data', medias: media}); - }); - break; - } - }; - - $window.addEventListener('message', frameEventListener, false); - $scope.$on("$destroy", function(){ - $window.removeEventListener('message', frameEventListener, false); - }); - - // Perhaps this should moved to a directive! - var sendFrameMessage = function (data) { - document.getElementById('webpage-frame').contentWindow.postMessage(JSON.parse(JSON.stringify(data)), '*'); - }; - - var cancel = function () { - $state.go('^.manage'); - }; - - var saveWebpage = function (webpage) { - delete $scope.data.webpage.snippets; - - var snippets_attributes = []; - _.each(webpage.snippets, function (value) { - snippets_attributes.push({ - id: value.id, - document_attributes: value.document - }); - }); - - $scope.data.webpage.snippets_attributes = snippets_attributes; - $scope.data.webpage.seo_keyword_list = $scope.data.webpage.seo_keyword_list.map(function(seo_keyword) { return seo_keyword.name; }); - $scope.data.webpage.$save().then( - function () { - $anchorScroll(); - flash.success = 'Saved Webpage information'; - $state.go('^.manage'); - }, - function () { - $anchorScroll(); - flash.error = 'Error while saving Webpage information'; - } - ); - }; - - var getMedias = function (page) { - return cortex.media.searchPaged({ - q: page.query, - per_page: page.perPage, - page: page.page - }); - } - - $scope.appendEditingParamsToUrl = function(url) { - var urlHasParams = _.includes(url, '?'); - - if (urlHasParams) { - url = url + '&editing_mode=1&disable_redirects=1'; - } else { - url = url + '?editing_mode=1&disable_redirects=1'; - } - - return url; - } - }); diff --git a/app/assets/javascripts/legacy/controllers/webpages/grid.js b/app/assets/javascripts/legacy/controllers/webpages/grid.js deleted file mode 100644 index 9e8b3f707..000000000 --- a/app/assets/javascripts/legacy/controllers/webpages/grid.js +++ /dev/null @@ -1,66 +0,0 @@ -angular.module('cortex.controllers.webpages.grid', [ - 'ngTable', - 'ui.bootstrap', - 'ui.router.state', - 'angular-flash.service', - 'cortex.services.cortex' -]) - - .controller('WebpagesGridCtrl', function ($scope, $window, $state, ngTableParams, cortex, flash) { - $scope.data = { - totalServerItems: 0, - webpages: [], - query: null - }; - - $scope.webpageDataParams = new ngTableParams({ - page: 1, - count: 10, - sorting: { - created_at: 'desc' - } - }, { - total: 0, - getData: function ($defer, params) { - cortex.webpages.searchPaged({page: params.page(), per_page: params.count(), q: $scope.data.query}, - function (webpages, headers, paging) { - params.total(paging.total); - $defer.resolve(webpages); - }, - function (data) { - $defer.reject(data); - } - ); - } - }); - - $scope.searchWebpages = function(event) { - if (event.which == 13) { - $scope.webpageDataParams.reload(); - } - - event.preventDefault(); - }; - - $scope.newWebpage = function () { - $state.go('^.new'); - }; - - $scope.editWebpage = function (webpage) { - $state.go('^.edit', {webpageId: webpage.id}); - }; - - $scope.deleteWebpage = function (webpage) { - if ($window.confirm('Are you sure you want to delete "' + webpage.name + '" with URL "' + webpage.url + '", and all associated Snippets/Documents?"')) { - cortex.webpages.delete({id: webpage.id}, function () { - $scope.data.webpages = _.reject($scope.data.webpages, function (w) { - return w.id == webpage.id; - }); - flash.warn = webpage.name + " deleted."; - $scope.webpageDataParams.reload(); - }, function (res) { - flash.error = webpage.name + " could not be deleted: " + res.data.message; - }); - } - }; - }); diff --git a/app/assets/javascripts/legacy/controllers/webpages/new.js b/app/assets/javascripts/legacy/controllers/webpages/new.js deleted file mode 100644 index 4d82adc4b..000000000 --- a/app/assets/javascripts/legacy/controllers/webpages/new.js +++ /dev/null @@ -1,26 +0,0 @@ -angular.module('cortex.controllers.webpages.new', [ - 'ui.router.state', - 'angular-flash.service', - 'cortex.services.cortex' -]) - -.controller('WebpagesNewCtrl', function ($scope, $state, $stateParams, flash, cortex) { - $scope.data = $scope.data || {}; - $scope.data.webpage = new cortex.webpages(); - - $scope.cancel = function () { - $state.go('^.manage'); - }; - - $scope.saveWebpage = function () { - $scope.data.webpage.$save().then( - function () { - flash.success = 'Saved webpage information'; - $state.go('^.manage'); - }, - function () { - flash.error = 'Error while saving webpage information'; - } - ); - }; -}); diff --git a/app/assets/javascripts/legacy/cortex.js b/app/assets/javascripts/legacy/cortex.js deleted file mode 100644 index 136d9c953..000000000 --- a/app/assets/javascripts/legacy/cortex.js +++ /dev/null @@ -1,84 +0,0 @@ -angular.module('cortex', [ - // Libraries/Vendor - 'ui.router', - 'ui.router.state', - 'angular-flash.service', - 'angular-flash.flash-alert-directive', - 'ncy-angular-breadcrumb', - 'ng-rails-csrf', - 'toggle-switch', - 'ngSanitize', - - // Cortex - 'cortex.states', - 'cortex.session', - 'cortex.vendor.moment' -]) - -.config(function ($provide, $urlRouterProvider, $httpProvider, flashProvider) { - var copy = angular.copy; - - $provide.constant('currentUser', copy(window.gon.current_user)); - $provide.constant('settings', copy(window.gon.settings)); - - $urlRouterProvider.when('/media/', '/media///'); - - $urlRouterProvider.otherwise(function($injector) { - var $state = $injector.get('$state'); - - if ($injector.get('currentUser')) { - if ($injector.get('currentUser').admin) { - $state.go('cortex.organizations.manage') - } - else { - $state.go('cortex.media.manage.components') - } - } - else { - $state.go('login'); - } - }); - - // Override the default Accept header value of 'application/json, text/plain, */*' - // as "*/*" invalidates all specificity. - // https://github.com/rails/rails/issues/9940 - // http://blog.bigbinary.com/2010/11/23/mime-type-resolution-in-rails.html - $httpProvider.defaults.headers.common['Accept'] = 'application/json, text/plain'; - - // Add Bootstrap classes to flash element - flashProvider.warnClassnames.push('alert-warning'); - flashProvider.infoClassnames.push('alert-info'); - flashProvider.successClassnames.push('alert-success'); - flashProvider.errorClassnames.push('alert-danger'); -}) - -// CortexAdminCtrl -// --------------- -// Cortex's root-level application controller -.controller('CortexCtrl', function ($rootScope, $scope, $state, $stateParams, $http, $window, currentUser, moment) { - var isDefined = angular.isDefined; - // Add $state and $stateParams to root scope for universal access within views - $rootScope.$state = $state; - $rootScope.$stateParams = $stateParams; - $rootScope.currentUser = currentUser; - $rootScope.moment = moment; - - $scope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) { - if (isDefined(toState.data) && isDefined(toState.data.pageTitle)) { - $scope.pageTitle = toState.data.pageTitle + " | Cortex"; - } - }); - - // Push page views google analytics, if available - if ($window._gaq) { - $scope.$on('$viewContentLoaded', function(event) { - $window._gaq.push(['_trackPageview', $location.path()]); - }); - } - - $rootScope.logout = function() { - $http.delete('/users/sign_out.json').success(function() { - $window.location.href = "/"; - }); - }; -}); diff --git a/app/assets/javascripts/legacy/directives/delayed-input.js b/app/assets/javascripts/legacy/directives/delayed-input.js deleted file mode 100644 index 2fcb8e4b7..000000000 --- a/app/assets/javascripts/legacy/directives/delayed-input.js +++ /dev/null @@ -1,28 +0,0 @@ -angular.module('cortex.directives.delayedInput', []) - -.directive('delayedInput', function($timeout) { - return { - restrict: 'E', - require: 'ngModel', - template: '', - scope: { - delay: '@', - placeholder: '@', - class: '@', - value: '=ngModel', - change: '&ngChange' - }, - link: function(scope, elem, attr, ctrl) { - scope.pendingValue = scope.value; - elem.removeClass(scope.class); - - scope.pendingChange = function() { - if (scope.pending) { $timeout.cancel(scope.pending); } - scope.pending = $timeout(function() { - scope.value = scope.pendingValue; - ctrl.$setViewValue(scope.value); - }, parseInt(scope.delay)); - }; - } - }; -}); diff --git a/app/assets/javascripts/legacy/directives/file-selector.js b/app/assets/javascripts/legacy/directives/file-selector.js deleted file mode 100644 index 7f27001cc..000000000 --- a/app/assets/javascripts/legacy/directives/file-selector.js +++ /dev/null @@ -1,46 +0,0 @@ -angular.module('cortex.directives.fileSelector', [ - 'angularFileUpload' -]) - -.directive('fileSelector', function() { - return { - restrict: 'E', - require: '^ngModel', - templateUrl: 'directives/file-selector-tpl.html', - scope: { - 'ngModel': '=', - 'multiple': '=' - }, - link: function(scope, element) { - // The file input is required to trigger an open file dialog (OFD) - var fileInput = element.find('input[type="file"]'); - var multiple = scope.multiple; - - // Allow multiple file selection - if (multiple) { - fileInput.attr('multiple', ''); - } - - scope.selectFiles = function(files) { - if (multiple) { - scope.ngModel = files; - scope.files = files; - } - else { - scope.ngModel = files[0]; - scope.files = [files[0]]; - } - }; - - // Trigger OFD - scope.browseForFiles = function() { - fileInput.click(); - }; - - scope.remove = function(file) { - scope.files.splice(scope.files.indexOf(file), 1); - scope.ngModel = scope.files; - }; - } - }; -}); diff --git a/app/assets/javascripts/legacy/directives/modal-show.js b/app/assets/javascripts/legacy/directives/modal-show.js deleted file mode 100644 index 2bf46b6a2..000000000 --- a/app/assets/javascripts/legacy/directives/modal-show.js +++ /dev/null @@ -1,36 +0,0 @@ -angular.module('cortex.directives.modalShow', []) - -.directive("modalShow", function () { - return { - restrict: "A", - scope: { - modalVisible: "=" - }, - link: function (scope, element, attrs) { - scope.showModal = function (visible) { - if (visible) { - element.modal("show"); - } - else { - element.modal("hide"); - } - }; - - if (!attrs.modalVisible) { - scope.showModal(true); - } - else { - scope.$watch("modalVisible", function (newValue, oldValue) { - scope.showModal(newValue); - }); - - element.bind("hide.bs.modal", function () { - scope.modalVisible = false; - if (!scope.$$phase && !scope.$root.$$phase) { - scope.$apply(); - } - }); - } - } - }; -}); diff --git a/app/assets/javascripts/legacy/directives/show-errors.js b/app/assets/javascripts/legacy/directives/show-errors.js deleted file mode 100644 index 092ae494f..000000000 --- a/app/assets/javascripts/legacy/directives/show-errors.js +++ /dev/null @@ -1,52 +0,0 @@ -angular.module('cortex.directives.showErrors', []) - -.factory('errorCounter', function() { - return {} -}) - -.directive('showErrors', function (errorCounter, $rootScope) { - return { - restrict: 'A', - require: '^form', - link: function (scope, el, attrs, formCtrl) { - var inputEl = el[0].querySelector("[name]"); - var inputNgEl = angular.element(inputEl); - var inputName = inputNgEl.attr('name'); - - var toggleErrors = function() { - var invalid = formCtrl[inputName].$invalid; - el.toggleClass('has-error', invalid); - var parentSelector = attrs['parentSelector']; - if (parentSelector) { - var errors = errorCounter[parentSelector] || {}; - if (invalid) { - errors[inputName] = true; - } - else if (!invalid) { - delete errors[inputName]; - } - errorCounter[parentSelector] = errors; - } - $rootScope.$broadcast('errorCountChange'); - }; - - inputNgEl.on('blur select change', toggleErrors); - scope.$on('validateShowErrors', toggleErrors); - } - } -}) -.directive('tabErrors', function(errorCounter) { - return { - restrict: 'A', - link: function(scope, el, attrs) { - scope.$on('errorCountChange', function() { - var name = attrs.selectorName; - var obj = errorCounter[name]; - if (typeof obj === 'object') { - var count = Object.keys(obj).length; - el.toggleClass('has-error', count > 0); - } - }); - } - } -}); \ No newline at end of file diff --git a/app/assets/javascripts/legacy/directives/tenant-settings.js b/app/assets/javascripts/legacy/directives/tenant-settings.js deleted file mode 100644 index 1daf3aafe..000000000 --- a/app/assets/javascripts/legacy/directives/tenant-settings.js +++ /dev/null @@ -1,8 +0,0 @@ -angular.module('cortex.directives.tenantSettings', []) - -.directive('tenantSettings', function() { - return { - restrict: 'EA', - templateUrl: 'directives/tenant-settings-tpl.html' - }; -}); \ No newline at end of file diff --git a/app/assets/javascripts/legacy/directives/youtube-selector.js b/app/assets/javascripts/legacy/directives/youtube-selector.js deleted file mode 100644 index 17eb10b8b..000000000 --- a/app/assets/javascripts/legacy/directives/youtube-selector.js +++ /dev/null @@ -1,48 +0,0 @@ -function youtubeIdFromUrl(url) { - var match = url.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/); - return match && match[2].length == 11 ? match[2] : null; -}; - -angular.module('cortex.directives.youtubeSelector', [ -]) - -// http://stackoverflow.com/questions/20447867/create-a-youtube-angularjs-directive -.directive('youtube', function($sce) { - return { - restrict: 'EA', - scope: { code: '=' }, - replace: true, - template: '
', - link: function (scope) { - scope.$watch('code', function (newVal) { - if (newVal) { - scope.url = $sce.trustAsResourceUrl("http://www.youtube.com/embed/" + newVal); - } - }); - } - }; -}) - -.controller('YoutubeSelectorCtrl', function($scope) { - $scope.$watch('youtubeLink', function() { - - if (!$scope.youtubeLink) { - $scope.ngModel = null; - return; - } - - $scope.ngModel = youtubeIdFromUrl($scope.youtubeLink); - }); -}) - -.directive('youtubeSelector', function() { - return { - restrict: 'E', - require: '^ngModel', - templateUrl: 'directives/youtube-selector-tpl.html', - controller: 'YoutubeSelectorCtrl', - scope: { - 'ngModel': '=' - } - }; -}); diff --git a/app/assets/javascripts/legacy/filters.js b/app/assets/javascripts/legacy/filters.js deleted file mode 100644 index 6c557fdf8..000000000 --- a/app/assets/javascripts/legacy/filters.js +++ /dev/null @@ -1,117 +0,0 @@ -angular.module('cortex.filters', [ - 'cortex.vendor.moment' -]) - -// Turns underscores into spaces, capitalizes first letter of string -.filter('humanize', function () { - return function (string) { - string = string.split('_').join(' ').toLowerCase(); - return string.charAt(0).toUpperCase() + string.slice(1); - }; -}) - -// Turns Media into its HTML representation -.filter('mediaToHtml', function () { - return function (media) { - var outputHtml; - - if (media.content_type === 'image') { - outputHtml = '

' +
-        (media.alt || '') +
-        '

'; - } - else { - outputHtml = '' + - media.name + - ''; - } - - return outputHtml; - }; -}) - -.filter('tagList', function () { - return function (tags) { - return _.map(tags, function (t) { - return t.name; - }).join(', '); - }; -}) - -.filter('prettifyArrayString', function () { - return function (arrayString) { - return JSON.parse(arrayString).join(", ") - }; -}) - -.filter('publishStatus', function (moment) { - return function (value, draft) { - if (!value || draft) { - return 'Draft'; - } - var publishedAt = moment(value); - var now = moment(); - return publishedAt.diff(now) <= 0 ? 'Published' : 'Scheduled'; - }; -}) - -// https://gist.github.com/thomseddon/3511330 -.filter('bytes', function () { - return function (bytes, precision) { - - if (isNaN(parseFloat(bytes)) || !isFinite(bytes)) { - return '-'; - } - - if (typeof precision === 'undefined') { - precision = 1; - } - - var units = ['bytes', 'kB', 'MB', 'GB', 'TB', 'PB'], - number = Math.floor(Math.log(bytes) / Math.log(1024)); - - return (bytes / Math.pow(1024, Math.floor(number))).toFixed(precision) + ' ' + units[number]; - }; -}) - -.filter('slugify', function () { - return function (value, delim) { - if (!value) { - return ''; - } - delim = delim || "-"; - return value.toLowerCase().replace(/[^\w ]+/g, '').replace(/ +/g, delim); - }; -}) - -.filter('postEditState', function () { - return function (post, sref) { - var state = "cortex.posts.edit.sections." + post.type.replace('Post', '').toLowerCase(); - if (sref) { - state = state + "({postId: " + post.id + "})"; - } - return state; - }; -}) - -.filter('trustAsResourceUrl', function ($sce) { - return function (url) { - return $sce.trustAsResourceUrl(url); - } -}) - -.filter('postNewState', function () { - return function (post) { - return "cortex.posts.new.sections." + post.type.replace('Post', '').toLowerCase(); - }; -}); diff --git a/app/assets/javascripts/legacy/resources.js b/app/assets/javascripts/legacy/resources.js deleted file mode 100644 index a7b3e54e1..000000000 --- a/app/assets/javascripts/legacy/resources.js +++ /dev/null @@ -1,89 +0,0 @@ -angular.module('cortex.resources', [ - 'ngResource', - 'cortex.settings', - 'cortex.session' -]) - -.constant('defaultActions', { - 'get': {method: 'GET'}, - 'save': {method: 'POST'}, - 'query': {method: 'GET', isArray: true}, - 'remove': {method: 'DELETE'}, - 'delete': {method: 'DELETE'} -}) - -.constant('updateCreateActions', { - update: {method: 'PUT', inArray: false}, - create: {method: 'POST'} -}) - -.factory('cortexResource', function($resource, settings, currentUser, updateCreateActions) { - return function (url, params, actions) { - actions = angular.extend(updateCreateActions, actions); - - var resource = $resource(settings.cortex_base_url + url, params, actions); - - resource.prototype.$save = function(params, success, error) { - return this.id ? this.$update(params, success, error) : this.$create(params, success, error); - }; - return resource; - }; -}) - -.factory('paginatedResource', function(cortexResource, defaultActions) { - var forEach = angular.forEach, - extend = angular.extend, - isFunction = angular.isFunction; - - return function(url, params, actions) { - actions = extend(actions, defaultActions); - - var resource = cortexResource(url, params, actions); - - forEach(actions, function(action, name) { - // If action is paginated ($query() or pagination == true in action config) - - if (/^(QUERY)$/i.test(name) || action.paginated) { - - // Wrap action function in pagination handler - resource[name + 'Paged'] = function(params, success, error) { - if (isFunction(params)) { - error = success; success = params; params = {}; - } - - var wrappedSuccess = function(data, headers) { - var pagination; - var range = headers('X-Total'); - if (range) { - - var start = (headers('X-Page') - 1) * headers('X-Per-Page'); - var end = parseInt(headers('X-Per-Page')) + start; - var per_page = headers('X-Per-Page'); - var total = headers('X-Total'); - var page = headers('X-Page') || 1; - - pagination = { - page: page, - pages: parseInt(total / per_page) + 1, - start: start, - end: end, - per_page: per_page, - total: total - }; - } - - // Call original callback - if (isFunction(success)) { - success(data, headers, pagination); - } - - }; - - return resource[name](params, wrappedSuccess, error); - }; - } - }); - - return resource; - }; -}); diff --git a/app/assets/javascripts/legacy/services/add-media.js b/app/assets/javascripts/legacy/services/add-media.js deleted file mode 100644 index 8d7e43abc..000000000 --- a/app/assets/javascripts/legacy/services/add-media.js +++ /dev/null @@ -1,42 +0,0 @@ -angular.module('cortex.services.addMedia', [ - 'cortex.services.postBodyEditor', - 'cortex.services.postsPopup' -]) - -.factory('AddMediaService', function($state, $window, - mediaSelectType, PostBodyEditorService, PostsPopupService) { - return { - setMedia: function(type, title) { - PostBodyEditorService.mediaSelectType = type; - PostsPopupService.title = title; - $state.go('.media.manage.components'); - }, - initRedactorMediaPlugin: function() { - var that = this; - - if (!$window.RedactorPlugins) { - $window.RedactorPlugins = {}; - } - - $window.RedactorPlugins.media = function() { - return { - init: function() - { - var mediaButton = this.button.add('media', 'Media'); - this.button.setAwesome('media', 'fa-picture-o'); - this.button.addCallback(mediaButton, this.media.addMediaPopup); - - this.button.remove('image'); - this.button.remove('video'); - - PostBodyEditorService.redactor = this; - }, - addMediaPopup: function() - { - that.setMedia(mediaSelectType.ADD_MEDIA, 'Insert Media from Media Library'); - } - }; - }; - } - }; -}); diff --git a/app/assets/javascripts/legacy/services/cortex.js b/app/assets/javascripts/legacy/services/cortex.js deleted file mode 100644 index f12ef68ff..000000000 --- a/app/assets/javascripts/legacy/services/cortex.js +++ /dev/null @@ -1,95 +0,0 @@ -angular.module('cortex.services.cortex', [ - 'cortex.settings', - 'cortex.resources' -]) - -.factory('cortex', function($rootScope, $http, cortexResource, paginatedResource, settings) { - var categories = cortexResource('/categories/:id', {id: '@id'}, { - hierarchy: { - method: 'GET', - url: settings.cortex_base_url + '/categories/:id/hierarchy', - isArray: true - } - }); - - var locales = paginatedResource('/localizations/:localization_id/locales/:locale_name', {locale_name: '@locale_name'}, { - search: {method: 'GET', params: {}, isArray: true, paginated: true} - }); - - var localizations = paginatedResource('/localizations/:id', {id: '@id'}, { - search: {method: 'GET', params: {}, isArray: true, paginated: true} - }); - - var posts = paginatedResource('/posts/:id', {id: '@id'}, { - feed: {method: 'GET', params: {id: 'feed'}, isArray: true, paginated: true}, - tags: {method: 'GET', params: {id: 'tags'}, isArray: true}, - search: {method: 'GET', params: { }, isArray: true, paginated: true}, - filters: {method: 'GET', params: {id: 'filters'} } - }); - - var media = paginatedResource('/media/:id', {id: '@id'}, { - tags: {method: 'GET', params: {id: 'tags'}, isArray: true}, - search: {method: 'GET', params: { }, isArray: true, paginated: true}, - bulkJob: { - method: 'POST', - url: settings.cortex_base_url + '/media/bulk_job' - } - }); - - var users = paginatedResource('/users/:id', {id: '@id'}, { - me: {method: 'GET', params: {id: 'me'}}, - bulkJob: { - method: 'POST', - url: settings.cortex_base_url + '/users/bulk_job' - } - }); - - var tenants = paginatedResource('/tenants/:id', {id: '@id'}, { - hierarchicalIndex: {method: 'GET', params: {include_children: true}, isArray: true}, - users: { - method: 'GET', - url: settings.cortex_base_url + '/tenants/:id/users', - isArray: true, - paginated: true - } - }); - - var userAuthor = cortexResource('/users/:user_id/author', {user_id: '@user_id'}); - - var occupations = cortexResource('/occupations/:id', {id: '@id', isArray: true}, { - industries: {method: 'GET', params: {id: 'industries'}, isArray: true} - }); - - var applications = paginatedResource('/applications/:id', {id: '@id', isArray: true}, { - search: {method: 'GET', params: {}, isArray: true, paginated: true} - }); - - var credentials = paginatedResource('/applications/:application_id/credentials/:credentials_id', {credential_ids: '@credentials_id'}, { - search: {method: 'GET', params: {}, isArray: true, paginated: true} - }); - - var bulkJobs = paginatedResource('/bulk_jobs/:id', {id: '@id'}, { - search: {method: 'GET', params: { }, isArray: true, paginated: true} - }); - - var webpages = paginatedResource('/webpages/:id', {id: '@id'}, { - search: {method: 'GET', params: { }, isArray: true, paginated: true}, - feed: {method: 'GET', params: {id: 'feed'}, isArray: true, paginated: true} - }); - - return { - categories: categories, - locales: locales, - localizations: localizations, - posts: posts, - media: media, - tenants: tenants, - users: users, - userAuthor: userAuthor, - occupations: occupations, - applications: applications, - credentials: credentials, - bulk_jobs: bulkJobs, - webpages: webpages - }; -}); diff --git a/app/assets/javascripts/legacy/services/image-fit.js b/app/assets/javascripts/legacy/services/image-fit.js deleted file mode 100644 index a63cf19a0..000000000 --- a/app/assets/javascripts/legacy/services/image-fit.js +++ /dev/null @@ -1,34 +0,0 @@ -angular.module('cortex.services.imageFit', [ -]) - -.factory('ImageFitService', function($window, flash) { - return { - initRedactorImageFitPlugin: function() { - if (!$window.RedactorPlugins) { - $window.RedactorPlugins = {}; - } - - $window.RedactorPlugins.imageFit = function() { - return { - init: function() - { - var imageFitButton = this.button.add('imageFit', 'Fit to Page'); - this.button.setAwesome('imageFit', 'fa-arrows-alt'); - this.button.addCallback(imageFitButton, this.imageFit.fitImageToPage); - }, - fitImageToPage: function() - { - var imgElement = angular.element(this.selection.getCurrent()).find('img'); - - if (imgElement.length) { - imgElement.css( "width", "100%" ); - } - else { - flash.error = 'Image not found at selection.'; - } - } - }; - }; - } - }; -}); diff --git a/app/assets/javascripts/legacy/services/media-constraints.js b/app/assets/javascripts/legacy/services/media-constraints.js deleted file mode 100644 index 2f040956f..000000000 --- a/app/assets/javascripts/legacy/services/media-constraints.js +++ /dev/null @@ -1,77 +0,0 @@ -angular.module('cortex.services.mediaConstraints', []) - -.factory('mediaConstraintsService', function($rootScope) { - var filesize = function(media, max) { - return media.attachment_file_size <= max; - }; - - var width = function(media, min, max) { - return media.dimensions[0] >= min && (media.dimensions[0] <= max || max === -1); - }; - - var height = function(media, min, max) { - return media.dimensions[1] >= min && (media.dimensions[1] <= max || max === -1); - }; - - var aspectratio = function(media, valid) { - var aspectRatio = media.dimensions[0] / media.dimensions[1]; - if (angular.isNumber(valid)) { - return aspectRatio.toFixed(1) === valid.toFixed(1); - } - else if (angular.isArray(valid)) { - return valid.filter(function(x) { - return compareDecimal(x, aspectRatio) - }).length; - } - }; - - function compareDecimal(x, y) { - return x.toFixed(1) === y.toFixed(1); - } - - var totalSize = function(media, valid, decimal) { - return decimal * valid <= media.dimensions[0] * media.dimensions[1]; - }; - - return { - filesize: filesize, - width: width, - height: height, - aspectratio: aspectratio, - totalSize: totalSize - }; - -}) - -.factory('featuredMediaConstraintsService', function($rootScope, mediaConstraintsService) { - var parent = mediaConstraintsService; - var child = angular.copy(parent); - child.width = function(media) { - return parent.width(media, 1100, -1); - }; - child.totalSize = function(media) { - return parent.totalSize(media, 660000, .9); - }; - - child.aspectratio = function(media) { - return parent.aspectratio(media, [1.6, 1.7, 1.8]); - }; - - return child; - -}) - -.factory('tileMediaConstraintsService', function($rootScope, mediaConstraintsService) { - var parent = mediaConstraintsService; - var child = angular.copy(parent); - - child.width = function(media) { - return parent.width(media, 375, -1); - }; - - child.aspectratio = function(media) { - return parent.aspectratio(media, [1.0, 1.1, 1.2]); - }; - - return child; -}); \ No newline at end of file diff --git a/app/assets/javascripts/legacy/services/post-body-editor.js b/app/assets/javascripts/legacy/services/post-body-editor.js deleted file mode 100644 index 695600a7a..000000000 --- a/app/assets/javascripts/legacy/services/post-body-editor.js +++ /dev/null @@ -1,17 +0,0 @@ -angular.module('cortex.services.postBodyEditor', [ - 'cortex.filters' -]) - -.factory('PostBodyEditorService', function($filter) { - return { - redactor: {}, - mediaSelectType: '', - media: { - featured: {}, - tile: {} - }, - addMediaToPost: function (media) { - this.redactor.insert.htmlWithoutClean($filter('mediaToHtml')(media)); - } - }; -}); diff --git a/app/assets/javascripts/legacy/services/posts-popup.js b/app/assets/javascripts/legacy/services/posts-popup.js deleted file mode 100644 index 135ce7117..000000000 --- a/app/assets/javascripts/legacy/services/posts-popup.js +++ /dev/null @@ -1,9 +0,0 @@ -angular.module('cortex.services.postsPopup', [ -]) - - .factory('PostsPopupService', function() { - return { - popupOpen: true, - title: '' - }; -}); diff --git a/app/assets/javascripts/legacy/session.js b/app/assets/javascripts/legacy/session.js deleted file mode 100644 index 5dd740ee5..000000000 --- a/app/assets/javascripts/legacy/session.js +++ /dev/null @@ -1,5 +0,0 @@ -angular.module('cortex.session', []) - -.config(function($provide) { - $provide.constant('currentUser', angular.copy(window.gon.current_user)); -}); diff --git a/app/assets/javascripts/legacy/settings.js b/app/assets/javascripts/legacy/settings.js deleted file mode 100644 index e56b7ad8d..000000000 --- a/app/assets/javascripts/legacy/settings.js +++ /dev/null @@ -1,17 +0,0 @@ -angular.module('cortex.settings', []) - -.config(function($provide) { - $provide.constant('settings', angular.copy(window.gon.settings)); -}) - -.constant('events', { - // Events that should be replaced with refactored states - TENANT_HIERARCHY_CHANGE: '$tenantHierarchyChange', - ORGANIZATIONS_CHANGE: '$organizationsChange' -}) - -.constant('mediaSelectType', { - ADD_MEDIA: 'addMedia', - SET_FEATURED: 'setFeatured', - SET_TILE: 'setTile' -}); diff --git a/app/assets/javascripts/legacy/states.js b/app/assets/javascripts/legacy/states.js deleted file mode 100644 index 0ded3a012..000000000 --- a/app/assets/javascripts/legacy/states.js +++ /dev/null @@ -1,1311 +0,0 @@ -angular.module('cortex.states', [ - 'ui.router.state', - - 'cortex.services.cortex', - 'cortex.templates', - - 'cortex.controllers.users.facets', - 'cortex.controllers.users.profile', - 'cortex.controllers.users.grid', - 'cortex.controllers.users.edit', - 'cortex.controllers.users.new', - 'cortex.controllers.users.bulk', - - 'cortex.controllers.media.edit', - 'cortex.controllers.media.grid', - 'cortex.controllers.media.bulk', - - 'cortex.controllers.organizations', - 'cortex.controllers.organizations.manage', - 'cortex.controllers.tenants.edit', - 'cortex.controllers.tenants.manage', - - 'cortex.controllers.posts.edit', - 'cortex.controllers.posts.edit.info', - 'cortex.controllers.posts.edit.classify', - 'cortex.controllers.posts.edit.display', - 'cortex.controllers.posts.edit.seo', - 'cortex.controllers.posts.grid', - 'cortex.controllers.posts.popup', - - 'cortex.controllers.localizations.edit', - 'cortex.controllers.localizations.grid', - 'cortex.controllers.locales.edit', - 'cortex.controllers.locales.grid', - - 'cortex.controllers.applications.grid', - 'cortex.controllers.credentials.grid', - 'cortex.controllers.credentials.edit', - 'cortex.controllers.credentials.new', - - 'cortex.controllers.bulk_jobs.grid', - - 'cortex.controllers.webpages.grid', - 'cortex.controllers.webpages.new', - 'cortex.controllers.webpages.edit' -]) - -.config(function ($stateProvider, $urlRouterProvider) { - - // Catch /admin/media link from breadcrumb - $urlRouterProvider.when('/media', '/media///'); - - $stateProvider - .state('login', { - url: '/login', - templateUrl: 'login', - data: {pageTitle: 'Login'} - }) - - .state('cortex', { - abstract: true, - url: '', - templateUrl: 'main.html', - data: { - ncyBreadcrumbLabel: 'Home' - } - }) - - // Bulk Jobs - - .state('cortex.bulk_jobs', { - url: '/bulk_jobs', - abstract: true, - template: '
', - data: { - ncyBreadcrumbLabel: 'Bulk Jobs' - } - }) - - .state('cortex.bulk_jobs.manage', { - url: '', - views: { - 'bulk-jobs@cortex.bulk_jobs': { - templateUrl: 'bulk_jobs/grid.html', - controller: 'BulkJobsGridCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - // Localizations - - .state('cortex.localizations', { - url: '/localizations', - abstract: true, - template: '
' + - '
', - data: { - ncyBreadcrumbLabel: 'Localizations' - } - }) - - .state('cortex.localizations.new', { - url: '/new', - views: { - 'localizations@cortex.localizations': { - templateUrl: 'localizations/edit.html', - controller: 'LocalizationsEditCtrl' - } - }, - data: { - ncyBreadcrumbLabel: 'Add Localization' - } - }) - - .state('cortex.localizations.localization', { - url: '/:localizationId', - abstract: true, - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.localizations.localization.edit', { - url: '/edit', - templateUrl: 'localizations/edit.html', - controller: 'LocalizationsEditCtrl', - views: { - 'localizations@cortex.localizations': { - templateUrl: 'localizations/edit.html', - controller: 'LocalizationsEditCtrl' - }, - 'locales-grid@cortex.localizations': { - templateUrl: 'locales/grid.html', - controller: 'LocalesGridCtrl' - } - }, - data: { - ncyBreadcrumbLabel: 'Edit Localization' - } - }) - - .state('cortex.localizations.manage', { - url: '', - views: { - 'localizations@cortex.localizations': { - templateUrl: 'localizations/grid.html', - controller: 'LocalizationsGridCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - // Locales - - .state('cortex.localizations.localization.new_locale', { - url: '/new', - views: { - 'localizations@cortex.localizations': { - templateUrl: 'locales/edit.html', - controller: 'LocalesEditCtrl' - } - }, - data: { - ncyBreadcrumbLabel: 'Add Locale' - } - }) - - .state('cortex.localizations.localization.edit_locale', { - url: '/:localeName/edit', - views: { - 'localizations@cortex.localizations': { - templateUrl: 'locales/edit.html', - controller: 'LocalesEditCtrl' - } - }, - data: { - ncyBreadcrumbLabel: 'Edit Locale' - } - }) - - // Media - - .state('cortex.media', { - url: '/media', - abstract: true, - template: '
', - data: { - ncyBreadcrumbLabel: 'Media', - ncyBreadcrumbLink: '/media///' - } - }) - - .state('cortex.media.new', { - url: '/new', - templateUrl: 'media/new.html', - controller: 'MediaEditCtrl', - data: { - ncyBreadcrumbLabel: 'Add Media' - } - }) - - .state('cortex.media.bulk', { - url: '/bulk', - templateUrl: 'media/bulk.html', - controller: 'MediaBulkCtrl', - data: { - ncyBreadcrumbLabel: 'Bulk Add Media' - } - }) - - .state('cortex.media.edit', { - url: '/:mediaId/edit', - templateUrl: 'media/edit.html', - controller: 'MediaEditCtrl', - data: { - ncyBreadcrumbLabel: 'Edit Media' - } - }) - - .state('cortex.media.manage', { - url: '', - abstract: true, - templateUrl: 'media/manage.html', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.media.manage.components', { - url: '/:page/:perPage/:query', - views: { - 'media-grid': { - templateUrl: 'media/grid.html', - controller: 'MediaGridCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - // Posts - - .state('cortex.posts', { - url: '/posts', - abstract: true, - template: '
', - data: { - ncyBreadcrumbLabel: 'Posts' - } - }) - - .state('cortex.posts.new', { - url: '/new', - abstract: true, - templateUrl: 'posts/edit.html', - controller: 'PostsEditCtrl', - resolve: { - post: ['$q', 'cortex', 'currentUser', function($q, cortex, currentUser) { - var defer = $q.defer(); - - var post = new cortex.posts(); - post.body = ''; - post.draft = true; - post.is_wysiwyg = true; - post.author = currentUser.full_name; - post.copyright_owner = post.copyright_owner || "CareerBuilder, LLC"; - post.tag_list = ''; - post.seo_keyword_list = ''; - post.published_at = new Date(); - post.display = 'medium'; - post.postCategories = {}; - - defer.resolve(post); - return defer.promise; - }], - categoriesHierarchy: ['cortex', function(cortex) { - return cortex.categories.hierarchy().$promise; - }], - filters: ['cortex', function(cortex) { - return cortex.posts.filters().$promise; - }], - currentUserAuthor: ['cortex', 'currentUser', function(cortex, currentUser) { - return cortex.userAuthor.get({user_id: currentUser.id}).$promise; - }] - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.new.sections', { - url: '', - abstract: true, - views: { - 'info': { - templateUrl: 'posts/article/info.html', - controller: 'PostsEditInfoCtrl' - }, - 'classify': { - templateUrl: 'posts/article/classify.html', - controller: 'PostsEditClassifyCtrl' - }, - 'display': { - templateUrl: 'posts/article/display.html', - controller: 'PostsEditDisplayCtrl' - }, - 'seo': { - templateUrl: 'posts/article/seo.html', - controller: 'PostsEditSeoCtrl' - } - } - }) - - .state('cortex.posts.new.sections.article', { - url: '/article', - data: { - ncyBreadcrumbLabel: 'New Post' - } - }) - - .state('cortex.posts.new.sections.video', { - url: '/video', - data: { - ncyBreadcrumbLabel: 'New Post' - } - }) - - .state('cortex.posts.new.sections.infographic', { - url: '/infographic', - data: { - ncyBreadcrumbLabel: 'New Post' - } - }) - - .state('cortex.posts.new.sections.promo', { - url: '/promo', - views: { - 'info@cortex.posts.new': { - templateUrl: 'posts/promo/info.html', - controller: 'PostsEditInfoCtrl' - }, - 'display@cortex.posts.new': { - templateUrl: 'posts/promo/display.html', - controller: 'PostsEditDisplayCtrl' - }, - 'seo@cortex.posts.new': { - templateUrl: 'posts/promo/seo.html', - controller: 'PostsEditSeoCtrl' - } - }, - data: { - ncyBreadcrumbLabel: 'New Post' - } - }) - - .state('cortex.posts.edit', { - url: '/:postId/edit', - abstract: true, - templateUrl: 'posts/edit.html', - controller: 'PostsEditCtrl', - resolve: { - categoriesHierarchy: ['cortex', function(cortex) { - return cortex.categories.hierarchy().$promise; - }], - filters: ['cortex', function(cortex) { - return cortex.posts.filters().$promise; - }], - currentUserAuthor: ['cortex', 'currentUser', function(cortex, currentUser) { - return cortex.userAuthor.get({user_id: currentUser.id}).$promise; - }], - post: ['$stateParams', '$q', 'cortex', function($stateParams, $q, cortex) { - var defer = $q.defer(); - - cortex.posts.get({id: $stateParams.postId}).$promise - .then(function(post) { - if (post.industry) { - post.industry_id = post.industry.id; - } - - var selectedCategoryIds = _.map(post.categories, function (c) { - return c.id; - }); - - postCategories = {}; - angular.forEach(selectedCategoryIds, function(id) { - postCategories[id] = true; - }); - post.postCategories = postCategories; - - defer.resolve(post); - }, function(response) { - defer.reject(response); - }); - - return defer.promise; - }] - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.edit.sections', { - url: '', - abstract: true, - views: { - 'info': { - templateUrl: 'posts/article/info.html', - controller: 'PostsEditInfoCtrl' - }, - 'classify': { - templateUrl: 'posts/article/classify.html', - controller: 'PostsEditClassifyCtrl' - }, - 'display': { - templateUrl: 'posts/article/display.html', - controller: 'PostsEditDisplayCtrl' - }, - 'seo': { - templateUrl: 'posts/article/seo.html', - controller: 'PostsEditSeoCtrl' - } - } - }) - - .state('cortex.posts.edit.sections.article', { - url: '/article', - data: { - ncyBreadcrumbLabel: 'Edit Post' - } - }) - - .state('cortex.posts.edit.sections.video', { - url: '/video', - data: { - ncyBreadcrumbLabel: 'Edit Post' - } - }) - - .state('cortex.posts.edit.sections.infographic', { - url: '/infographic', - data: { - ncyBreadcrumbLabel: 'Edit Post' - } - }) - - .state('cortex.posts.edit.sections.promo', { - url: '/promo', - views: { - 'info@cortex.posts.edit': { - templateUrl: 'posts/promo/info.html', - controller: 'PostsEditInfoCtrl' - }, - 'display@cortex.posts.edit': { - templateUrl: 'posts/promo/display.html', - controller: 'PostsEditDisplayCtrl' - }, - 'seo@cortex.posts.edit': { - templateUrl: 'posts/promo/seo.html', - controller: 'PostsEditSeoCtrl' - } - }, - data: { - ncyBreadcrumbLabel: 'Edit Post' - } - }) - - // Posts Edit + Media Popup - // ********************** - - // ** Article/Media Popup (Edit) - - .state('cortex.posts.edit.sections.article.media', { - url: '/media', - abstract: true, - views: { - 'popup@cortex.posts.edit': { - templateUrl: 'posts/popup.html', - controller: 'PostsPopupCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.edit.sections.article.media.new', { - url: '/new', - templateUrl: 'media/new.html', - controller: 'MediaEditCtrl', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.edit.sections.article.media.bulk', { - url: '/bulk', - templateUrl: 'media/bulk.html', - controller: 'MediaBulkCtrl', - data: { - ncyBreadcrumbLabel: 'Bulk Add Media' - } - }) - - .state('cortex.posts.edit.sections.article.media.edit', { - url: '/:mediaId/edit', - templateUrl: 'media/edit.html', - controller: 'MediaEditCtrl', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.edit.sections.article.media.manage', { - url: '', - abstract: true, - templateUrl: 'media/manage.html', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.edit.sections.article.media.manage.components', { - url: '/:page/:perPage/:query', - views: { - 'media-grid': { - templateUrl: 'media/grid.html', - controller: 'MediaGridCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - // ** Video/Media Popup (Edit) - - .state('cortex.posts.edit.sections.video.media', { - url: '/media', - abstract: true, - views: { - 'popup@cortex.posts.edit': { - templateUrl: 'posts/popup.html', - controller: 'PostsPopupCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.edit.sections.video.media.new', { - url: '/new', - templateUrl: 'media/new.html', - controller: 'MediaEditCtrl', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.edit.sections.video.media.bulk', { - url: '/bulk', - templateUrl: 'media/bulk.html', - controller: 'MediaBulkCtrl', - data: { - ncyBreadcrumbLabel: 'Bulk Add Media' - } - }) - - .state('cortex.posts.edit.sections.video.media.edit', { - url: '/:mediaId/edit', - templateUrl: 'media/edit.html', - controller: 'MediaEditCtrl', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.edit.sections.video.media.manage', { - url: '', - abstract: true, - templateUrl: 'media/manage.html', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.edit.sections.video.media.manage.components', { - url: '/:page/:perPage/:query', - views: { - 'media-grid': { - templateUrl: 'media/grid.html', - controller: 'MediaGridCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - // ** Infographic/Media Popup (Edit) - - .state('cortex.posts.edit.sections.infographic.media', { - url: '/media', - abstract: true, - views: { - 'popup@cortex.posts.edit': { - templateUrl: 'posts/popup.html', - controller: 'PostsPopupCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.edit.sections.infographic.media.new', { - url: '/new', - templateUrl: 'media/new.html', - controller: 'MediaEditCtrl', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.edit.sections.infographic.media.bulk', { - url: '/bulk', - templateUrl: 'media/bulk.html', - controller: 'MediaBulkCtrl', - data: { - ncyBreadcrumbLabel: 'Bulk Add Media' - } - }) - - .state('cortex.posts.edit.sections.infographic.media.edit', { - url: '/:mediaId/edit', - templateUrl: 'media/edit.html', - controller: 'MediaEditCtrl', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.edit.sections.infographic.media.manage', { - url: '', - abstract: true, - templateUrl: 'media/manage.html', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.edit.sections.infographic.media.manage.components', { - url: '/:page/:perPage/:query', - views: { - 'media-grid': { - templateUrl: 'media/grid.html', - controller: 'MediaGridCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - // ** Promo/Media Popup (Edit) - - .state('cortex.posts.edit.sections.promo.media', { - url: '/media', - abstract: true, - views: { - 'popup@cortex.posts.edit': { - templateUrl: 'posts/popup.html', - controller: 'PostsPopupCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.edit.sections.promo.media.new', { - url: '/new', - templateUrl: 'media/new.html', - controller: 'MediaEditCtrl', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.edit.sections.promo.media.bulk', { - url: '/bulk', - templateUrl: 'media/bulk.html', - controller: 'MediaBulkCtrl', - data: { - ncyBreadcrumbLabel: 'Bulk Add Media' - } - }) - - .state('cortex.posts.edit.sections.promo.media.edit', { - url: '/:mediaId/edit', - templateUrl: 'media/edit.html', - controller: 'MediaEditCtrl', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.edit.sections.promo.media.manage', { - url: '', - abstract: true, - templateUrl: 'media/manage.html', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.edit.sections.promo.media.manage.components', { - url: '/:page/:perPage/:query', - views: { - 'media-grid': { - templateUrl: 'media/grid.html', - controller: 'MediaGridCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - // ** Article/Media Popup (New) - - .state('cortex.posts.new.sections.article.media', { - url: '/media', - abstract: true, - views: { - 'popup@cortex.posts.new': { - templateUrl: 'posts/popup.html', - controller: 'PostsPopupCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.new.sections.article.media.new', { - url: '/new', - templateUrl: 'media/new.html', - controller: 'MediaEditCtrl', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.new.sections.article.media.bulk', { - url: '/bulk', - templateUrl: 'media/bulk.html', - controller: 'MediaBulkCtrl', - data: { - ncyBreadcrumbLabel: 'Bulk Add Media' - } - }) - - .state('cortex.posts.new.sections.article.media.edit', { - url: '/:mediaId/edit', - templateUrl: 'media/edit.html', - controller: 'MediaEditCtrl', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.new.sections.article.media.manage', { - url: '', - abstract: true, - templateUrl: 'media/manage.html', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.new.sections.article.media.manage.components', { - url: '/:page/:perPage/:query', - views: { - 'media-grid': { - templateUrl: 'media/grid.html', - controller: 'MediaGridCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - // ** Video/Media Popup (New) - - .state('cortex.posts.new.sections.video.media', { - url: '/media', - abstract: true, - views: { - 'popup@cortex.posts.new': { - templateUrl: 'posts/popup.html', - controller: 'PostsPopupCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.new.sections.video.media.new', { - url: '/new', - templateUrl: 'media/new.html', - controller: 'MediaEditCtrl', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.new.sections.video.media.bulk', { - url: '/bulk', - templateUrl: 'media/bulk.html', - controller: 'MediaBulkCtrl', - data: { - ncyBreadcrumbLabel: 'Bulk Add Media' - } - }) - - .state('cortex.posts.new.sections.video.media.edit', { - url: '/:mediaId/edit', - templateUrl: 'media/edit.html', - controller: 'MediaEditCtrl', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.new.sections.video.media.manage', { - url: '', - abstract: true, - templateUrl: 'media/manage.html', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.new.sections.video.media.manage.components', { - url: '/:page/:perPage/:query', - views: { - 'media-grid': { - templateUrl: 'media/grid.html', - controller: 'MediaGridCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - // ** Infographic/Media Popup (New) - - .state('cortex.posts.new.sections.infographic.media', { - url: '/media', - abstract: true, - views: { - 'popup@cortex.posts.new': { - templateUrl: 'posts/popup.html', - controller: 'PostsPopupCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.new.sections.infographic.media.new', { - url: '/new', - templateUrl: 'media/new.html', - controller: 'MediaEditCtrl', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.new.sections.infographic.media.bulk', { - url: '/bulk', - templateUrl: 'media/bulk.html', - controller: 'MediaBulkCtrl', - data: { - ncyBreadcrumbLabel: 'Bulk Add Media' - } - }) - - .state('cortex.posts.new.sections.infographic.media.edit', { - url: '/:mediaId/edit', - templateUrl: 'media/edit.html', - controller: 'MediaEditCtrl', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.new.sections.infographic.media.manage', { - url: '', - abstract: true, - templateUrl: 'media/manage.html', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.new.sections.infographic.media.manage.components', { - url: '/:page/:perPage/:query', - views: { - 'media-grid': { - templateUrl: 'media/grid.html', - controller: 'MediaGridCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - // ** Promo/Media Popup (New) - - .state('cortex.posts.new.sections.promo.media', { - url: '/media', - abstract: true, - views: { - 'popup@cortex.posts.new': { - templateUrl: 'posts/popup.html', - controller: 'PostsPopupCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.new.sections.promo.media.new', { - url: '/new', - templateUrl: 'media/new.html', - controller: 'MediaEditCtrl', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.new.sections.promo.media.bulk', { - url: '/bulk', - templateUrl: 'media/bulk.html', - controller: 'MediaBulkCtrl', - data: { - ncyBreadcrumbLabel: 'Bulk Add Media' - } - }) - - .state('cortex.posts.new.sections.promo.media.edit', { - url: '/:mediaId/edit', - templateUrl: 'media/edit.html', - controller: 'MediaEditCtrl', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.new.sections.promo.media.manage', { - url: '', - abstract: true, - templateUrl: 'media/manage.html', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.new.sections.promo.media.manage.components', { - url: '/:page/:perPage/:query', - views: { - 'media-grid': { - templateUrl: 'media/grid.html', - controller: 'MediaGridCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - // ********************** - - .state('cortex.posts.manage', { - url: '', - abstract: true, - templateUrl: 'posts/manage.html', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.posts.manage.components', { - url: '', - views: { - 'posts-grid': { - templateUrl: 'posts/grid.html', - controller: 'PostsGridCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - // Tenants - - .state('cortex.organizations', { - url: '/organizations/:organizationId', - template: '', - abstract: true, - controller: 'OrganizationsCtrl', - resolve: { - organizations: ['cortex', function(cortex) { - return cortex.tenants.query().$promise; - }] - }, - data: { - ncyBreadcrumbLabel: 'Tenants' - } - }) - - .state('cortex.organizations.tenants', { - url: '', - template: '', - abstract: true, - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.organizations.tenants.edit', { - url: '/tenants/:tenantId/edit', - templateUrl: 'tenants/edit.html', - controller: 'EditTenantsCtrl', - data: { - ncyBreadcrumbLabel: 'Edit Tenant' - } - }) - - .state('cortex.organizations.tenants.new', { - url: '/tenants/new', - templateUrl: 'tenants/edit.html', - controller: 'EditTenantsCtrl', - data: { - ncyBreadcrumbLabel: 'Add Tenant' - } - }) - - .state('cortex.organizations.manage', { - url: '', - templateUrl: 'organizations/manage.html', - controller: 'OrganizationsManageCtrl', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.organizations.manage.tenants', { - url: '/tenants/:tenantId', - views: { - 'tenants-tree': { - templateUrl: 'tenants/manage.tree.html', - controller: 'TenantsTreeCtrl' - }, - 'tenants-details': { - templateUrl: 'tenants/manage.details.html' - } - }, - resolve: { - organization: ['$stateParams', 'cortex', function($stateParams, cortex) { - return cortex.tenants.get({id: $stateParams.organizationId, include_children: true}).$promise; - }] - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - // Products - - .state('cortex.products', { - url: '/products', - template: 'Applications placeholder', - data: { - ncyBreadcrumbLabel: 'Apps/Products' - } - }) - - // Permissions - - .state('cortex.permissions', { - url: '/permissions', - template: 'Permissions placeholder', - data: { - ncyBreadcrumbLabel: 'Roles/Permissions' - } - }) - - // Users - - .state('cortex.users', { - url: '/users', - abstract: true, - template: '
', - data: { - ncyBreadcrumbLabel: 'Users' - } - }) - - .state('cortex.users.facets', { - url: '', - abstract: true, - controller: 'UsersFacetCtrl', - templateUrl: 'users/facets.html', - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.users.facets.grid', { - url: '', - views: { - 'users-grid': { - templateUrl: 'users/grid.html', - controller: 'UsersGridCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.users.new', { - url: '/new', - templateUrl: 'users/new.html', - controller: 'UsersNewCtrl', - data: { - ncyBreadcrumbLabel: 'New User' - }, - resolve: { - user: ['cortex', function(cortex) { - return new cortex.users(); - }] - } - }) - - .state('cortex.users.bulk', { - url: '/bulk', - templateUrl: 'users/bulk.html', - controller: 'UsersBulkCtrl', - data: { - ncyBreadcrumbLabel: 'Bulk Add Users' - } - }) - - .state('cortex.users.edit', { - url: '/:userId', - templateUrl: 'users/edit.html', - controller: 'UsersEditCtrl', - data: { - ncyBreadcrumbLabel: 'Edit' - }, - resolve: { - user: ['$stateParams', 'cortex', function($stateParams, cortex) { - return cortex.users.get({id: $stateParams.userId}); - }] - } - }) - - .state('cortex.users.profile', { - url: '/profile/:userId', - templateUrl: 'users/profile.html', - controller: 'UsersProfileCtrl', - data: { - ncyBreadcrumbLabel: 'Profile' - }, - resolve: { - user: ['$stateParams', 'cortex', function($stateParams, cortex) { - return cortex.users.get({id: $stateParams.userId}); - }], - author: ['$stateParams', '$q', 'cortex', function($stateParams, $q, cortex) { - var defer = $q.defer(); - - // Resolve the user's author information or create a new userAuthor resource - cortex.userAuthor.get({user_id: $stateParams.userId}).$promise - .then(function(author) { - author.user_id = $stateParams.userId; - defer.resolve(author); - }, function(response) { - if (response.status === 404) { - defer.resolve(new cortex.userAuthor({user_id: $stateParams.userId})); - } else { - defer.reject(response); - } - }); - - return defer.promise; - }] - } - }) - - // Applications - - .state('cortex.applications', { - url: '/applications', - abstract: true, - template: '
', - data: { - ncyBreadcrumbLabel: 'Applications' - } - }) - - .state('cortex.applications.manage', { - url: '', - views: { - 'applications@cortex.applications': { - templateUrl: 'applications/grid.html', - controller: 'ApplicationsGridCtrl' - } - }, - data: { - ncyBreadcrumbLabel: false - } - }) - - .state('cortex.applications.manage.credentials', { - url: '/:applicationId/credentials', - views: { - 'applications@cortex.applications': { - templateUrl: 'credentials/grid.html', - controller: 'CredentialsGridCtrl' - } - }, - data: { - ncyBreadcrumbLabel: 'Credentials' - } - }) - - .state('cortex.applications.manage.credentials.new', { - url: '/new', - views: { - 'applications@cortex.applications': { - templateUrl: 'credentials/new.html', - controller: 'CredentialsNewCtrl' - } - }, - data: { - ncyBreadcrumbLabel: 'New' - } - }) - - .state('cortex.applications.manage.credentials.edit', { - url: '/edit/:credentialsId', - views: { - 'applications@cortex.applications': { - templateUrl: 'credentials/edit.html', - controller: 'CredentialsEditCtrl' - } - }, - data: { - ncyBreadcrumbLabel: 'Edit' - } - }) - .state('cortex.webpages', { - url: '/webpages', - abstract: true, - template: '
', - data: { - ncyBreadcrumbLabel: 'Webpages' - } - }) - .state('cortex.webpages.manage', { - url: '', - controller: 'WebpagesGridCtrl', - templateUrl: 'webpages/grid.html', - data: { - ncyBreadcrumbLabel: false - } - }) - .state('cortex.webpages.new', { - url: '/new', - controller: 'WebpagesNewCtrl', - templateUrl: 'webpages/new.html', - data: { - ncyBreadcrumbLabel: 'New' - } - }) - .state('cortex.webpages.edit', { - url: '/:webpageId', - controller: 'WebpagesEditCtrl', - templateUrl: 'webpages/edit.html', - data: { - ncyBreadcrumbLabel: 'Edit' - } - }) -}); diff --git a/app/assets/javascripts/legacy/util.js b/app/assets/javascripts/legacy/util.js deleted file mode 100644 index 0c7d25ff3..000000000 --- a/app/assets/javascripts/legacy/util.js +++ /dev/null @@ -1,67 +0,0 @@ -angular.module('cortex.util', []) - -.constant('util', { - supplant: function (str, obj) { - return str.replace( - /\{([^{}]*)\}/g, - function (a, b) { - var r = obj[b]; - return typeof r === 'string' || typeof r === 'number' ? r : a; - } - ); - }, - - randomString: function (length) { - var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - var result = ''; - for (var i = 0; i < length; ++i) { - result += chars[Math.round(Math.random() * (chars.length - 1))]; - } - return result; - }, - - isEmpty: function (str) { - return (!str || 0 === str.length); - } - - // Eventually replace many of these util functions with Underscore-String -}) - -.factory('hierarchyUtils', function () { - return { - flattenTenantHierarchy: function (tenants) { - var flatten = function (tenants, result) { - _.each(tenants, function (tenant) { - result.push(tenant); - if (tenant.children && tenant.children.length > 0) { - flatten(tenant.children, result); - } - }); - }; - var flattened = []; - flatten(tenants, flattened); - return flattened; - } - }; -}) - -.filter('totalTenants', function (hierarchyUtils) { - return function (children) { - return hierarchyUtils.flattenTenantHierarchy(children).length; - }; -}) - -.factory('delayedBind', function($timeout) { - return function(scope, watch, delay, callback) { - var pending; - - scope.$watch(watch, function() { - if (pending) { - $timeout.cancel(pending); - } - pending = $timeout(function() { - callback(); - }, delay); - }); - }; -}); diff --git a/app/assets/javascripts/legacy/vendor/abn-tree-directive.js b/app/assets/javascripts/legacy/vendor/abn-tree-directive.js deleted file mode 100644 index f7c918e23..000000000 --- a/app/assets/javascripts/legacy/vendor/abn-tree-directive.js +++ /dev/null @@ -1,172 +0,0 @@ -angular.module('angularBootstrapNavTree', []) - -.directive('abnTree', function($timeout) { - return { - restrict: 'E', - templateUrl: 'vendor/abn-tree.html', - scope: { - treeData: '=', - onSelect: '&', - initialSelection: '=' - }, - link: function(scope, element, attrs) { - var expand_level, for_each_branch, on_treeData_change, select_branch, selected_branch; - if (attrs.iconExpand == null) { - attrs.iconExpand = 'fa fa-plus'; - } - if (attrs.iconCollapse == null) { - attrs.iconCollapse = 'fa fa-minus'; - } - if (attrs.iconLeaf == null) { - attrs.iconLeaf = 'fa fa-file'; - } - if (attrs.expandLevel == null) { - attrs.expandLevel = '3'; - } - expand_level = parseInt(attrs.expandLevel, 10); - scope.header = attrs.header; - if (!scope.treeData) { - alert('no treeData defined for the tree!'); - return; - } - if (scope.treeData.length == null) { - if (treeData.name != null) { - scope.treeData = [treeData]; - } else { - alert('treeData should be an array of root branches'); - return; - } - } - for_each_branch = function(f) { - var do_f, root_branch, _i, _len, _ref, _results; - do_f = function(branch, level) { - var child, _i, _len, _ref, _results; - f(branch, level); - if (branch.children != null) { - _ref = branch.children; - _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - child = _ref[_i]; - _results.push(do_f(child, level + 1)); - } - return _results; - } - }; - _ref = scope.treeData; - _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - root_branch = _ref[_i]; - _results.push(do_f(root_branch, 1)); - } - return _results; - }; - for_each_branch(function(b, level) { - b.level = level; - return b.expanded = b.level < expand_level; - }); - selected_branch = null; - select_branch = function(branch) { - if (branch !== selected_branch) { - if (selected_branch != null) { - selected_branch.selected = false; - } - branch.selected = true; - selected_branch = branch; - if (branch.onSelect != null) { - return $timeout(function() { - return branch.onSelect(branch); - }); - } else { - if (scope.onSelect != null) { - return $timeout(function() { - return scope.onSelect({ - branch: branch - }); - }); - } - } - } - }; - scope.user_clicks_branch = function(branch) { - if (branch !== selected_branch) { - return select_branch(branch); - } - }; - scope.tree_rows = []; - on_treeData_change = function() { - var add_branch_to_list, root_branch, _i, _len, _ref, _results; - scope.tree_rows = []; - for_each_branch(function(branch) { - if (branch.children) { - if (branch.children.length > 0) { - return branch.children = branch.children.map(function(e) { - if (typeof e === 'string') { - return { - name: e, - children: [] - }; - } else { - return e; - } - }); - } - } else { - return branch.children = []; - } - }); - for_each_branch(function(b, level) { - if (!b.uid) { - return b.uid = "" + Math.random(); - } - }); - add_branch_to_list = function(level, branch, visible) { - var child, child_visible, tree_icon, _i, _len, _ref, _results; - if (branch.expanded == null) { - branch.expanded = false; - } - if (!branch.children || branch.children.length === 0) { - tree_icon = attrs.iconLeaf; - } else { - if (branch.expanded) { - tree_icon = attrs.iconCollapse; - } else { - tree_icon = attrs.iconExpand; - } - } - scope.tree_rows.push({ - level: level, - branch: branch, - label: branch.name, - tree_icon: tree_icon, - visible: visible - }); - if (branch.children != null) { - _ref = branch.children; - _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - child = _ref[_i]; - child_visible = visible && branch.expanded; - _results.push(add_branch_to_list(level + 1, child, child_visible)); - } - return _results; - } - }; - _ref = scope.treeData; - _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - root_branch = _ref[_i]; - _results.push(add_branch_to_list(1, root_branch, true)); - } - return _results; - }; - if (attrs.initialSelection) { - for_each_branch(function(b) { - if (b.name === attrs.initialSelection) { - return select_branch(b); - } - }); - } - return scope.$watch('treeData', on_treeData_change, true); - } - }; -}); diff --git a/app/assets/javascripts/legacy/vendor/angular-breadcrumb.js b/app/assets/javascripts/legacy/vendor/angular-breadcrumb.js deleted file mode 100644 index 052f617e3..000000000 --- a/app/assets/javascripts/legacy/vendor/angular-breadcrumb.js +++ /dev/null @@ -1,119 +0,0 @@ -/*! angular-breadcrumb - v0.1.0 - 2014-04-29 -* https://github.com/ncuillery/angular-breadcrumb -* Copyright (c) 2014 Nicolas Cuillery; Licensed MIT */ -angular.module('ncy-angular-breadcrumb', ['ui.router.state']) - .provider('$breadcrumb', function() { - - var $$options = { - prefixStateName: null, - template: 'bootstrap3', - templateUrl: null - }; - - this.setOptions = function(options) { - angular.extend($$options, options); - }; - - var $pushNonexistentState = function(array, state) { - // Allow user to explicitly ignore state - if (state.data && (state.data.ncyBreadcrumbLabel === false)) { - return false; - } - var stateAlreadyInArray = false; - angular.forEach(array, function(value) { - if(!stateAlreadyInArray && angular.equals(value, state)) { - stateAlreadyInArray = true; - } - }); - if(!stateAlreadyInArray) { - array.push(state); - } - return stateAlreadyInArray; - }; - - this.$get = ['$state', function($state) { - - return { - getTemplate: function(templates) { - if($$options.templateUrl) { - // templateUrl takes precedence over template - return null; - } else if(templates[$$options.template]) { - // Predefined templates (bootstrap, ...) - return templates[$$options.template]; - } else { - return $$options.template; - } - }, - getTemplateUrl: function() { - return $$options.templateUrl; - }, - getStatesChain: function() { - var chain = []; - - // Prefix state treatment - if($$options.prefixStateName) { - var prefixState = $state.get($$options.prefixStateName); - if(prefixState) { - var prefixStep = angular.extend(prefixState, {ncyBreadcrumbLink: $state.href(prefixState)}); - $pushNonexistentState(chain, prefixStep); - } else { - throw 'Bad configuration : prefixState "' + $$options.prefixStateName + '" unknown'; - } - } - - angular.forEach($state.$current.path, function(value) { - var step = angular.extend(value.self, {ncyBreadcrumbLink: $state.href(value)}); - $pushNonexistentState(chain, step); - }); - - return chain; - } - }; - }]; - - }) - .directive('ncyBreadcrumb', ['$state', '$interpolate', '$breadcrumb', '$rootScope', function ($state, $interpolate, $breadcrumb, $rootScope) { - this.$$templates = { - bootstrap2: '', - bootstrap3: '' - }; - - return { - replace: true, - scope: {}, - template: $breadcrumb.getTemplate(this.$$templates), - templateUrl: $breadcrumb.getTemplateUrl(), - link: { - post: function postLink(scope) { - $rootScope.$on('$viewContentLoaded', function (event) { - scope.steps = $breadcrumb.getStatesChain(); - angular.forEach(scope.steps, function (value) { - if (value.data && value.data.ncyBreadcrumbLabel) { - var parseLabel = $interpolate(value.data.ncyBreadcrumbLabel); - value.ncyBreadcrumbLabel = parseLabel(event.targetScope); - } else { - value.ncyBreadcrumbLabel = value.name; - } - }); - }); - } - } - }; - }]); - diff --git a/app/assets/javascripts/legacy/vendor/moment.js b/app/assets/javascripts/legacy/vendor/moment.js deleted file mode 100644 index 6798876a3..000000000 --- a/app/assets/javascripts/legacy/vendor/moment.js +++ /dev/null @@ -1,5 +0,0 @@ -angular.module('cortex.vendor.moment', []) - -.config(function($provide) { - $provide.constant('moment', window.moment); -}); diff --git a/app/assets/javascripts/legacy/vendor/placeholders-img.js b/app/assets/javascripts/legacy/vendor/placeholders-img.js deleted file mode 100644 index 9bc91221b..000000000 --- a/app/assets/javascripts/legacy/vendor/placeholders-img.js +++ /dev/null @@ -1,146 +0,0 @@ -/** - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/** - * Creates a placeholder image client-side for use during design and - * development. - * - * TODO: Right now, it only supports `img` tags. This should be enforced in code - * and default to adding a CSS `background-image` for non-`img` elements. - */ -angular.module( 'placeholders.img', [] ) -.directive( 'phImg', function () { - return { - restrict: 'A', - scope: { dimensions: '@phImg', text: '@phText' }, - link: function( scope, element, attr ) { - // A reference to a canvas that we can reuse - var canvas; - - /** - * The configurable parameters of the placeholder image. - * - * TODO: make configurable - * TODO: make defaultable - */ - var config = { - text_size: 10, - fill_color: '#EEEEEE', - text_color: '#AAAAAA' - }; - - /** - * When the provided dimensions change, re-pull the width and height and - * then redraw the image. - */ - scope.$watch('dimensions', function () { - if( ! angular.isDefined( scope.dimensions ) ) { - return; - } - var matches = scope.dimensions.match( /^(\d+)x(\d+)$/ ), - dataUrl; - - if( ! matches ) { - console.error("Expected '000x000'. Got " + scope.dimensions); - return; - } - - // Grab the provided dimensions. - scope.size = { w: matches[1], h: matches[2] }; - - // FIXME: only add these if not already present - element.prop( "title", scope.dimensions ); - element.prop( "alt", scope.dimensions ); - - // And draw the image, getting the returned data URL. - dataUrl = drawImage(); - - // If this is an `img` tag, set the src as the data URL. Else, we set - // the CSS `background-image` property to same. - if ( element.prop( "tagName" ) === "IMG" ) { - element.prop( 'src', dataUrl ); - } else { - element.css( 'background-image', 'url("' + dataUrl + '")' ); - } - }); - - /** - * Calculate the maximum height of the text we can draw, based on the - * requested dimensions of the image. - */ - function getTextSize() { - var dimension_arr = [scope.size.h, scope.size.w].sort(), - maxFactor = Math.round(dimension_arr[1] / 16); - - return Math.max(config.text_size, maxFactor); - } - - /** - * Using the HTML5 canvas API, draw a placeholder image of the requested - * size with text centered vertically and horizontally that specifies its - * dimensions. Returns the data URL that can be used as an `img`'s `src` - * attribute. - */ - function drawImage() { - // Create a new canvas if we don't already have one. We reuse the canvas - // when if gets redrawn so as not to be wasteful. - canvas = canvas || document.createElement( 'canvas' ); - - // Obtain a 2d drawing context on which we can add the placeholder - // image. - var context = canvas.getContext( '2d' ), - text_size, - text; - - // Set the canvas to the appropriate size. - canvas.width = scope.size.w; - canvas.height = scope.size.h; - - // Draw the placeholder image square. - // TODO: support other shapes - // TODO: support configurable colors - context.fillStyle = config.fill_color; - context.fillRect( 0, 0, scope.size.w, scope.size.h ); - - // Add the dimension text. - // TODO: support configurable font - // FIXME: ensure text will fit and resize if it doesn't - text_size = getTextSize(); - text = scope.text || scope.dimensions; - context.fillStyle = config.text_color; - context.textAlign = 'center'; - context.textBaseline = 'middle'; - context.font = 'bold '+text_size+'pt sans-serif'; - - // If the text is too long to fit, reduce it until it will. - if (context.measureText( text ).width / scope.size.w > 1) { - text_size = config.text_size / (context.measureText( text ).width / scope.size.w); - context.font = 'bold '+text_size+'pt sans-serif'; - } - - // Finally, draw the text in its calculated position. - context.fillText( text, scope.size.w / 2, scope.size.h / 2 ); - - // Get the data URL and return it. - return canvas.toDataURL("image/png"); - } - } - }; -}); diff --git a/app/assets/javascripts/legacy/vendor/redactor.js b/app/assets/javascripts/legacy/vendor/redactor.js deleted file mode 100644 index fe045dbe3..000000000 --- a/app/assets/javascripts/legacy/vendor/redactor.js +++ /dev/null @@ -1,10030 +0,0 @@ -/* - Redactor 10.2.1 - Updated: July 6, 2015 - - http://imperavi.com/redactor/ - - Copyright (c) 2009-2015, Imperavi LLC. - License: http://imperavi.com/redactor/license/ - - Usage: $('#content').redactor(); -*/ - -(function($) -{ - - 'use strict'; - - if (!Function.prototype.bind) - { - Function.prototype.bind = function(scope) - { - var fn = this; - return function() - { - return fn.apply(scope); - }; - }; - } - - var uuid = 0; - - // Plugin - $.fn.redactor = function(options) - { - var val = []; - var args = Array.prototype.slice.call(arguments, 1); - - if (typeof options === 'string') - { - this.each(function() - { - var instance = $.data(this, 'redactor'); - var func; - - if (options.search(/\./) != '-1') - { - func = options.split('.'); - if (typeof instance[func[0]] != 'undefined') - { - func = instance[func[0]][func[1]]; - } - } - else - { - func = instance[options]; - } - - if (typeof instance !== 'undefined' && $.isFunction(func)) - { - var methodVal = func.apply(instance, args); - if (methodVal !== undefined && methodVal !== instance) - { - val.push(methodVal); - } - } - else - { - $.error('No such method "' + options + '" for Redactor'); - } - }); - } - else - { - this.each(function() - { - $.data(this, 'redactor', {}); - $.data(this, 'redactor', Redactor(this, options)); - }); - } - - if (val.length === 0) return this; - else if (val.length === 1) return val[0]; - else return val; - - }; - - // Initialization - function Redactor(el, options) - { - return new Redactor.prototype.init(el, options); - } - - // Functionality - $.Redactor = Redactor; - $.Redactor.VERSION = '10.2.2'; - $.Redactor.modules = ['alignment', 'autosave', 'block', 'buffer', 'build', 'button', - 'caret', 'clean', 'code', 'core', 'dropdown', 'file', 'focus', - 'image', 'indent', 'inline', 'insert', 'keydown', 'keyup', - 'lang', 'line', 'link', 'linkify', 'list', 'modal', 'observe', 'paragraphize', - 'paste', 'placeholder', 'progress', 'selection', 'shortcuts', - 'tabifier', 'tidy', 'toolbar', 'upload', 'utils']; - - $.Redactor.opts = { - - // settings - lang: 'en', - direction: 'ltr', // ltr or rtl - - plugins: false, // array - - focus: false, - focusEnd: false, - - placeholder: false, - - visual: true, - tabindex: false, - - minHeight: false, - maxHeight: false, - - linebreaks: false, - replaceDivs: true, - paragraphize: true, - cleanStyleOnEnter: false, - enterKey: true, - - cleanOnPaste: true, - cleanSpaces: true, - pastePlainText: false, - - autosave: false, // false or url - autosaveName: false, - autosaveInterval: 60, // seconds - autosaveOnChange: false, - autosaveFields: false, - - linkTooltip: true, - linkProtocol: 'http', - linkNofollow: false, - linkSize: 50, - - imageEditable: true, - imageLink: true, - imagePosition: true, - imageFloatMargin: '10px', - imageResizable: true, - - imageUpload: null, - imageUploadParam: 'file', - - uploadImageField: false, - - dragImageUpload: true, - - fileUpload: null, - fileUploadParam: 'file', - - dragFileUpload: true, - - s3: false, - - convertLinks: true, - convertUrlLinks: true, - convertImageLinks: true, - convertVideoLinks: true, - - preSpaces: 4, // or false - tabAsSpaces: false, // true or number of spaces - tabKey: true, - - scrollTarget: false, - - toolbar: true, - /* concrete5 */ - /*toolbarFixed: true,*/ - toolbarFixed: false, - /* end concrete5 */ - toolbarFixedTarget: document, - toolbarFixedTopOffset: 0, // pixels - toolbarExternal: false, // ID selector - toolbarOverflow: false, - - source: true, - buttons: ['html', 'formatting', 'bold', 'italic', 'deleted', 'unorderedlist', 'orderedlist', - 'outdent', 'indent', 'image', /* concrete5 'file', */ 'link', 'alignment', 'horizontalrule'], // + 'underline' - - buttonsHide: [], - buttonsHideOnMobile: [], - - formatting: ['p', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'], - formattingAdd: false, - - tabifier: true, - - deniedTags: ['script', 'style'], - allowedTags: false, // or array - - paragraphizeBlocks: ['table', 'div', 'pre', 'form', 'ul', 'ol', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'dl', 'blockquote', 'figcaption', - 'address', 'section', 'header', 'footer', 'aside', 'article', 'object', 'style', 'script', 'iframe', 'select', 'input', 'textarea', - 'button', 'option', 'map', 'area', 'math', 'hr', 'fieldset', 'legend', 'hgroup', 'nav', 'figure', 'details', 'menu', 'summary', 'p'], - - removeComments: false, - replaceTags: [ - ['strike', 'del'], - ['b', 'strong'] - ], - replaceStyles: [ - ['font-weight:\\s?bold', "strong"], - ['font-style:\\s?italic', "em"], - ['text-decoration:\\s?underline', "u"], - ['text-decoration:\\s?line-through', 'del'] - ], - removeDataAttr: false, - - removeAttr: false, // or multi array - allowedAttr: false, // or multi array - - removeWithoutAttr: ['span'], // or false - removeEmpty: ['p'], // or false; - - activeButtons: ['deleted', 'italic', 'bold', 'underline', 'unorderedlist', 'orderedlist', - 'alignleft', 'aligncenter', 'alignright', 'justify'], - activeButtonsStates: { - b: 'bold', - strong: 'bold', - i: 'italic', - em: 'italic', - del: 'deleted', - strike: 'deleted', - ul: 'unorderedlist', - ol: 'orderedlist', - u: 'underline' - }, - - shortcuts: { - 'ctrl+shift+m, meta+shift+m': { func: 'inline.removeFormat' }, - 'ctrl+b, meta+b': { func: 'inline.format', params: ['bold'] }, - 'ctrl+i, meta+i': { func: 'inline.format', params: ['italic'] }, - 'ctrl+h, meta+h': { func: 'inline.format', params: ['superscript'] }, - 'ctrl+l, meta+l': { func: 'inline.format', params: ['subscript'] }, - 'ctrl+k, meta+k': { func: 'link.show' }, - 'ctrl+shift+7': { func: 'list.toggle', params: ['orderedlist'] }, - 'ctrl+shift+8': { func: 'list.toggle', params: ['unorderedlist'] } - }, - shortcutsAdd: false, - - concrete5: { - filemanager: false, - sitemap: false, - lightbox: false - }, - - // private - buffer: [], - rebuffer: [], - emptyHtml: '

', - invisibleSpace: '​', - imageTypes: ['image/png', 'image/jpeg', 'image/gif'], - indentValue: 20, - verifiedTags: ['a', 'img', 'b', 'strong', 'sub', 'sup', 'i', 'em', 'u', 'small', 'strike', 'del', 'cite', 'ul', 'ol', 'li'], // and for span tag special rule - inlineTags: ['strong', 'b', 'u', 'em', 'i', 'code', 'del', 'ins', 'samp', 'kbd', 'sup', 'sub', 'mark', 'var', 'cite', 'small'], - alignmentTags: ['P', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'DL', 'DT', 'DD', 'DIV', 'TD', 'BLOCKQUOTE', 'OUTPUT', 'FIGCAPTION', 'ADDRESS', 'SECTION', 'HEADER', 'FOOTER', 'ASIDE', 'ARTICLE'], - blockLevelElements: ['PRE', 'UL', 'OL', 'LI'], - highContrast: false, - observe: { - dropdowns: [] - }, - - // lang - langs: { - en: { - html: 'HTML', - video: 'Insert Video', - image: 'Insert Image', - table: 'Table', - link: 'Link', - link_insert: 'Insert link', - link_edit: 'Edit link', - unlink: 'Unlink', - formatting: 'Formatting', - paragraph: 'Normal text', - quote: 'Quote', - code: 'Code', - header1: 'Header 1', - header2: 'Header 2', - header3: 'Header 3', - header4: 'Header 4', - header5: 'Header 5', - bold: 'Bold', - italic: 'Italic', - fontcolor: 'Font Color', - backcolor: 'Back Color', - unorderedlist: 'Unordered List', - orderedlist: 'Ordered List', - outdent: 'Outdent', - indent: 'Indent', - cancel: 'Cancel', - insert: 'Insert', - save: 'Save', - _delete: 'Delete', - insert_table: 'Insert Table', - insert_row_above: 'Add Row Above', - insert_row_below: 'Add Row Below', - insert_column_left: 'Add Column Left', - insert_column_right: 'Add Column Right', - delete_column: 'Delete Column', - delete_row: 'Delete Row', - delete_table: 'Delete Table', - rows: 'Rows', - columns: 'Columns', - add_head: 'Add Head', - delete_head: 'Delete Head', - alt: 'Alt', - image_position: 'Position', - none: 'None', - left: 'Left', - right: 'Right', - center: 'Center', - image_web_link: 'Image Web Link', - text: 'Text', - mailto: 'Email', - web: 'URL', - video_html_code: 'Video Embed Code or Youtube/Vimeo Link', - file: 'Insert File', - upload: 'Upload', - download: 'Download', - choose: 'Choose', - or_choose: 'Or choose', - drop_file_here: 'Drop file here', - align_left: 'Align text to the left', - align_center: 'Center text', - align_right: 'Align text to the right', - align_justify: 'Justify text', - horizontalrule: 'Insert Horizontal Rule', - deleted: 'Deleted', - anchor: 'Anchor', - link_new_tab: 'Open link in new tab', - /* concrete5 */ - link_same_window: 'Open link in same window', - in_lightbox: 'Open link in Lightbox', - lightbox_link_type: 'Link Type', - lightbox_link_type_iframe: 'Web Page', - lightbox_link_type_image: 'Image', - lightbox_link_type_iframe_options: 'Frame Options', - lightbox_link_type_iframe_width: 'Width', - lightbox_link_type_iframe_height: 'Height', - customStyles: 'Custom Styles', - remove_font: 'Remove font', - change_font_family: 'Change font family', - remove_font_size: 'Remove font size', - change_font_size: 'Change font size', - remove_style: 'Remove Style', - insert_character: 'Insert Character', - undo: 'Undo', - redo: 'Redo', - remove_font_family: 'Remove Font Family', - // Remember to add new strings also in in /concrete/controllers/frontend/assets_localization.php, function getRedactorJavascript - /* end concrete5 */ - underline: 'Underline', - alignment: 'Alignment', - filename: 'Name (optional)', - edit: 'Edit', - upload_label: 'Drop file here or ' - } - }, - - linkify: { - regexps: { - youtube: /https?:\/\/(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube\.com\S*[^\w\-\s])([\w\-]{11})(?=[^\w\-]|$)(?![?=&+%\w.\-]*(?:['"][^<>]*>|<\/a>))[?=&+%\w.-]*/ig, - vimeo: /https?:\/\/(www\.)?vimeo.com\/(\d+)($|\/)/, - image: /((https?|www)[^\s]+\.)(jpe?g|png|gif)(\?[^\s-]+)?/ig, - url: /(https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/ig, - } - }, - - codemirror: false - }; - - // Functionality - Redactor.fn = $.Redactor.prototype = { - - keyCode: { - BACKSPACE: 8, - DELETE: 46, - UP: 38, - DOWN: 40, - ENTER: 13, - SPACE: 32, - ESC: 27, - TAB: 9, - CTRL: 17, - META: 91, - SHIFT: 16, - ALT: 18, - RIGHT: 39, - LEFT: 37, - LEFT_WIN: 91 - }, - - // Initialization - init: function(el, options) - { - this.$element = $(el); - this.uuid = uuid++; - - // if paste event detected = true - this.rtePaste = false; - this.$pasteBox = false; - - this.loadOptions(options); - this.loadModules(); - - // formatting storage - this.formatting = {}; - - // block level tags - $.merge(this.opts.blockLevelElements, this.opts.alignmentTags); - this.reIsBlock = new RegExp('^(' + this.opts.blockLevelElements.join('|' ) + ')$', 'i'); - - // setup allowed and denied tags - this.tidy.setupAllowed(); - - // setup denied tags - if (this.opts.deniedTags !== false) - { - var tags = ['html', 'head', 'link', 'body', 'meta', 'applet']; - for (var i = 0; i < tags.length; i++) - { - this.opts.deniedTags.push(tags[i]); - } - } - - // load lang - this.lang.load(); - - // extend shortcuts - $.extend(this.opts.shortcuts, this.opts.shortcutsAdd); - - // start callback - this.core.setCallback('start'); - - // build - this.start = true; - this.build.run(); - }, - - loadOptions: function(options) - { - this.opts = $.extend( - {}, - $.extend(true, {}, $.Redactor.opts), - this.$element.data(), - options - ); - }, - getModuleMethods: function(object) - { - return Object.getOwnPropertyNames(object).filter(function(property) - { - return typeof object[property] == 'function'; - }); - }, - loadModules: function() - { - var len = $.Redactor.modules.length; - for (var i = 0; i < len; i++) - { - this.bindModuleMethods($.Redactor.modules[i]); - } - }, - bindModuleMethods: function(module) - { - if (typeof this[module] == 'undefined') return; - - // init module - this[module] = this[module](); - - var methods = this.getModuleMethods(this[module]); - var len = methods.length; - - // bind methods - for (var z = 0; z < len; z++) - { - this[module][methods[z]] = this[module][methods[z]].bind(this); - } - }, - alignment: function() - { - return { - left: function() - { - this.alignment.set(''); - }, - right: function() - { - this.alignment.set('right'); - }, - center: function() - { - this.alignment.set('center'); - }, - justify: function() - { - this.alignment.set('justify'); - }, - set: function(type) - { - // focus - if (!this.utils.browser('msie')) this.$editor.focus(); - - this.buffer.set(); - this.selection.save(); - - // get blocks - this.alignment.blocks = this.selection.getBlocks(); - this.alignment.type = type; - - // set alignment - if (this.alignment.isLinebreaksOrNoBlocks()) - { - this.alignment.setText(); - } - else - { - this.alignment.setBlocks(); - } - - // sync - this.selection.restore(); - this.code.sync(); - }, - setText: function() - { - var wrapper = this.selection.wrap('div'); - $(wrapper).attr('data-tagblock', 'redactor').css('text-align', this.alignment.type); - }, - setBlocks: function() - { - $.each(this.alignment.blocks, $.proxy(function(i, el) - { - var $el = this.utils.getAlignmentElement(el); - if (!$el) return; - - if (this.alignment.isNeedReplaceElement($el)) - { - this.alignment.replaceElement($el); - } - else - { - this.alignment.alignElement($el); - } - - }, this)); - }, - isLinebreaksOrNoBlocks: function() - { - return (this.opts.linebreaks && this.alignment.blocks[0] === false); - }, - isNeedReplaceElement: function($el) - { - return (this.alignment.type === '' && typeof($el.data('tagblock')) !== 'undefined'); - }, - replaceElement: function($el) - { - $el.replaceWith($el.html()); - }, - alignElement: function($el) - { - $el.css('text-align', this.alignment.type); - this.utils.removeEmptyAttr($el, 'style'); - } - }; - }, - autosave: function() - { - return { - html: false, - enable: function() - { - if (!this.opts.autosave) return; - - this.autosave.name = (this.opts.autosaveName) ? this.opts.autosaveName : this.$textarea.attr('name'); - - if (this.opts.autosaveOnChange) return; - this.autosaveInterval = setInterval(this.autosave.load, this.opts.autosaveInterval * 1000); - }, - onChange: function() - { - if (!this.opts.autosaveOnChange) return; - this.autosave.load(); - }, - load: function() - { - this.autosave.source = this.code.get(); - - if (this.autosave.html === this.autosave.source) return; - - // data - var data = {}; - data['name'] = this.autosave.name; - data[this.autosave.name] = this.autosave.source; - data = this.autosave.getHiddenFields(data); - - // ajax - var jsxhr = $.ajax({ - url: this.opts.autosave, - type: 'post', - data: data - }); - - jsxhr.done(this.autosave.success); - }, - getHiddenFields: function(data) - { - if (this.opts.autosaveFields === false || typeof this.opts.autosaveFields !== 'object') - { - return data; - } - - $.each(this.opts.autosaveFields, $.proxy(function(k, v) - { - if (v !== null && v.toString().indexOf('#') === 0) v = $(v).val(); - data[k] = v; - - }, this)); - - return data; - - }, - success: function(data) - { - var json; - try - { - json = $.parseJSON(data); - } - catch(e) - { - //data has already been parsed - json = data; - } - - var callbackName = (typeof json.error == 'undefined') ? 'autosave' : 'autosaveError'; - - this.core.setCallback(callbackName, this.autosave.name, json); - this.autosave.html = this.autosave.source; - }, - disable: function() - { - clearInterval(this.autosaveInterval); - } - }; - }, - block: function() - { - return { - formatting: function(name) - { - this.block.clearStyle = false; - var type, value; - - if (typeof this.formatting[name].data != 'undefined') type = 'data'; - else if (typeof this.formatting[name].attr != 'undefined') type = 'attr'; - else if (typeof this.formatting[name]['class'] != 'undefined') type = 'class'; - - if (typeof this.formatting[name].clear != 'undefined') - { - this.block.clearStyle = true; - } - - if (type) value = this.formatting[name][type]; - - this.block.format(this.formatting[name].tag, type, value); - - }, - format: function(tag, type, value) - { - if (tag == 'quote') tag = 'blockquote'; - - var formatTags = ['p', 'pre', 'blockquote', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6']; - if ($.inArray(tag, formatTags) == -1) return; - - this.block.isRemoveInline = (tag == 'pre' || tag.search(/h[1-6]/i) != -1); - - // focus - if (!this.utils.browser('msie')) this.$editor.focus(); - - var html = $.trim(this.$editor.html()); - this.block.isEmpty = this.utils.isEmpty(html); - - // FF focus - if (this.utils.browser('mozilla') && !this.focus.isFocused()) - { - if (this.block.isEmpty) - { - var $first; - if (!this.opts.linebreaks) - { - $first = this.$editor.children().first(); - this.caret.setEnd($first); - } - } - } - - this.block.blocks = this.selection.getBlocks(); - - this.block.blocksSize = this.block.blocks.length; - this.block.type = type; - this.block.value = value; - - this.buffer.set(); - this.selection.save(); - - this.block.set(tag); - - this.selection.restore(); - this.code.sync(); - this.observe.load(); - - }, - set: function(tag) - { - - this.selection.get(); - this.block.containerTag = this.range.commonAncestorContainer.tagName; - - if (this.range.collapsed) - { - this.block.setCollapsed(tag); - } - else - { - this.block.setMultiple(tag); - } - }, - setCollapsed: function(tag) - { - if (this.opts.linebreaks && this.block.isEmpty && tag != 'p') - { - var node = document.createElement(tag); - this.$editor.html(node); - this.caret.setEnd(node); - - return; - } - - - var block = this.block.blocks[0]; - if (block === false) return; - - if (block.tagName == 'LI') - { - if (tag != 'blockquote') return; - - this.block.formatListToBlockquote(); - return; - } - - var isContainerTable = (this.block.containerTag == 'TD' || this.block.containerTag == 'TH'); - if (isContainerTable && !this.opts.linebreaks) - { - document.execCommand('formatblock', false, '<' + tag + '>'); - - block = this.selection.getBlock(); - this.block.toggle($(block)); - - } - else if (block.tagName.toLowerCase() != tag) - { - if (this.opts.linebreaks && tag == 'p') - { - $(block).append('
'); - this.utils.replaceWithContents(block); - } - else - { - var $formatted = this.utils.replaceToTag(block, tag); - - this.block.toggle($formatted); - - if (tag != 'p' && tag != 'blockquote') $formatted.find('img').remove(); - if (this.block.isRemoveInline) this.utils.removeInlineTags($formatted); - if (tag == 'p' || this.block.headTag) $formatted.find('p').contents().unwrap(); - - this.block.formatTableWrapping($formatted); - } - } - else if (tag == 'blockquote' && block.tagName.toLowerCase() == tag) - { - // blockquote off - if (this.opts.linebreaks) - { - $(block).append('
'); - this.utils.replaceWithContents(block); - } - else - { - var $el = this.utils.replaceToTag(block, 'p'); - this.block.toggle($el); - } - } - else if (block.tagName.toLowerCase() == tag) - { - this.block.toggle($(block)); - } - - - - if (typeof this.block.type == 'undefined' && typeof this.block.value == 'undefined') - { - $(block).removeAttr('class').removeAttr('style'); - } - - }, - setMultiple: function(tag) - { - var block = this.block.blocks[0]; - var isContainerTable = (this.block.containerTag == 'TD' || this.block.containerTag == 'TH'); - - if (block !== false && this.block.blocksSize === 1) - { - if (block.tagName.toLowerCase() == tag && tag == 'blockquote') - { - // blockquote off - if (this.opts.linebreaks) - { - $(block).append('
'); - this.utils.replaceWithContents(block); - } - else - { - var $el = this.utils.replaceToTag(block, 'p'); - this.block.toggle($el); - } - } - else if (block.tagName == 'LI') - { - if (tag != 'blockquote') return; - - this.block.formatListToBlockquote(); - } - else if (this.block.containerTag == 'BLOCKQUOTE') - { - this.block.formatBlockquote(tag); - } - else if (this.opts.linebreaks && ((isContainerTable) || (this.range.commonAncestorContainer != block))) - { - this.block.formatWrap(tag); - } - else - { - if (this.opts.linebreaks && tag == 'p') - { - $(block).prepend('
').append('
'); - this.utils.replaceWithContents(block); - } - else if (block.tagName === 'TD') - { - this.block.formatWrap(tag); - } - else - { - var $formatted = this.utils.replaceToTag(block, tag); - - this.block.toggle($formatted); - - if (this.block.isRemoveInline) this.utils.removeInlineTags($formatted); - if (tag == 'p' || this.block.headTag) $formatted.find('p').contents().unwrap(); - } - } - } - else - { - if (this.opts.linebreaks || tag != 'p') - { - if (tag == 'blockquote') - { - var count = 0; - for (var i = 0; i < this.block.blocksSize; i++) - { - if (this.block.blocks[i].tagName == 'BLOCKQUOTE') count++; - } - - // only blockquote selected - if (count == this.block.blocksSize) - { - $.each(this.block.blocks, $.proxy(function(i,s) - { - var $formatted = false; - if (this.opts.linebreaks) - { - $(s).prepend('
').append('
'); - $formatted = this.utils.replaceWithContents(s); - } - else - { - $formatted = this.utils.replaceToTag(s, 'p'); - } - - if ($formatted && typeof this.block.type == 'undefined' && typeof this.block.value == 'undefined') - { - $formatted.removeAttr('class').removeAttr('style'); - } - - }, this)); - - return; - } - - } - - this.block.formatWrap(tag); - } - else - { - var classSize = 0; - var toggleType = false; - if (this.block.type == 'class') - { - toggleType = 'toggle'; - classSize = $(this.block.blocks).filter('.' + this.block.value).length; - - if (this.block.blocksSize == classSize) toggleType = 'toggle'; - else if (this.block.blocksSize > classSize) toggleType = 'set'; - else if (classSize === 0) toggleType = 'set'; - - } - - var exceptTags = ['ul', 'ol', 'li', 'td', 'th', 'dl', 'dt', 'dd']; - $.each(this.block.blocks, $.proxy(function(i,s) - { - if ($.inArray(s.tagName.toLowerCase(), exceptTags) != -1) return; - - var $formatted = this.utils.replaceToTag(s, tag); - - if (toggleType) - { - if (toggleType == 'toggle') this.block.toggle($formatted); - else if (toggleType == 'remove') this.block.remove($formatted); - else if (toggleType == 'set') this.block.setForce($formatted); - } - else this.block.toggle($formatted); - - if (tag != 'p' && tag != 'blockquote') $formatted.find('img').remove(); - if (this.block.isRemoveInline) this.utils.removeInlineTags($formatted); - if (tag == 'p' || this.block.headTag) $formatted.find('p').contents().unwrap(); - - if (typeof this.block.type == 'undefined' && typeof this.block.value == 'undefined') - { - $formatted.removeAttr('class').removeAttr('style'); - } - - - }, this)); - } - } - }, - setForce: function($el) - { - // remove style and class if the specified setting - if (this.block.clearStyle) - { - $el.removeAttr('class').removeAttr('style'); - } - - if (this.block.type == 'class') - { - $el.addClass(this.block.value); - return; - } - else if (this.block.type == 'attr' || this.block.type == 'data') - { - $el.attr(this.block.value.name, this.block.value.value); - return; - } - }, - toggle: function($el) - { - // remove style and class if the specified setting - if (this.block.clearStyle) - { - $el.removeAttr('class').removeAttr('style'); - } - - if (this.block.type == 'class') - { - $el.toggleClass(this.block.value); - return; - } - else if (this.block.type == 'attr' || this.block.type == 'data') - { - if ($el.attr(this.block.value.name) == this.block.value.value) - { - $el.removeAttr(this.block.value.name); - } - else - { - $el.attr(this.block.value.name, this.block.value.value); - } - - return; - } - else - { - $el.removeAttr('style class'); - return; - } - }, - remove: function($el) - { - $el.removeClass(this.block.value); - }, - formatListToBlockquote: function() - { - var block = $(this.block.blocks[0]).closest('ul, ol', this.$editor[0]); - - $(block).find('ul, ol').contents().unwrap(); - $(block).find('li').append($('
')).contents().unwrap(); - - var $el = this.utils.replaceToTag(block, 'blockquote'); - this.block.toggle($el); - }, - formatBlockquote: function(tag) - { - document.execCommand('outdent'); - document.execCommand('formatblock', false, tag); - - this.clean.clearUnverified(); - this.$editor.find('p:empty').remove(); - - var formatted = this.selection.getBlock(); - - if (tag != 'p') - { - $(formatted).find('img').remove(); - } - - if (!this.opts.linebreaks) - { - this.block.toggle($(formatted)); - } - - this.$editor.find('ul, ol, tr, blockquote, p').each($.proxy(this.utils.removeEmpty, this)); - - if (this.opts.linebreaks && tag == 'p') - { - this.utils.replaceWithContents(formatted); - } - - }, - formatWrap: function(tag) - { - if (this.block.containerTag == 'UL' || this.block.containerTag == 'OL') - { - if (tag == 'blockquote') - { - this.block.formatListToBlockquote(); - } - else - { - return; - } - } - - var formatted = this.selection.wrap(tag); - if (formatted === false) return; - - var $formatted = $(formatted); - - this.block.formatTableWrapping($formatted); - - var $elements = $formatted.find(this.opts.blockLevelElements.join(',') + ', td, table, thead, tbody, tfoot, th, tr'); - - $elements.contents().unwrap(); - - if (tag != 'p' && tag != 'blockquote') $formatted.find('img').remove(); - - $.each(this.block.blocks, $.proxy(this.utils.removeEmpty, this)); - - $formatted.append(this.selection.getMarker(2)); - - if (!this.opts.linebreaks) - { - this.block.toggle($formatted); - } - - this.$editor.find('ul, ol, tr, blockquote, p').each($.proxy(this.utils.removeEmpty, this)); - $formatted.find('blockquote:empty').remove(); - - if (this.block.isRemoveInline) - { - this.utils.removeInlineTags($formatted); - } - - if (this.opts.linebreaks && tag == 'p') - { - this.utils.replaceWithContents($formatted); - } - - if (this.opts.linebreaks) - { - var $next = $formatted.next().next(); - if ($next.size() != 0 && $next[0].tagName === 'BR') - { - $next.remove(); - } - } - - - - }, - formatTableWrapping: function($formatted) - { - if ($formatted.closest('table', this.$editor[0]).length === 0) return; - - if ($formatted.closest('tr', this.$editor[0]).length === 0) $formatted.wrap(''); - if ($formatted.closest('td', this.$editor[0]).length === 0 && $formatted.closest('th').length === 0) - { - $formatted.wrap(''); - } - }, - removeData: function(name, value) - { - var blocks = this.selection.getBlocks(); - $(blocks).removeAttr('data-' + name); - - this.code.sync(); - }, - setData: function(name, value) - { - var blocks = this.selection.getBlocks(); - $(blocks).attr('data-' + name, value); - - this.code.sync(); - }, - toggleData: function(name, value) - { - var blocks = this.selection.getBlocks(); - $.each(blocks, function() - { - if ($(this).attr('data-' + name)) - { - $(this).removeAttr('data-' + name); - } - else - { - $(this).attr('data-' + name, value); - } - }); - }, - removeAttr: function(attr, value) - { - var blocks = this.selection.getBlocks(); - $(blocks).removeAttr(attr); - - this.code.sync(); - }, - setAttr: function(attr, value) - { - var blocks = this.selection.getBlocks(); - $(blocks).attr(attr, value); - - this.code.sync(); - }, - toggleAttr: function(attr, value) - { - var blocks = this.selection.getBlocks(); - $.each(blocks, function() - { - if ($(this).attr(name)) - { - $(this).removeAttr(name); - } - else - { - $(this).attr(name, value); - } - }); - }, - removeClass: function(className) - { - var blocks = this.selection.getBlocks(); - $(blocks).removeClass(className); - - this.utils.removeEmptyAttr(blocks, 'class'); - - this.code.sync(); - }, - setClass: function(className) - { - var blocks = this.selection.getBlocks(); - $(blocks).addClass(className); - - this.code.sync(); - }, - toggleClass: function(className) - { - var blocks = this.selection.getBlocks(); - $(blocks).toggleClass(className); - - this.code.sync(); - } - }; - }, - buffer: function() - { - return { - set: function(type) - { - if (typeof type == 'undefined' || type == 'undo') - { - this.buffer.setUndo(); - } - else - { - this.buffer.setRedo(); - } - }, - setUndo: function() - { - this.selection.save(); - this.opts.buffer.push(this.$editor.html()); - this.selection.restore(); - }, - setRedo: function() - { - this.selection.save(); - this.opts.rebuffer.push(this.$editor.html()); - this.selection.restore(); - }, - getUndo: function() - { - this.$editor.html(this.opts.buffer.pop()); - }, - getRedo: function() - { - this.$editor.html(this.opts.rebuffer.pop()); - }, - add: function() - { - this.opts.buffer.push(this.$editor.html()); - }, - undo: function() - { - if (this.opts.buffer.length === 0) return; - - this.buffer.set('redo'); - this.buffer.getUndo(); - - this.selection.restore(); - - setTimeout($.proxy(this.observe.load, this), 50); - }, - redo: function() - { - if (this.opts.rebuffer.length === 0) return; - - this.buffer.set('undo'); - this.buffer.getRedo(); - - this.selection.restore(); - - setTimeout($.proxy(this.observe.load, this), 50); - } - }; - }, - build: function() - { - return { - run: function() - { - this.build.createContainerBox(); - this.build.loadContent(); - this.build.loadEditor(); - this.build.enableEditor(); - this.build.setCodeAndCall(); - }, - isTextarea: function() - { - return (this.$element[0].tagName === 'TEXTAREA'); - }, - createContainerBox: function() - { - this.$box = $('
'); - }, - createTextarea: function() - { - this.$textarea = $(' -
- -
-
- -
- -
- -
-
- - - - diff --git a/app/assets/legacy_templates/locales/grid.html b/app/assets/legacy_templates/locales/grid.html deleted file mode 100644 index 59bfb762b..000000000 --- a/app/assets/legacy_templates/locales/grid.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - -
{{ locale.name }}{{ locale.creator.fullname }}{{ locale.created_at|date:"y/MM/dd h:mm:ss a" }}{{ locale.updated_at|date:"y/MM/dd h:mm:ss a" }} -
- - - -
-
diff --git a/app/assets/legacy_templates/localizations/edit.html b/app/assets/legacy_templates/localizations/edit.html deleted file mode 100644 index 0fa84135c..000000000 --- a/app/assets/legacy_templates/localizations/edit.html +++ /dev/null @@ -1,35 +0,0 @@ -
-
-
-
- Provide Details -
-
-
- - -
- -
-
- -
- -
- -
-
-
-
-
- -
-
-
-
diff --git a/app/assets/legacy_templates/localizations/grid.html b/app/assets/legacy_templates/localizations/grid.html deleted file mode 100644 index bf22538e3..000000000 --- a/app/assets/legacy_templates/localizations/grid.html +++ /dev/null @@ -1,23 +0,0 @@ -
- - - - - - - - - - -
{{ localization.name }}{{ localization.creator.fullname }}{{ localization.created_at|date:"y/MM/dd h:mm:ss a" }}{{ localization.updated_at|date:"y/MM/dd h:mm:ss a" }} -
- - - -
-
-
diff --git a/app/assets/legacy_templates/main.html b/app/assets/legacy_templates/main.html deleted file mode 100644 index e8b36d139..000000000 --- a/app/assets/legacy_templates/main.html +++ /dev/null @@ -1,39 +0,0 @@ - - -
- -
-
- {{flash.message}} -
- -
-
- -
diff --git a/app/assets/legacy_templates/media/bulk.html b/app/assets/legacy_templates/media/bulk.html deleted file mode 100644 index ff974e6aa..000000000 --- a/app/assets/legacy_templates/media/bulk.html +++ /dev/null @@ -1,37 +0,0 @@ -
-
-
-
Select CSV detailing assets' metadata
-
- Please click here for a Bulk Media Upload CSV template, which includes some basic examples. Empty cell values will be ignored, while cell values of 'N/A' will clear out existing record values. - - -
-
- -
-
Select ZIP containing assets
-
- - -
-
- -
-
- -
- -
- -
-
-
-
diff --git a/app/assets/legacy_templates/media/edit.html b/app/assets/legacy_templates/media/edit.html deleted file mode 100644 index 13b2da7e5..000000000 --- a/app/assets/legacy_templates/media/edit.html +++ /dev/null @@ -1,156 +0,0 @@ -
-
-
-
- File Info -
-
- {{data.media.alt}} - -
-
Filename
-
{{data.media.attachment_file_name}}
- -
File Type
-
{{data.media.attachment_content_type}}
- -
File Size
-
{{data.media.attachment_file_size | bytes}}
- - -
Dimensions
-
{{data.media.dimensions[0]}} x {{data.media.dimensions[1]}}
-
- -
Author
-
{{data.media.creator.fullname}}
- -
Created
-
{{data.media.created_at | date:"y/M/d h:mm:ss a"}}
- -
Last Modified
-
{{data.media.updated_at | date:"y/M/d h:mm:ss a"}}
- -
Direct URL
-
{{data.media.url}}
- - -
Youtube Title
-
{{data.media.title}}
- -
Youtube Description
-
{{data.media.video_description}}
- -
Youtube Authors
-
{{data.media.authors | prettifyArrayString}}
-
-
-
-
-
- -
-
- - - Select File - - -

- - Please note that it can take 15-30 minutes before your new image will appear. - -

-
- - YouTube - - - -
- -
-
- Provide Details -
-
- -
-
-
- - -
-
- -
-
- -
- - - - -
-
-
-
- -
- - -
- -
- -
- - - - - - - -
-
- -
-
- -
- -
- -
-
-
-
-
-
-
diff --git a/app/assets/legacy_templates/media/grid.html b/app/assets/legacy_templates/media/grid.html deleted file mode 100644 index ace8d0fdf..000000000 --- a/app/assets/legacy_templates/media/grid.html +++ /dev/null @@ -1,115 +0,0 @@ - - -
-
-
-
- - -
- -
- items per page • Sort by -
- -
- - -
-
-
- -
-
- - Page {{ data.paging.page }} of {{ data.paging.pages }} -
- - -
-
- -
-
-
- - -
- {{ media.name }}
- {{ media.attachment_file_name }}
-
- Author: {{ media.creator.fullname }}
- Description: {{ media.description }}
- Tags: - - {{ tag }} - -
- -
- Created: {{ media.created_at|date:"y/M/d h:mm:ss a" }}
- Last Modified: {{ moment(media.updated_at).fromNow(); }}
-
- UID: {{ media.taxon }}
- Status: {{ media.deactive_at != null && (Date().new) > - moment(media.deactive_at).toDate() ? 'Deactive' : 'Active' }}
-
-
- - - -
-
-
-
-
diff --git a/app/assets/legacy_templates/media/manage.html b/app/assets/legacy_templates/media/manage.html deleted file mode 100644 index 3b6b8f398..000000000 --- a/app/assets/legacy_templates/media/manage.html +++ /dev/null @@ -1,2 +0,0 @@ - -
diff --git a/app/assets/legacy_templates/media/new.html b/app/assets/legacy_templates/media/new.html deleted file mode 100644 index 065bf541c..000000000 --- a/app/assets/legacy_templates/media/new.html +++ /dev/null @@ -1,111 +0,0 @@ -
-
-
-
- - - - Select File - - - - - YouTube - - - - - -
-
- -
-
-
-
- Provide Details -
-
- -
-
-
- - -
-
- -
-
- -
- - - - -
-
-
-
- -
- - -
- -
- -
- - - - - - - -
-
- -
-
- -
- -
- -
-
-
-
-
-
-
-
diff --git a/app/assets/legacy_templates/organizations/manage.html b/app/assets/legacy_templates/organizations/manage.html deleted file mode 100644 index f5c9fb466..000000000 --- a/app/assets/legacy_templates/organizations/manage.html +++ /dev/null @@ -1,52 +0,0 @@ -
-
- - - -
- -
-
- Hierarchy - -
- -
- -
-
-
-
- -
- - Details - -
- -
- -
- -
- -
-
-
-
-
diff --git a/app/assets/legacy_templates/posts/article/classify.html b/app/assets/legacy_templates/posts/article/classify.html deleted file mode 100644 index 28d36e5c6..000000000 --- a/app/assets/legacy_templates/posts/article/classify.html +++ /dev/null @@ -1,69 +0,0 @@ -
- -
- -
- - -
-
- -
-
- -
- - -
- -
-
- -
- - -
-
- -
-
- -
- - -
- - - - - - - -
-
diff --git a/app/assets/legacy_templates/posts/article/display.html b/app/assets/legacy_templates/posts/article/display.html deleted file mode 100644 index df7472141..000000000 --- a/app/assets/legacy_templates/posts/article/display.html +++ /dev/null @@ -1,84 +0,0 @@ -
- -
-
- - - -
-
-
- -
- - -
  • {{warning}}
- -
-
- {{data.post.featured_media.alt}} -
-
- {{data.post.featured_media.name}} - {{data.post.featured_media.taxon}} -
-
- - -
-
-
- -
- - -
  • {{warning}}
- -
-
- {{data.post.tile_media.alt}} -
-
- {{data.post.tile_media.name}} - {{data.post.tile_media.taxon}} -
-
- - -
-
-
diff --git a/app/assets/legacy_templates/posts/article/info.html b/app/assets/legacy_templates/posts/article/info.html deleted file mode 100644 index 14390a051..000000000 --- a/app/assets/legacy_templates/posts/article/info.html +++ /dev/null @@ -1,95 +0,0 @@ -
- - -
-
- -
-
- -
- - -
-
- -
-
- -
- - -
-
- -
-
- -
- - -
-
Self
- -
-
- - - -
- -
- - -
-

Consider disabling the WYSIWYG editor if you'd like to input raw HTML

-
diff --git a/app/assets/legacy_templates/posts/article/seo.html b/app/assets/legacy_templates/posts/article/seo.html deleted file mode 100644 index 3d29a3892..000000000 --- a/app/assets/legacy_templates/posts/article/seo.html +++ /dev/null @@ -1,72 +0,0 @@ -
- - -
-
- -
-
- -
- - -
-
- -
-
- -
- - -
- - -
-
- -
- -
-
- -
-
- -
-
- -
-
- -
-
- -
diff --git a/app/assets/legacy_templates/posts/edit.html b/app/assets/legacy_templates/posts/edit.html deleted file mode 100644 index 734207f93..000000000 --- a/app/assets/legacy_templates/posts/edit.html +++ /dev/null @@ -1,152 +0,0 @@ -
-
-
-
-
- -
-
- -
-
-
-
- -
-
-
-
-
- Publish/Distribute -
-
- -
-
- - -
-
-
-
- -
- - - - -
-
-
- -
- - - - -
-
-
-
-
-
- - -
-
-
-
- Please fill out the required fields, marked with a * -
-
- Slug "{{ data.post.slug }}" already taken, please use something else -
-
-
-
-
- - - Fields marked with * are required. Your input will be retained between tabs. -
-
- - -
diff --git a/app/assets/legacy_templates/posts/grid.html b/app/assets/legacy_templates/posts/grid.html deleted file mode 100644 index e03b73e6c..000000000 --- a/app/assets/legacy_templates/posts/grid.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - -
{{ post.title }}{{ post.type }}{{ post.published_at|publishStatus:post.draft }}{{ post.custom_author }}{{ post.categories|tagList }}{{ post.created_at|date:"y/MM/dd h:mm:ss a" }}{{ post.updated_at|date:"y/MM/dd h:mm:ss a" }}{{ post.is_sticky ? "\u2713" : "" }}{{ post.is_published ? "\u2713" : "" }}{{ post.tag_list.join(', ') }}
diff --git a/app/assets/legacy_templates/posts/manage.html b/app/assets/legacy_templates/posts/manage.html deleted file mode 100644 index 5e2ed6865..000000000 --- a/app/assets/legacy_templates/posts/manage.html +++ /dev/null @@ -1,2 +0,0 @@ - -
diff --git a/app/assets/legacy_templates/posts/popup.html b/app/assets/legacy_templates/posts/popup.html deleted file mode 100644 index a30b517ad..000000000 --- a/app/assets/legacy_templates/posts/popup.html +++ /dev/null @@ -1,13 +0,0 @@ - diff --git a/app/assets/legacy_templates/posts/promo/display.html b/app/assets/legacy_templates/posts/promo/display.html deleted file mode 100644 index 9923acf2d..000000000 --- a/app/assets/legacy_templates/posts/promo/display.html +++ /dev/null @@ -1,56 +0,0 @@ -
- -
-
- - - -
-
-
- -
- - -
  • {{warning}}
- -
-
- {{data.post.tile_media.alt}} -
-
- {{data.post.tile_media.name}} - {{data.post.tile_media.taxon}} -
-
- - -
-
-
diff --git a/app/assets/legacy_templates/posts/promo/info.html b/app/assets/legacy_templates/posts/promo/info.html deleted file mode 100644 index eeda934c8..000000000 --- a/app/assets/legacy_templates/posts/promo/info.html +++ /dev/null @@ -1,63 +0,0 @@ -
- - -
-
- -
-
- -
- - -
-
- -
-
- -
- - -
-
- -
-
- -
- - -
-
Self
- -
-
diff --git a/app/assets/legacy_templates/posts/promo/seo.html b/app/assets/legacy_templates/posts/promo/seo.html deleted file mode 100644 index ebb4dd115..000000000 --- a/app/assets/legacy_templates/posts/promo/seo.html +++ /dev/null @@ -1 +0,0 @@ -This section is not applicable to Promo Posts diff --git a/app/assets/legacy_templates/tenants/edit.html b/app/assets/legacy_templates/tenants/edit.html deleted file mode 100644 index d1dba595e..000000000 --- a/app/assets/legacy_templates/tenants/edit.html +++ /dev/null @@ -1,78 +0,0 @@ -
- - -
-

1. {{ levelName.charAt(0).toUpperCase() + levelName.slice(1) }} Information

- -
-
-
-
-
- - -
- - -
- -
- - -
- -
-
-
-
- -
-

2. Tenant Location in Organization Hierarchy

-

2. {{ levelName.charAt(0).toUpperCase() + levelName.slice(1) - }} Settings

- - - -
-
- -
-
- -
- -
- -
- -
-
-
diff --git a/app/assets/legacy_templates/tenants/manage.details.html b/app/assets/legacy_templates/tenants/manage.details.html deleted file mode 100644 index dedbbfbda..000000000 --- a/app/assets/legacy_templates/tenants/manage.details.html +++ /dev/null @@ -1,44 +0,0 @@ -

- -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Name:{{ data.tenants.selected.name }}
Contact Name{{ data.tenants.selected.contact_name }}
Contact Phone{{ data.tenants.selected.contact_phone }}
Contact Email{{ data.tenants.selected.contact_email }}
Activate Date{{ data.tenants.selected.active_at | date }}
Deactivate Date{{ data.tenants.selected.deactive_at | date }}
Contract Number{{ data.tenants.selected.contract }}
DID{{ data.tenants.selected.did }}
- -

Settings

- - \ No newline at end of file diff --git a/app/assets/legacy_templates/tenants/manage.tree.html b/app/assets/legacy_templates/tenants/manage.tree.html deleted file mode 100644 index 29cb62624..000000000 --- a/app/assets/legacy_templates/tenants/manage.tree.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/legacy_templates/users/bulk.html b/app/assets/legacy_templates/users/bulk.html deleted file mode 100644 index f1307ce31..000000000 --- a/app/assets/legacy_templates/users/bulk.html +++ /dev/null @@ -1,28 +0,0 @@ -
-
-
-
Select CSV detailing users' metadata
-
- Please click here for a Bulk Users Upload CSV template, which includes some basic examples. All users will be created with an initial password, 'welcome1'. - - -
-
- -
-
- -
- -
- -
-
-
-
diff --git a/app/assets/legacy_templates/users/edit.html b/app/assets/legacy_templates/users/edit.html deleted file mode 100644 index 0d545adeb..000000000 --- a/app/assets/legacy_templates/users/edit.html +++ /dev/null @@ -1,48 +0,0 @@ -
-
-
- Edit User Information -
-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
-
- -
- -
- -
-
-
-
-
-
diff --git a/app/assets/legacy_templates/users/facets.html b/app/assets/legacy_templates/users/facets.html deleted file mode 100644 index 86dfdbf2b..000000000 --- a/app/assets/legacy_templates/users/facets.html +++ /dev/null @@ -1,10 +0,0 @@ -
-
-
Tenant Selection
-
- -
-
-
- -
diff --git a/app/assets/legacy_templates/users/grid.html b/app/assets/legacy_templates/users/grid.html deleted file mode 100644 index 093152f4c..000000000 --- a/app/assets/legacy_templates/users/grid.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - -
{{ user.email }}{{ user.fullname }}{{ user.created_at|date:"y/MM/dd h:mm:ss a" }}{{ user.updated_at|date:"y/MM/dd h:mm:ss a" }} -
- - -
-
diff --git a/app/assets/legacy_templates/users/new.html b/app/assets/legacy_templates/users/new.html deleted file mode 100644 index 42a39b32f..000000000 --- a/app/assets/legacy_templates/users/new.html +++ /dev/null @@ -1,65 +0,0 @@ -
-
-
- New User Information -
-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
Passwords do not match!
-
- -
{{data.selectedTenant.name}}
-
-
- - -
-
-
- -
- -
- -
-
-
-
-
-
diff --git a/app/assets/legacy_templates/users/profile.html b/app/assets/legacy_templates/users/profile.html deleted file mode 100644 index 0449f711c..000000000 --- a/app/assets/legacy_templates/users/profile.html +++ /dev/null @@ -1,87 +0,0 @@ -
-
-
-
- Author Information - {{ data.user.fullname }} -
-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
- -
-
-
-
-
-
-
- Password Management -
-
-
-
- - -
-
- - -
-
- - -
- -
-
-
-
-
diff --git a/app/assets/legacy_templates/vendor/abn-tree.html b/app/assets/legacy_templates/vendor/abn-tree.html deleted file mode 100644 index f8cc864de..000000000 --- a/app/assets/legacy_templates/vendor/abn-tree.html +++ /dev/null @@ -1,9 +0,0 @@ - - \ No newline at end of file diff --git a/app/assets/legacy_templates/webpages/edit.html b/app/assets/legacy_templates/webpages/edit.html deleted file mode 100644 index 7922ace94..000000000 --- a/app/assets/legacy_templates/webpages/edit.html +++ /dev/null @@ -1,134 +0,0 @@ -
- - - Info -
-
-
- - -
-
- - -
-
-
-
- - SEO -
-
-
- - -
-
- - -
- -
- - -
- - -
-
- -
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
- - Dynamic Yield -
-
-
- - -
-
- - -
-
-
-
- - Widgets -
-
-
- - -
-
- - -
-
- - -
-
-
-
-
- - -
diff --git a/app/assets/legacy_templates/webpages/grid.html b/app/assets/legacy_templates/webpages/grid.html deleted file mode 100644 index ca3d6bfa6..000000000 --- a/app/assets/legacy_templates/webpages/grid.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - -
{{ webpage.name }}{{ webpage.url }}{{ webpage.creator.fullname }}{{ webpage.created_at|date:"y/MM/dd h:mm:ss a" }}{{ webpage.updated_at|date:"y/MM/dd h:mm:ss a" }} -
- - -
-
diff --git a/app/assets/legacy_templates/webpages/new.html b/app/assets/legacy_templates/webpages/new.html deleted file mode 100644 index f78d31b9c..000000000 --- a/app/assets/legacy_templates/webpages/new.html +++ /dev/null @@ -1,36 +0,0 @@ -
-
-
-
- Provide Details -
-
-
- - -
-
- - -
- -
-
- -
- -
- -
-
-
-
-
-
diff --git a/app/assets/stylesheets/legacy/bootstrap-cortex.scss b/app/assets/stylesheets/legacy/bootstrap-cortex.scss deleted file mode 100644 index a4a3f287e..000000000 --- a/app/assets/stylesheets/legacy/bootstrap-cortex.scss +++ /dev/null @@ -1,24 +0,0 @@ -$navbar-inverse-bg: #333333; -$navbar-inverse-link-color: #BFBFBF; -$border-radius-base: 0; - -@import 'bootstrap-sass-official/assets/stylesheets/bootstrap'; - -// Correct cursors for Angular Bootstrap -.nav, .pagination, .carousel, .panel-title a, [ng-click] { cursor: pointer; } - -.btn { - @include truncate; -} - -.label { - margin-right: $standard-margin / 4; -} - -.breadcrumb { - margin-bottom: $standard-margin; -} - -.modal { - z-index: 1054; // Priority over Redactor toolbar -} diff --git a/app/assets/stylesheets/legacy/cortex.scss b/app/assets/stylesheets/legacy/cortex.scss deleted file mode 100644 index 697eba0e5..000000000 --- a/app/assets/stylesheets/legacy/cortex.scss +++ /dev/null @@ -1,69 +0,0 @@ -main { - @extend .container-fluid; -} - -// Login -.flash_success, .reset-password { - margin-bottom: 12px; -} - -// Alerts -.alert-box { - @include make-xs-column(12); - @include make-md-column-offset(3); - @include make-md-column(6); - position: fixed; - left: 0; - right: 0; - bottom: 0; - z-index: 2; -} - -// Fix message flash transition -.alert-flash:not(.in) { - height: 0; - transition-property: all; -} - -// Transitions -.fade { - transition-property: all; - height: 0; - &.in { - height: auto; - } -} - -.fade-slow { - opacity: 0; - height: 0; - @include transition(opacity .3s linear); - transition-property: all; - &.in { - height: auto; - opacity: 1; - } -} - -// Cortex Navbar - screech! -.navbar { - margin-bottom: 0; -} - -.navbar-admin { - @extend .container-fluid; - - @media (min-width: $screen-md-min) { - .navbar-brand { - padding-left: 0; - } - } -} - -// Modal Dialogs -@media (min-width: $screen-md-min) { - .modal-xl { - width: $screen-lg-min; } } - -// AngularJS -[ng-click], [ui-sref] { cursor: pointer; } diff --git a/app/assets/stylesheets/legacy/directives/file-selector.scss b/app/assets/stylesheets/legacy/directives/file-selector.scss deleted file mode 100644 index 50fea1a67..000000000 --- a/app/assets/stylesheets/legacy/directives/file-selector.scss +++ /dev/null @@ -1,51 +0,0 @@ -@mixin striped-background-45($colorA, $colorB) { - background: repeating-linear-gradient( - 45deg, - $colorA, - $colorA 10px, - $colorB 10px, - $colorB 20px - ); -} - -file-selector { - input[type="file"] { - display: none; - } - .dropzone { - @extend .text-center; - @extend h3; - margin-top: 10px; - padding: 20px; - border: 2px dashed $gray-light; - @include striped-background-45($gray-lighter, #fff); - - &:hover { - color: darken($brand-primary, 10%); - border: 2px dashed lighten($brand-primary, 10%); - @include striped-background-45(lighten($brand-primary, 30%), #fff); - } - } - ul.files { - list-style-type: none; - padding: 0; - margin: 0; - li { - margin-top: 10px; - padding: 10px; - @extend .bg-success; - .remove { - display: none; - } - &:hover { - @extend .bg-danger; - .remove { - display: inline; - } - .present { - display: none; - } - } - } - } -} diff --git a/app/assets/stylesheets/legacy/directives/youtube-selector.scss b/app/assets/stylesheets/legacy/directives/youtube-selector.scss deleted file mode 100644 index 99bcc2555..000000000 --- a/app/assets/stylesheets/legacy/directives/youtube-selector.scss +++ /dev/null @@ -1,5 +0,0 @@ -youtube-selector { - iframe { - margin-top: 20px; - } -} diff --git a/app/assets/stylesheets/legacy/mixins.scss b/app/assets/stylesheets/legacy/mixins.scss deleted file mode 100644 index 958bbd55c..000000000 --- a/app/assets/stylesheets/legacy/mixins.scss +++ /dev/null @@ -1,26 +0,0 @@ -//////////////////////////////// -// Mixins - -// Placeholder content -@mixin placeholder { - &.placeholder { @content; } - &:-moz-placeholder { @content; } - &::-moz-placeholder { @content; } - &::-webkit-input-placeholder { @content; } - &:-ms-input-placeholder { @content; } -} - -//Cortex navbar background positioning for image sprites -@mixin navbar-bg-position($vertical-pos) { - background-position: center $vertical-pos; -} - -@mixin navbar-bg-position-dual($vertical-pos) { - background-position: center $vertical-pos, center bottom; -} - -@mixin truncate { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} diff --git a/app/assets/stylesheets/legacy/states/credentials.edit.scss b/app/assets/stylesheets/legacy/states/credentials.edit.scss deleted file mode 100644 index dac399277..000000000 --- a/app/assets/stylesheets/legacy/states/credentials.edit.scss +++ /dev/null @@ -1,5 +0,0 @@ -.credentials-edit { - .actions div { - @include make-lg-column(6); - } -} diff --git a/app/assets/stylesheets/legacy/states/credentials.new.scss b/app/assets/stylesheets/legacy/states/credentials.new.scss deleted file mode 100644 index f001f05bf..000000000 --- a/app/assets/stylesheets/legacy/states/credentials.new.scss +++ /dev/null @@ -1,5 +0,0 @@ -.credentials-new { - .actions div { - @include make-lg-column(6); - } -} diff --git a/app/assets/stylesheets/legacy/states/locales.edit.scss b/app/assets/stylesheets/legacy/states/locales.edit.scss deleted file mode 100644 index e0271aef1..000000000 --- a/app/assets/stylesheets/legacy/states/locales.edit.scss +++ /dev/null @@ -1,5 +0,0 @@ -.locale-edit { - .actions div { - @include make-md-column(6); - } -} diff --git a/app/assets/stylesheets/legacy/states/localizations.edit.scss b/app/assets/stylesheets/legacy/states/localizations.edit.scss deleted file mode 100644 index 1e80a8e4b..000000000 --- a/app/assets/stylesheets/legacy/states/localizations.edit.scss +++ /dev/null @@ -1,5 +0,0 @@ -.localization-edit { - .actions div { - @include make-md-column(6); - } -} diff --git a/app/assets/stylesheets/legacy/states/media.bulk.scss b/app/assets/stylesheets/legacy/states/media.bulk.scss deleted file mode 100644 index 9f91c2e55..000000000 --- a/app/assets/stylesheets/legacy/states/media.bulk.scss +++ /dev/null @@ -1,5 +0,0 @@ -.media-bulk { - .actions div { - @include make-lg-column(6); - } -} diff --git a/app/assets/stylesheets/legacy/states/media.edit.scss b/app/assets/stylesheets/legacy/states/media.edit.scss deleted file mode 100644 index caae3aba9..000000000 --- a/app/assets/stylesheets/legacy/states/media.edit.scss +++ /dev/null @@ -1,33 +0,0 @@ -.media-edit { - @extend .row; - - .media-details { - @include make-md-column(9); - @include make-md-column-pull(3); - } - - .media-info { - @include make-md-column(3); - @include make-md-column-push(9); - } - - .display-name-container, .expiration-container, .actions div { - @include make-md-column(6); - } - - .content-selector-tabs { - .tab-content { - @extend .panel; - @extend .panel-default; - @extend .panel-body; - - border-top: none; - border-top-right-radius: 0; - border-top-left-radius: 0; - } - } - - textarea { - resize: none; - } -} diff --git a/app/assets/stylesheets/legacy/states/media.grid.scss b/app/assets/stylesheets/legacy/states/media.grid.scss deleted file mode 100644 index 9c55832e6..000000000 --- a/app/assets/stylesheets/legacy/states/media.grid.scss +++ /dev/null @@ -1,21 +0,0 @@ -.media-tiles { - .media-data-row { - @extend .row; - margin-bottom: $standard-margin; - } - - .media-thumb { - @include make-sm-column(2); - @include make-xs-column(12); - } - - .media-data-desc { - @include make-xs-column(6); - } - - .media-data-actions { - @include make-sm-column(4); - @include make-xs-column(6); - @extend .text-right; - } -} diff --git a/app/assets/stylesheets/legacy/states/media.manage.scss b/app/assets/stylesheets/legacy/states/media.manage.scss deleted file mode 100644 index 3241476b0..000000000 --- a/app/assets/stylesheets/legacy/states/media.manage.scss +++ /dev/null @@ -1,36 +0,0 @@ -.media { - .actions-and-search { - @extend .row; - margin-bottom: $standard-margin; - - .manipulate-actions { - @include make-md-column(8); - @extend .pull-left; - } - - .media-search { - @include make-md-column(4); - @extend .pull-right; - } - } - - .pagination-sorting { - @extend .row; - margin-bottom: $standard-margin; - - .media-sort { - @include make-md-column(9); - @extend .pull-left; - } - - .media-page { - @include make-md-column(3); - @extend .pull-right; - - ul { - @extend .pagination, .pull-right; - margin: 0 0 0 $standard-margin; - } - } - } -} diff --git a/app/assets/stylesheets/legacy/states/media.new.scss b/app/assets/stylesheets/legacy/states/media.new.scss deleted file mode 100644 index 40174781d..000000000 --- a/app/assets/stylesheets/legacy/states/media.new.scss +++ /dev/null @@ -1,25 +0,0 @@ -.media-new { - .media-types, .media-details { - @include make-lg-column(12); - } - - .display-name-container, .expiration-container, .actions div { - @include make-lg-column(6); - } - - .content-selector-tabs { - .tab-content { - @extend .panel; - @extend .panel-default; - @extend .panel-body; - - border-top: none; - border-top-right-radius: 0; - border-top-left-radius: 0; - } - } - - textarea { - resize: none; - } -} diff --git a/app/assets/stylesheets/legacy/states/posts.edit.classify.scss b/app/assets/stylesheets/legacy/states/posts.edit.classify.scss deleted file mode 100644 index 8feb024fd..000000000 --- a/app/assets/stylesheets/legacy/states/posts.edit.classify.scss +++ /dev/null @@ -1,12 +0,0 @@ -.tags { - @extend .form-group; - - .tags-group { - @extend .input-group; - width: 100%; - - tags-input input { - width: 100%; - } - } -} diff --git a/app/assets/stylesheets/legacy/states/posts.edit.display.scss b/app/assets/stylesheets/legacy/states/posts.edit.display.scss deleted file mode 100644 index 80339aa67..000000000 --- a/app/assets/stylesheets/legacy/states/posts.edit.display.scss +++ /dev/null @@ -1,18 +0,0 @@ -.display { - .media-selector { - @extend .row; - - .thumb { - @include make-md-column(4); - } - - .info { - @include make-md-column(4.5); - } - - .actions { - @include make-md-column(3.5); - @extend .btn-group-vertical; - } - } -} diff --git a/app/assets/stylesheets/legacy/states/posts.edit.info.scss b/app/assets/stylesheets/legacy/states/posts.edit.info.scss deleted file mode 100644 index c0806ca7a..000000000 --- a/app/assets/stylesheets/legacy/states/posts.edit.info.scss +++ /dev/null @@ -1,7 +0,0 @@ -.is-wysiwyg { - @extend .form-group; - - .is-wysiwyg-group { - @extend .input-group; - } -} diff --git a/app/assets/stylesheets/legacy/states/posts.edit.scss b/app/assets/stylesheets/legacy/states/posts.edit.scss deleted file mode 100644 index e77871f08..000000000 --- a/app/assets/stylesheets/legacy/states/posts.edit.scss +++ /dev/null @@ -1,139 +0,0 @@ -.admin-posts { - @extend .row; - - .composer-column { - @include make-md-column(8); - - .composer { - @extend .form-group; - - .editor { - @extend .form-control; - - min-height: 800px; - } - } - } - - .details-column { - @include make-md-column(4); - - .publish-row { - @extend .row; - - .publish-column { - @include make-md-column(12); - - .publish-panel { - @extend .panel, .panel-default; - - .heading { - @extend .panel-heading; - } - - .content { - @extend .panel-body; - - .draft { - @include make-md-column(4); - @include make-sm-column(8); - - .bootstrap-switch { - width: 100%; - } - } - - .actions { - @include make-md-column(4); - @include make-sm-column(8); - - .actions-group { - width: 100%; - - button.cancel { - width: 50%; - @include button-variant($btn-default-color, $btn-default-bg, $btn-default-border); - } - - button.submit { - width: 50%; - @include button-variant($btn-primary-color, $btn-primary-bg, $btn-primary-border); - } - } - } - - .form-status { - @extend .row; - @include make-md-column(12); - - color: $brand-danger; - &.hidden { - display: none; - } - } - - .date-columns { - @include make-md-column(12); - } - - .publish-date { - @include make-md-column(6); - } - - .expiration-date { - @include make-md-column(6); - } - - } - } - } - } - - .metadata-row { - @extend .row; - - .metadata-column { - @include make-md-column(12); - - .panel-tabs { - .tab-content { - @extend .panel; - @extend .panel-default; - @extend .panel-body; - - border-top: none; - border-top-right-radius: 0; - border-top-left-radius: 0; - } - - .info { - .post-type-group { - @extend .form-group; - } - } - } - } - } - } -} - -.form-group.has-feedback { - .input-group { - .form-control-feedback { - top: 0px; - } - } -} - -span.has-error { - color: red; -} -span.has-error i::before { - font-family: FontAwesome; - content: ' \f071'; -} - -.form-control-feedback.select-feedback { - pointer-events: none; - right: 15px; - } diff --git a/app/assets/stylesheets/legacy/states/posts.edit.seo.scss b/app/assets/stylesheets/legacy/states/posts.edit.seo.scss deleted file mode 100644 index 83ad98bad..000000000 --- a/app/assets/stylesheets/legacy/states/posts.edit.seo.scss +++ /dev/null @@ -1,41 +0,0 @@ -.seo { - .title-group { - @extend .form-group; - - .title-input-group { - @extend .input-group; - - .addon { - @extend .input-group-addon; - } - - .control { - @extend .form-control; - } - } - } - - .description-group { - @extend .form-group; - - .description-input-group { - @extend .input-group; - - .addon { - @extend .input-group-addon; - } - - .control { - @extend .form-control; - } - } - } - - .preview-group { - @extend .form-group; - - .control { - @extend .form-control; - } - } -} diff --git a/app/assets/stylesheets/legacy/states/posts.manage.scss b/app/assets/stylesheets/legacy/states/posts.manage.scss deleted file mode 100644 index 5c6c024f0..000000000 --- a/app/assets/stylesheets/legacy/states/posts.manage.scss +++ /dev/null @@ -1,40 +0,0 @@ -.admin-posts { - .actions-and-search { - @extend .row; - margin-bottom: $standard-margin; - - .manipulate-actions { - @include make-md-column(8); - @extend .pull-left; - } - - .post-search { - @include make-md-column(4); - @extend .pull-right; - } - } - - .posts-grid { - @include make-md-column(12); - } - - //////////////////////////////// - // Posts Index Table - - .posts-table th{ - cursor: default; - background: white; - } - - .posts-table thead tr:hover { - color: black; - } - - .posts-table tbody tr:hover { - @extend .btn:hover; - } - - .posts-table .pagination { - margin: 0; - } -} diff --git a/app/assets/stylesheets/legacy/states/tenant.manage.scss b/app/assets/stylesheets/legacy/states/tenant.manage.scss deleted file mode 100644 index d69b998df..000000000 --- a/app/assets/stylesheets/legacy/states/tenant.manage.scss +++ /dev/null @@ -1,7 +0,0 @@ -#tenantSearchBar { - width: 70%; -} - -.org-btn { - margin-bottom: $standard-margin; -} diff --git a/app/assets/stylesheets/legacy/states/users.bulk.scss b/app/assets/stylesheets/legacy/states/users.bulk.scss deleted file mode 100644 index 2157730d7..000000000 --- a/app/assets/stylesheets/legacy/states/users.bulk.scss +++ /dev/null @@ -1,7 +0,0 @@ -.users-bulk { - @include make-md-column(12); - - .actions div { - @include make-lg-column(6); - } -} diff --git a/app/assets/stylesheets/legacy/states/users.edit.scss b/app/assets/stylesheets/legacy/states/users.edit.scss deleted file mode 100644 index c73139e9e..000000000 --- a/app/assets/stylesheets/legacy/states/users.edit.scss +++ /dev/null @@ -1,7 +0,0 @@ -section.users-edit { - @include make-md-column(12); - - .actions div { - @include make-md-column(6); - } -} diff --git a/app/assets/stylesheets/legacy/states/users.facets.scss b/app/assets/stylesheets/legacy/states/users.facets.scss deleted file mode 100644 index 1532a4406..000000000 --- a/app/assets/stylesheets/legacy/states/users.facets.scss +++ /dev/null @@ -1,24 +0,0 @@ -.admin-users { - @extend .row; - - .tenant-selection { - @include make-md-column(3); - } - - .actions-and-search { - @extend .row; - margin-bottom: $standard-margin; - - .manipulate-actions { - @include make-md-column(8); - } - - .search { - @include make-md-column(4); - } - } - - .users-grid { - @include make-md-column(9); - } -} \ No newline at end of file diff --git a/app/assets/stylesheets/legacy/states/users.profile.scss b/app/assets/stylesheets/legacy/states/users.profile.scss deleted file mode 100644 index 81bdda57f..000000000 --- a/app/assets/stylesheets/legacy/states/users.profile.scss +++ /dev/null @@ -1,8 +0,0 @@ -section.users-profile { - form.author { - textarea.bio { - resize: none; - height: 300px; - } - } -} \ No newline at end of file diff --git a/app/assets/stylesheets/legacy/states/webpages.edit.scss b/app/assets/stylesheets/legacy/states/webpages.edit.scss deleted file mode 100644 index 28fd285ae..000000000 --- a/app/assets/stylesheets/legacy/states/webpages.edit.scss +++ /dev/null @@ -1,13 +0,0 @@ -.webpage-edit { - .webpage-frame { - width: 100%; - min-height: 800px; - border: 0 none transparent; - } - - .tab-content { - padding: 15px; - border: 1px solid #ccc; - border-top: 0; - } -} diff --git a/app/assets/stylesheets/legacy/states/webpages.manage.scss b/app/assets/stylesheets/legacy/states/webpages.manage.scss deleted file mode 100644 index 86f195eb4..000000000 --- a/app/assets/stylesheets/legacy/states/webpages.manage.scss +++ /dev/null @@ -1,16 +0,0 @@ -.admin-webpages { - .actions-and-search { - @extend .row; - margin-bottom: $standard-margin; - - .manipulate-actions { - @include make-md-column(8); - @extend .pull-left; - } - - .webpage-search { - @include make-md-column(4); - @extend .pull-right; - } - } -} diff --git a/app/assets/stylesheets/legacy/states/webpages.new.scss b/app/assets/stylesheets/legacy/states/webpages.new.scss deleted file mode 100644 index 83c492e5f..000000000 --- a/app/assets/stylesheets/legacy/states/webpages.new.scss +++ /dev/null @@ -1,5 +0,0 @@ -.webpage-new { - .actions div { - @include make-md-column(6); - } -} diff --git a/app/assets/stylesheets/legacy/variables.scss b/app/assets/stylesheets/legacy/variables.scss deleted file mode 100644 index 33073c657..000000000 --- a/app/assets/stylesheets/legacy/variables.scss +++ /dev/null @@ -1,16 +0,0 @@ -// Responsive Navbar Breakpoint Override -$grid-float-breakpoint: 992px; - -// Margin/Gutter -$standard-margin: 10px; - -// Border -$standard-border: 1px solid #e5e5e5; -$light-border: 1px solid #ccc; - -// Fonts -$humanist: "PT Sans", Arial, sans-serif; -$neo: "Helvetica Neue", Helvetica, Arial, sans-serif; - -// Colors -$breadcrumb-bg: #f5f5f5; diff --git a/app/assets/stylesheets/legacy/vendor/abn-tree.scss b/app/assets/stylesheets/legacy/vendor/abn-tree.scss deleted file mode 100644 index 114e0a2bb..000000000 --- a/app/assets/stylesheets/legacy/vendor/abn-tree.scss +++ /dev/null @@ -1,112 +0,0 @@ -/* - abn-tree.scss - - style for the angular-bootstrap-nav-tree - for both Bootstrap 2 and Bootstrap 3 - -*/ - -/* ------------------------------------------ -AngularJS Animations... - -The first selector is for Angular 1.1.5 -The second selector is for Angular 1.2.0 - -*/ - -.abn-tree-animate-enter, li.abn-tree-row.ng-enter { - transition: 200ms linear all; - position: relative; - display: block; - opacity: 0; - max-height: 0px; -} - -.abn-tree-animate-enter.abn-tree-animate-enter-active, li.abn-tree-row.ng-enter-active { - opacity: 1; - max-height: 30px; -} - -.abn-tree-animate-leave, li.abn-tree-row.ng-leave { - transition: 200ms linear all; - position: relative; - display: block; - height: 30px; - max-height: 30px; - opacity: 1; -} - -.abn-tree-animate-leave.abn-tree-animate-leave-active, li.abn-tree-row.ng-leave-active { - height: 0px; - max-height: 0px; - opacity: 0; -} - -/* ------------------------------------------- -Angular 1.2.0 Animation -*/ - -.abn-tree-animate.ng-enter! {} - -/* - end animation stuff ------------------------------------------ - begin normal css stuff -*/ - -ul.abn-tree { - li.abn-tree-row { - padding: 0px; - margin: 0px; - a { - padding: 3px 10px; - } - } - i.indented { - padding: 2px; - } -} - -.abn-tree { - cursor: pointer; -} - -ul.nav { - &.abn-tree { - .level-1 .indented { - position: relative; - left: 0px; - } - .level-2 .indented { - position: relative; - left: 20px; - } - .level-3 .indented { - position: relative; - left: 40px; - } - .level-4 .indented { - position: relative; - left: 60px; - } - .level-5 .indented, .level-6 .indented { - position: relative; - left: 80px; - } - } - &.nav-list.abn-tree { - .level-7 .indented { - position: relative; - left: 100px; - } - .level-8 .indented { - position: relative; - left: 120px; - } - .level-9 .indented { - position: relative; - left: 140px; - } - } -} \ No newline at end of file diff --git a/app/assets/stylesheets/legacy/vendor/redactor/redactor-font.eot b/app/assets/stylesheets/legacy/vendor/redactor/redactor-font.eot deleted file mode 100755 index be2a55b38..000000000 Binary files a/app/assets/stylesheets/legacy/vendor/redactor/redactor-font.eot and /dev/null differ diff --git a/app/assets/stylesheets/legacy/vendor/redactor/redactor.css b/app/assets/stylesheets/legacy/vendor/redactor/redactor.css deleted file mode 100644 index 57aa6e29d..000000000 --- a/app/assets/stylesheets/legacy/vendor/redactor/redactor.css +++ /dev/null @@ -1,921 +0,0 @@ -/* - Icon font -*/ -@font-face { - font-family: 'RedactorFont'; - src: url('redactor-font.eot'); -} -@font-face { - font-family: 'RedactorFont'; - src: url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMggi/NUAAAC8AAAAYGNtYXAaVcx2AAABHAAAAExnYXNwAAAAEAAAAWgAAAAIZ2x5Zm8dIFkAAAFwAAATSGhlYWQACVb9AAAUuAAAADZoaGVhA+ECBQAAFPAAAAAkaG10eEEBA94AABUUAAAAkGxvY2FVlFE8AAAVpAAAAEptYXhwAC8AkgAAFfAAAAAgbmFtZRHEcG0AABYQAAABZnBvc3QAAwAAAAAXeAAAACAAAwIAAZAABQAAAUwBZgAAAEcBTAFmAAAA9QAZAIQAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADmHwHg/+D/4AHgACAAAAABAAAAAAAAAAAAAAAgAAAAAAACAAAAAwAAABQAAwABAAAAFAAEADgAAAAKAAgAAgACAAEAIOYf//3//wAAAAAAIOYA//3//wAB/+MaBAADAAEAAAAAAAAAAAAAAAEAAf//AA8AAQAAAAAAAAAAAAIAADc5AQAAAAABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAwAAACUCAAGSAAQACQANAAA3EQURBQEFEQURATUXBwACAP4AAdv+SgG2/tySkiUBbgH+lAEBSgH+3AEBJv7/3G9sAAAGAAAASQIAAW4ABAAJAA4AEwAYAB0AABMhFSE1FSEVITUVIRUhNSczFSM1FTMVIzUVMxUjNZIBbv6SAW7+kgFu/pKSSUlJSUlJAW5JSW5JSW5JSdxJSW5JSW5JSQAAAAACAAAAJQH3AZIAFgAuAAAlLgMnBzIuAic+AyMXNh4CByUnMg4CBx4DIxcnHgMXNi4CBwH3Dik/XUABAR04Vjg+WDUYAQFNeEcZEv7MAQENHDMlHzIfEQEBASZUTDYHCSBIZj4lGCQaEARqFi5HLzJFKhJqDC1RZSzVPQoWIxkbJBQID0wCCQ4VDxo4KA8PAAACAG4AJQGSAZIABAAzAAA3IQchJzceAzMyPgI3PgMnNyMXDgMHDgMjIi4CJy4DNycjBx4DF24BJQH+3QFABRIUGg0QGBUQCAYKBgQBAUABAQEEBAQCCAgKBQYJCQcEAgUCAwEBPwEBAwcJCEkkJD8HCgYEBAYKBwcRFRkPtcMGCQkHAwMFAwEBAwUDAwcJCQbDtQ8ZFREHAAUAAP//AgABtwAGAA4AFgBHAF8AAAEzFTMVIzUfAQc1IzUzNS8BNxUzFSMVFx4DFRwBDgEHDgMHMh4CFx4DHwEjJzwBJjQjLgMrARUjNTMyHgIXBzMyPgI3PgM1NC4CJy4DKwEVAUkjS24mkZFvb96RkW9vDAMFAwECAwICBQUGBAECAgIBAQICAgEbIBMBAQIEBQUCCh0qCAwKCQM3DgMFBQMCAQIBAQEBAgECAwQGAw4BtpYgtv9cXEolSUhcXEklSlUDCAoNBwQJBwcCAwUDAgEBAQIBAQMEBANCLgEBAQIGBwYCSLYBAwUDRAECAgECBAQGAwQFBQQBAgIBATIAAAAAAwBtAAABkgGTAAMADAARAAAlIzcXBzM3MxczAyMDFyEVITUBI0YjI7ZKF2MXSmVbZQEBJP7c5nh4eUlJASb+2iRJSQAKAAAAJQIAAZIABAAJAA4AEwAYAB0AIgAnACwAMQAANxEFEQU3FzUHFTU3NScVJwcVFzUVJxU3NRUHFRc1NxUXNQclBxUXNRUnFTc1FQcVFzUAAgD+ALeSkpKSJW1tbW1tbSWSkgEkbW1tbW1tJQFuAf6UASUBSgFIbQFIAUq4AUgBSm8BSgFIbQFIAUrbSAFKAQEBSAFKbwFKAUhtAUgBSgAAAAIACQAlAgABkgAWAC4AACUOAxU1DgMHJj4CFzU0HgIXBT4DNxU1FD4CNy4DNRUmDgIXAgA5VTkcQVxAKA8RGEh3Thc2Vz/+PAY3S1UlECAxICYyHQw9Z0chCt8wRi8VAWsFDxsjGS1kUiwLaQETKUYxYBAUDwgDTRABCRMlGhoiFwkBPhAQJzkZAAAAAgBJAEkBtwFuAEcAjwAAAQ4DFRQeAhceAxc+Azc+AzU0LgInLgMHJg4CBwYiBiYHNAYmIicwLgE0NTQ+Ajc+Azc1DgMHJw4DFRQeAhceAxc+Azc+AzU0LgInLgMHJg4CBwYiBiYVJgYmIjUiJjQmNTQ+Ajc+Azc1DgMHATkJDQkEAwYKBgcOEBAJCA4NDAUGCAUDAwQHBQUKCgwGBQoICAMBAgIBAQEBAQEBAQMGCgYGDxITCxMhHBYJzQkNCQQDBwkHBg4QEQgIDg0MBgUIBQMCBQcFBAoLDAYFCQkIAwECAgEBAQEBAQEBAwcJBgcPERQLEyEcFwkBIgwYHBsQCxgUEgcICwgDAQECBggGBQ0MDwYIDA0KBgUIBAQBAQICBQECAgEBAQECAQQCBQEKEhQRCggQDAwDFwgQFBQNAQwYHBsQCxgUEgcICwgDAQECBggGBQ0MDwYIDA0KBgUIBAQBAQICBQECAgEBAQECAQQCBQEKEhQRCggQDAwDFwgQFBQNAAT//wBJAgABbgAEAAkADgASAAATIRUhNRchFSE1FSEVITUHNQcXAAIA/gC3AUn+twFJ/rclk5MBbklJbklJbklJSbdcWwAAAAUAAABJAgABbgAEAAkADgAaAG0AABMhFSE1FSEVITUVIRUhNSczNSM1IwcVNxUjFRc+Azc+Azc0PgE0NTQuAicuAyMiBioBByIOAiMVPgM3Mj4BMjM6AR4BFx4CFBUcAQYUBw4DBw4DDwEVMzUjPgM3MZIBbv6SAW7+kgFu/pKNRBgUFhYYIAUHBQMBAgICAQEBAQEDBAICBgcHBQEEAwQCAgMEBAICBAQDAgIDAwMCAgMDAwEBAgEBAQEBAgICAQQGCQULRC0BAwQEAgFuSUluSUluSUlrFF0GFAZJFJEFBwYEAQIDBAMBAgMDAwIDBwUFAgIEAgEBAQEBAhUBAgIBAQEBAQIBAQIDBAIBAgMCAQICAwMCAQUHCQYNExQBBAMFAgADAAAASQIAAW4ALAAxAGwAACUiLgInNTMeAzMyPgI1NC4CIyIOAgcjNT4DMzIeAhUUDgIjJzMVIzUnIg4CByMVDgMVFB4CFxUzHgMzMj4CNzMVDgMjIi4CNTQ+AjMyHgIXFSMuAyMBbgoUEhEIHgUKCwsGEyEZDg4ZIRMGCwsKBR4IERIUCh41KBcXKDUet5KSJQYLCwoFHgQHBQICBQcEHgUKCwsGBgsLCgUeCBESFAoeNSgXFyg1HgoUEhEIHgUKCwsGSQMGBwU0AgQDAQ0XHhESHhcNAQMEAjQFBwYDFyg1Hx41KBe3SUkvAQMEAhgFCw0OBwcNDQsGFwIEAwEBAwQCNAUHBgMXKDUeHzUoFwMGBwU0AgQDAQAAAAEAAAC3AgABAAAEAAATIRUhNQACAP4AAQBJSQABAJIASQGSAZIADAAAAQ8CFzcHNxc3DwEXAQcpQQvBC0ApQAvBC0EBWdYBOAE6AdgBOgE4AQAAAAQAAABJAgABbgAEAAkADgASAAATIRUhNRchFSE1FSEVITUHNRcHAAIA/gC3AUn+twFJ/re3k5MBbklJbklJbklJSbdcWwAAAAMAAAAlAgABkgAEAAkAEgAANxEFEQUBBREFEQc/ARcVJTU3FwACAP4AAdv+SgG2tiQwPv6Sbm4lAW4B/pQBAUoB/twBASa4AV5eSgFIk5MABAAlAAAB2wG3AAMAGgAeADUAAAEVJzMHHgIGDwEOAS4BJy4BNDY/AT4BHgEXARcnFTceATI2PwE+AS4BJy4CBg8BDgEeARcB29vbKgMDAQICcwIGBgYCAwMBAnQCBQYGAv5029sqAwYGBQJzAgEBAgMCBgYGAnICAgEDAgG33NwrAgYGBgJzAgEBAgMDBQYGAnMCAQECA/51AdvaKgMDAQJzAgUGBgMCAwECAnMCBQYGAgAABAAA/9sCAAHbAAMAGgAeADUAACU1Fwc3LgI2PwE+AR4BFx4BFAYPAQ4BIiYnBycXNQcuASIGDwEOAR4BFx4CNj8BPgEuAScBJdvbKgMDAQICcwIGBgYCAwMBAnQCBQYGAnTb2yoDBgYFAnMCAQECAwIGBgYCcgICAQMC/9zbASwCBgYGAnICAgEDAgMGBgUCcwIBAwN1AdzbKgMDAQJzAgUGBgMCAwECAnICBgYGAgABAG4AJQFuAZIAEgAAJREjESM1Ii4CNTQ+AjsBESMBSSRKFigeEREeKBaTJSUBSf63khEeKBcWKB4R/pMAAAAAAwAlAAEB3AG2AAoAVwB4AAAlMwcnMzUjNxcjFQcOAwcOAyMiLgInLgM1ND4CNz4DOwE1NC4CJy4DIyIOAgcOAwc1PgM3PgIyMzIeAhceAx0BIzU1IyIOAgcOAxUUHgIXHgMzMj4CNz4DPQEBkkpcXEpKXFxK6wIGBgcEAwgICQUIDw4LBQUHBQIDBQkGBQ8SFAwlAQMDAgMFBwgFBAoJCQQFCQkJBQQJCQkEBQkKCQUNFRENBQUIBQI0FQgMCggDAwUDAQECAwICBQUHAwUJCQcCAwUCApKRkZORkZMHBAYFBQECAwIBAgUHBQULDQ8JCRANCwQFBgUCCQMGBQQCAgICAQEBAgEBAwQFAy8CAwMCAQEBAQIFCAUGDhIXDXgYSwECAwICBgYIBQQGBgUCAgMCAQIEBgQECgsOBwQAAAAEACUASgHbAW4AAwAMAC0AegAANyM3FwczNzMXMwMjAyUVFA4CBw4DIyIuAicuAzU0PgI3PgM7ATcuAyMqAQ4BBw4DBxU+Azc+AzMyHgIXHgMdASMiDgIHDgMVFB4CFx4DMzI+Ajc+AzcVMzU0LgInrjUbGok4EUsSOE1ETQF/AQMFAwMHCQoFBAYGBQIDAwIBAgMEAwMJCw0IFiIFDhIWDQYKCgoFBAoJCgQFCgoJBQUJCgoFBAkHBgIDAwMBJg0WEw8GBgkGAwIFCAUFDA4QCQUJCQgEBAcHBgI3AgUIBsV1dXZHRwEf/uFlBAcOCwsEBAYEAwICAwICBQYHAwUJBwUCAgMCAWIFCAYCAQEBAQMCBAIwAwUEAwIBAgEBAQIDAQIEBgYDCQMEBwQFCw4QCgkPDgsFBQcFAgEBAwICBQUHAxh7DhcTDwUAAAIASQBJAbcBkwAEAIEAABMhFSE1Fx4DFx4DFRQOAgcOAyMiLgInLgMnFR4DFx4DMzI+Ajc+AzU0LgInLgMvAS4DJy4DNTQ+Ajc+AzMyHgIXHgMXNS4DJy4DIyIOAgcOAxUUHgIXHgMfAUkBbv6SvwQIBgYCAgMDAQIDBQQDCAkLBgYNDAwGBg0NDQYGCwwNBgYNDAwHDxoXEggHCwgDAgUHBAUMDxIKHAcNCQcDAgMDAQIDBQMDCAkKBgYLCgsGBQsLCgYGCwwLBgYLDAsGDBcUEQcICwcDAgQHBAUMERUNIAEAJSUxAgMFBAMDBgYHAwUICAYDAgQDAQECAwMCBQcIBEEDBAUDAgECAQEDBgkGBQ8SFQwJEA8NBgYKCggDCwIFBQQDAgUFBgMFBwcFAwIDAwEBAgMCAgQGBgM9AgUDBAEBAgEBAwcJBgYPERMLCA8ODAQFCgoJBQsAAAQAAABJAgABbgAEAAkADgATAAA/ARcHJxc3FwcnJScHFzcXJwcXNwAltiO4AbYluCMB/yO4JbYBuCO2Jdsdkh6TAZQekhwBHZIekwGUHpIcAAAAAAUAAP/bAgAB2wAEAAkADgATABgAABcRIREhASERIREHITUhFRUhNSEVFSE1IRUAAgD+AAHb/koBtkn+3AEk/twBJP7cASQlAgD+AAHc/kkBt5JJSW5JSW5JSQAAAwCTAEkBbQGSABcALwBbAAA3Mh4CFx4DFwYUDgEHDgMrATczNzIeAhceAhQXBhQOAQcOAysBNzMDMzI+Ajc+Ayc2LgInLgMnPgM3PgMnNi4CJy4DKwED+AcNCQkDBAMEAQEBBAQEAgkKDQcqASgBBQsIBwIDAwQBAQQCBAEICAsFKgEoZGQRGRgRCAYLBgQBAQMEBwQGCg8OCggMDQgFAwcDAwEBBAYLBgcQFBcOZAHeAQMEAwMICQwHBgsJCAIDBAMBYYECAgMDAgYHCQUFCQcGAgIEAgFN/uoDBQgGBQ4RFQsKEQ8NBgUJBgQBAQMFBwUECwwOCAsSDw0FBggFAv63AAADACUAAAHbAbcABAANABEAADcRIREhEyMDMzczFzMDBxcjNyUBtv5K/URMOBBLETdLIho0GgABt/5JAW7+20hIASU1eHgAAAACAEIAHwG8AZkAIQBLAAAlBycOAS4BJwcXBw4BIiYvAS4BNDY/AT4BMhYfAR4BFAYHJy4BIgYPAQ4BFBYXHgE+AT8BLgMnLgI2PwE+AhYXBxc3PgE0JicBvJQEBQsMCwYhHg8PJygnDw8PDw8P1w8nKCcPDw8QEA8lCxscHAvFCwwLCgsbHRsLJwMFBgUCCgwDBQhSBg8QEgl+JoYLCwoL9pQEAQECAwMgHg8PDw8PDxAmKCcP1w8QEA8PDycoJw9+CwoLC8YLGx0bCwoLAQsLJgIDBAUCChcXFQhSBgYBBAV9JYYLHBwbCwAAAAMAAABJAgABbgAEAAkADgAAEyEVITUXIRUhNRczFSM1AAIA/gCSAW7+kpPb2wFuSUluSUluSUkAAwAAAEkCAAFuAAQACQAOAAATIRUhNRUhFSE1FTMVIzUAAgD+AAFt/pPc3AFuSUluSUluSUkAAAADAAAASQIAAW4ABAAJAA4AABMhFSE1FSEVITUVIRUhNQAB//4BAf/+AQIA/gABbklJbklJbklJAAMAAABJAgABbgAEAAkADgAAEyEHIScHIRchNxchByEnbgElAf7dAW0B/wH9/wFtASUB/t0BAW5JSW5JSW5JSQAGAAAAJwIAAZUACAANABQAGAAdACEAADc1IxEhFTMRIQEhFSE1FyMVIRUhNQcjNxcXITUhFScXIzdJSQG3Sf5JAUn+kwFtSiX+twFu27hcXG3+2wElKSlJICdJASVK/twBSdzcSbcl3EltbSUlJW5JSQAAAAEAAAABAADCHXSvXw889QALAgAAAAAAz3WLJQAAAADPdYsl////2wIAAdsAAAAIAAIAAAAAAAAAAQAAAeD/4AAAAgD//wAAAgAAAQAAAAAAAAAAAAAAAAAAACQAAAAAAAAAAAAAAAABAAAAAgAAAAIAAAACAAAAAgAAbgIAAAACAABtAgAAAAIAAAkCAABJAgD//wIAAAACAAAAAgAAAAIAAJICAAAAAgAAAAIAACUCAAAAAgAAbgIAACUCAAAlAgAASQIAAAACAAAAAgAAkwIAACUCAABCAgAAAAIAAAACAAAAAgAAAAIAAAAAAAAAAAoAFAAeAEAAcAC4AQQBhgGoAfoCQAMCAyYDuARGBFQEcASUBLwFFgVuBY4GLgbUB4IHrAfaCFwIgAj2CRIJLglKCWoJpAAAAAEAAAAkAJAACgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAOAK4AAQAAAAAAAQAYAAAAAQAAAAAAAgAOAGoAAQAAAAAAAwAYAC4AAQAAAAAABAAYAHgAAQAAAAAABQAWABgAAQAAAAAABgAMAEYAAQAAAAAACgAoAJAAAwABBAkAAQAYAAAAAwABBAkAAgAOAGoAAwABBAkAAwAYAC4AAwABBAkABAAYAHgAAwABBAkABQAWABgAAwABBAkABgAYAFIAAwABBAkACgAoAJAAUgBlAGQAYQBjAHQAbwByAEYAbwBuAHQAVgBlAHIAcwBpAG8AbgAgADEALgAwAFIAZQBkAGEAYwB0AG8AcgBGAG8AbgB0UmVkYWN0b3JGb250AFIAZQBkAGEAYwB0AG8AcgBGAG8AbgB0AFIAZQBnAHUAbABhAHIAUgBlAGQAYQBjAHQAbwByAEYAbwBuAHQARwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABJAGMAbwBNAG8AbwBuAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==) format('truetype'), url(data:application/font-woff;charset=utf-8;base64,d09GRk9UVE8AABIoAAoAAAAAEeAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABDRkYgAAAA9AAADgEAAA4Bg0Rie09TLzIAAA74AAAAYAAAAGAIIvzVY21hcAAAD1gAAABMAAAATBpVzHZnYXNwAAAPpAAAAAgAAAAIAAAAEGhlYWQAAA+sAAAANgAAADYACVb9aGhlYQAAD+QAAAAkAAAAJAPhAgVobXR4AAAQCAAAAJAAAACQQQED3m1heHAAABCYAAAABgAAAAYAJFAAbmFtZQAAEKAAAAFmAAABZhHEcG1wb3N0AAASCAAAACAAAAAgAAMAAAEABAQAAQEBDVJlZGFjdG9yRm9udAABAgABADr4HAL4GwP4GAQeCgAZU/+Lix4KABlT/4uLDAeKZviU+HQFHQAAAT8PHQAAAUQRHQAAAAkdAAAN+BIAJQEBDRkbHSAlKi80OT5DSE1SV1xhZmtwdXp/hImOk5idoqessba7wFJlZGFjdG9yRm9udFJlZGFjdG9yRm9udHUwdTF1MjB1RTYwMHVFNjAxdUU2MDJ1RTYwM3VFNjA0dUU2MDV1RTYwNnVFNjA3dUU2MDh1RTYwOXVFNjBBdUU2MEJ1RTYwQ3VFNjBEdUU2MEV1RTYwRnVFNjEwdUU2MTF1RTYxMnVFNjEzdUU2MTR1RTYxNXVFNjE2dUU2MTd1RTYxOHVFNjE5dUU2MUF1RTYxQnVFNjFDdUU2MUR1RTYxRXVFNjFGAAACAYkAIgAkAgABAAQABwAKAA0AQQCYAPEBSQH6Ai8CxwMhA98EGwTXBYEFkQW0BfEGLwagBxEHOgf0CLUJaQmsCfwKhAq5C0QLdAuiC9AMAQxo/JQO/JQO/JQO+5QOi7AVi/gB+JSLi/wB/JSLBfhv990V/EqLi/u5+EqLi/e5Bfu4+5QVi/dv9yb7Avsm+wEFDvcm+AIV+AKLi0L8AouL1AWL+wIV+AKLi0L8AouL1AWL+wIV+AKLi0L8AouL1AX7JvdwFdSLi0JCi4vUBYv7AhXUi4tCQouL1AWL+wIV1IuLQkKLi9QFDviLsBVky0yq+0KWCIshBYuLQMb7LPcT9z33GsW4i4sIiyEF92Wr9wT7QV77Cgj7yfdpFYvIBYuLb3ImSOFBtnqLiwiLfIvXBe6F9yJ7nGSl0PsO6Ps2YwgO9wLUFfe4i4tn+7iLi68FysoVnHmngrGLsounlJydnJ2Up4uyCIv3SUyLi/tXBYt8hoCDg4ODgId8i32Lf4+Dk4OTh5aLmgiL91dLi4v7SQWLZJRvnXkIDvfd+EoVrouL+yrWi4tr+wKLi/dKBbH7kxX3JS/7JS+L1fsDi4uw9wOLi9QF+3LTFfsl5/cl54tC9wOLi2b7A4uLQQWXNhWTg499i3iLf4mBhoSGg4SHgYmOio6KjYiNiI6GjoQIpklri3i5BYuMio2KjYaZhZKEiwiBi4tDbouL90q1iwWfi5mHk4MIVEcVmYsFk4uRjY+Pjo+NkYuUi5SJkoiOh4+FjYOLCH2Li1kFDve393oVRYuu9wyu+wwF+0r7DRXVi6LU7ouiQtWLJve6MIsm+7oFjGcV97iLi0L7uIuL1AUOi7AVi/gB+JSLi/wB/JSLBfdLrxX3JouL1Psmi4tCBYv3AhX3JouL1Psmi4tCBWb3SxX7AYuLQvcBi4vUBYv7AhX7AYuLQvcBi4vUBYv7AhX7AYuLQvcBi4vUBbD3cBWLQvcmi4vU+yaLBfe4ixX7AYuLQvcBi4vUBYv7AhX7AYuLQvcBi4vUBYv7AhX7AYuLQvcBi4vUBQ74lPdzFfss+xNAUIuLCIv1BftCgExsZEte9wr3BPdB92VrCIv1BYuLxV73PfsaCPxYLBWcsvcim+6RCIs/i5oFi4u2nOHVJs5vpIuLCItOBfs2s/sOLqVGCA73zfe2FXNsgGiLY4tpk3Ccd513n4Gji6CLnJKZmpqakpyLn4uehZt+mH+ZfJJ7i32LgIeChQiIiYmKiYuKi4mMioyKjoqPi5GLpJOknKOco6KcqJYIi6EFWXhlcnRrCPthixV0bH9oi2OLaZNwnXecd6CBoougi5ySmpqZmpKci5+LnoWbfph/mX2Seot+i3+IgoQIiImJioqLiYuKjIqMiY6Kj4uRi6SUpJujnKOinKmWCIuhBVh4ZnJzawgOi/gCFfiUi4tC/JSLi9QF90v7AhX33YuLQvvdi4vUBYv7AhX33YuLQvvdi4vUBWZCFYv3S/snL/cnMAUO9yb4AhX4AouLQvwCi4vUBYv7AhX4AouLQvwCi4vUBYv7AhX4AouLQvwCi4vUBfsh9hXPi4ufc4uL6HeLdYWLd6GRi0Jzi4t3Bav7JRWXl5KTjY6PkI2PjY+Mj4yPi5CLlIiThJCFkYKOf4uHi4aKhoqGioaKhokIi3YFkI6QjZCNkIyPjI+LkIuPio6IjoiMh4uGi4iLiImIiYeJh4eHiIiDgX18CIB+i3jPi4ufXosFjo+QkJGRCIuLBQ74AtQVcItyk3aYCIu/qYsFmIWZh5uLvYu0sIu5i7pisFmLe4t9h36FCG2Li78FoJikk6aL3IvMSYs6iztKSTqLCPtL90sV9yaLi0L7JouL1AVmuhV8i3yHfoUIbYuLcwWAfYR6i3iLeZJ5ln0Ii3SpiwWYhZqHmoubi5mPmJEIqYuLVwV2fnKDcIs6i0rNi9uL3MzN3Iumi6SDoH4Ii1dtiwV+kX2Pe4sIDov3lBX4lIuLQvyUi4vUBQ73m/ftFWL7a0qLgFL3VYuWxEuLtPdry4uWxPtVi4BSzIsFDov4AhX4lIuLQvyUi4vUBfdL+wIV992Li0L73YuL1AWL+wIV992Li0L73YuL1AX7S0IVi/dL9ycv+ycwBQ6LsBWL+AH4lIuL/AH8lIsF+G/33RX8SouL+7n4SouL97kF+0r7SxWvi7vqySyLQvwCi4vU9wL3JvcC+yYFDvhv+EsVi/tw+2/3cPdviwVhYBWShIyChoUI+wf7BwWFhoKMhJKEkoqUkJEI9wj3BwWQkJWKkYQI/CD8HxX3b4r7b/dvi/tuBbW1FZKElYqQkAj3B/cHBZCQipWEkoSRgo2FhQj7BvsHBYWGjYGRhQgO97n3kxWL93D3b/tv+2+KBbW3FYSSipSQkQj3B/cGBZGRlIqShJKEjIGGhgj7CPsHBYaGgYyFkgj7CPsJFftvjPdv+3CL928FYWEVhJKBjIaGCPsH+wcFhoaMgZKEkoSUipGRCPcG9wYFkZGJlIWSCA733bAVi/fdZ4uL+91Bi4v3JgVPi1q8i8iLx7y8x4sI9yeLi/wBZosFDvgm9yYV1Ysv+yUv9yXVi4v3J0GL5/cl5/slQYuL+ycF+3+EFYWCgoSBhoGGgIh/i3WLeZF+mH6XhZ2Looujkp2blpqXopGriwiwi4uUBYuUiJKFj4SQgo1/i3+Lf4l/iH+If4V+hAiLugWWkJeOl46XjZiMmIusi6KEmH6ZfZFyi2gIi/sMV4uLowWL1hV2iwV3i32IhIaDhoeCi36LgY6EkIWQhpOIlIuZi5aQkpaTlo+ai58Ii48FDvdC91kVVoum9wml+wkF+x37ChXDi5zS1oudRMOLPvezR4s++7MF+BPwFYuHBYt3h3uDgIOAf4V9i4GLg46GkYWRiJOLlIuYj5WTkJSQmY6giwihiwWt7RV9mXOSaYt8i36Kfol/iH6Hf4YIi1sFmJOYkJiPl46YjZmLl4uViJGHkoaOhIuCCIuCZYsFaYtyhXt/e3+DeItyi3SReZl+mH6ehaOLmIuXjZWQlpCTk5KUCItzwouL9w8Fi6+EpX2ZCA7U95QV+AKLi2b8AouLsAX3U1oVloeUhZGEkYSOgouCi36GgYKEgoR/iHuLe4t6jnuRepB6lHqXCItKBZqEm4Wch5yIm4mci7OLqZOfm5+alKOLq4ujhZ9/mn6bd5dwlAhvlgV3kX6ShZGFkIiTi5OLl4+UlJGTkZeOm4uai5mImoaZhpqEmYIIi8gFfJF8kHuPfI58jXuLaYtxg3h6d3uCdItui3WQeZd+l32hf61+CKuABQ6L928Vr6n3S/snZ277S/cmBYuLFfdL9yevbvtL+ydnqAX4lIsVZ6n7S/snr273S/cmBYuLFftL9ydnbvdL+yevqAUOi2YVi/iU+JSLi/yU/JSLBfhv+HAV/EqLi/xL+EqLi/hLBUL7JhX7uIuL1Pe4i4tCBYv7AhX7uIuL1Pe4i4tCBYv7AhX7uIuL1Pe4i4tCBQ73jPdyFZ6LmYiUg5ODj36LeYt6h3+DhIOEfYd3iwhii4vstIsFi/cVFZuLloiShJKFjoKLfYt+iIGEhYSFgIh7iwhii4vYtIsFJvuqFfCLBbWLqJKemp2ZlKKLqoulhZ9/mn+ZeZRzjZ+NmpKVl5aXkJuLoIungqB5mHqZcJJoiwgmi4v73QUOsIsVi/hL+EqLi/xL/EqLBfeR+AIVR4s/+7nDi5vT1oucQ8KLQPe5BWlWFaX7DFeLpfcMBQ74UPeKFfso+yiHjwV9h3uNfJMIamupbXx8BWJiSYtitAh8mgVitIvNtLQI92v3awW0tM2LtGIImnwFtGKLSWJiCGb3EhVuqFyKbm4I+1n7WgVtbotcp26ob7qLqKkIsrEFg4+EkIWScKaGsJ+gCN3dBZuapIyifwj7EvsRsWb3GvcaBaiojLpuqAgOi/gCFfiUi4tC/JSLi9QF9yb7AhX4AouLQvwCi4vUBfcn+wIV92+Li0L7b4uL1AUOi/gCFfiUi4tC/JSLi9QFi/sCFfgBi4tC/AGLi9QFi/sCFfdwi4tC+3CLi9QFDov4AhX4k4uLQvyTi4vUBYv7AhX4k4uLQvyTi4vUBYv7AhX4lIuLQvyUi4vUBQ73AvgCFfe4i4tC+7iLi9QF+wL7AhX4lIuLQvyUi4vUBfcC+wIV97iLi0L7uIuL1AUO1LIVi9RCi4v3ufhLi4tB1IuL+7j8S4sF99333RX8AYuL+3D4AYuL93AF1UIVZouL+0v73YuLZvgCi4v3cAX7b0IV+0yL5/cB5/sBBfcBZhX7uYuLsPe5i4tmBWL3AhW0QkKLq9QFDviUFPiUFYsMCgAAAAADAgABkAAFAAABTAFmAAAARwFMAWYAAAD1ABkAhAAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAAAAAAAAAAAAAAEAAAOYfAeD/4P/gAeAAIAAAAAEAAAAAAAAAAAAAACAAAAAAAAIAAAADAAAAFAADAAEAAAAUAAQAOAAAAAoACAACAAIAAQAg5h///f//AAAAAAAg5gD//f//AAH/4xoEAAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAQAAhlBJsl8PPPUACwIAAAAAAM91iyUAAAAAz3WLJf///9sCAAHbAAAACAACAAAAAAAAAAEAAAHg/+AAAAIA//8AAAIAAAEAAAAAAAAAAAAAAAAAAAAkAAAAAAAAAAAAAAAAAQAAAAIAAAACAAAAAgAAAAIAAG4CAAAAAgAAbQIAAAACAAAJAgAASQIA//8CAAAAAgAAAAIAAAACAACSAgAAAAIAAAACAAAlAgAAAAIAAG4CAAAlAgAAJQIAAEkCAAAAAgAAAAIAAJMCAAAlAgAAQgIAAAACAAAAAgAAAAIAAAACAAAAAABQAAAkAAAAAAAOAK4AAQAAAAAAAQAYAAAAAQAAAAAAAgAOAGoAAQAAAAAAAwAYAC4AAQAAAAAABAAYAHgAAQAAAAAABQAWABgAAQAAAAAABgAMAEYAAQAAAAAACgAoAJAAAwABBAkAAQAYAAAAAwABBAkAAgAOAGoAAwABBAkAAwAYAC4AAwABBAkABAAYAHgAAwABBAkABQAWABgAAwABBAkABgAYAFIAAwABBAkACgAoAJAAUgBlAGQAYQBjAHQAbwByAEYAbwBuAHQAVgBlAHIAcwBpAG8AbgAgADEALgAwAFIAZQBkAGEAYwB0AG8AcgBGAG8AbgB0UmVkYWN0b3JGb250AFIAZQBkAGEAYwB0AG8AcgBGAG8AbgB0AFIAZQBnAHUAbABhAHIAUgBlAGQAYQBjAHQAbwByAEYAbwBuAHQARwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABJAGMAbwBNAG8AbwBuAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==) format('woff'); - font-weight: normal; - font-style: normal; -} -/* - Box -*/ -.redactor-box { - position: relative; - overflow: visible; - margin-bottom: 24px; -} -.redactor-box textarea { - display: block; - position: relative; - margin: 0; - padding: 0; - width: 100%; - overflow: auto; - outline: none; - border: none; - background-color: #111; - box-shadow: none; - color: #ccc; - font-size: 13px; - font-family: Menlo, Monaco, monospace, sans-serif; - resize: none; -} -.redactor-box textarea:focus { - outline: none; -} -/* - Z-index setup -*/ -.redactor-editor, -.redactor-box { - background: #fff; -} -.redactor-editor, -.redactor-box, -.redactor-box textarea { - z-index: auto !important; -} -.redactor-box-fullscreen { - z-index: 1052 !important; -} -.redactor-toolbar, -.redactor-dropdown { - z-index: 1053 !important; -} -#redactor-modal-overlay, -#redactor-modal-box, -#redactor-modal { - z-index: 1054 !important; -} -/* - Resize -*/ -.redactor-resize { - background: #f4f4f4; - padding: 4px 0 3px 0; - cursor: move; - border: 1px solid #e3e3e3; - border-top: none; -} -.redactor-resize div { - width: 30px; - margin: auto; - border-top: 1px solid #bbb; - border-bottom: 1px solid #fff; -} -/* - Fullscreen -*/ -body .redactor-box-fullscreen { - position: fixed; - top: 0; - left: 0; - width: 100%; -} -/* - Utils -*/ -.body-redactor-hidden { - overflow: hidden; -} -/* - Editor -*/ -.redactor-editor { - position: relative; - overflow: auto; - margin: 0 !important; - padding: 20px; - outline: none; - white-space: normal; - border: 1px solid #eee; - font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif; - font-size: 14px; - line-height: 1.6em; -} -.redactor-editor:focus { - outline: none; -} -/* - Placeholder -*/ -.redactor-placeholder { - position: relative; -} -.redactor-placeholder:after { - position: absolute; - top: 20px; - left: 20px; - content: attr(placeholder); - color: #999 !important; - font-weight: normal !important; -} -/* Placeholder in linebreaks mode */ -.redactor-linebreaks.redactor-placeholder:after { - top: 20px; - left: 20px; -} -/* - Toolbar -*/ -.redactor-toolbar { - position: relative; - top: 0; - left: 0; - margin: 0 !important; - padding: 0 !important; - list-style: none !important; - font-size: 14px !important; - line-height: 1 !important; - background: #fff; - border: none; - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); -} -.redactor-toolbar:after { - content: ""; - display: table; - clear: both; -} -.redactor-toolbar.redactor-toolbar-overflow { - overflow-y: auto; - height: 29px; - white-space: nowrap; -} -.redactor-toolbar.redactor-toolbar-external { - z-index: 999; - box-shadow: none; - border: 1px solid rgba(0, 0, 0, 0.1); -} -.redactor-toolbar li { - vertical-align: top; - display: inline-block; - margin: 0 !important; - padding: 0 !important; - outline: none; - list-style: none !important; - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; -} -.redactor-toolbar li a { - display: block; - color: #333; - text-align: center; - padding: 9px 10px; - outline: none; - border: none; - text-decoration: none; - cursor: pointer; - zoom: 1; - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; -} -.redactor-toolbar li a:hover { - outline: none; - background-color: #1f78d8; - color: #fff; -} -.redactor-toolbar li a:hover i:before { - color: #fff; -} -.redactor-toolbar li a:active, -.redactor-toolbar li a.redactor-act { - outline: none; - background-color: #ccc; - color: #444; -} -.redactor-toolbar li a.redactor-btn-image { - width: 14px; - height: 14px; - background-position: center center; - background-repeat: no-repeat; -} -.redactor-toolbar li a.fa-redactor-btn { - display: inline-block; - padding: 9px 10px 8px 10px; - line-height: 1; -} -.redactor-toolbar li a.redactor-button-disabled { - filter: alpha(opacity=30); - -moz-opacity: 0.3; - opacity: 0.3; -} -.redactor-toolbar li a.redactor-button-disabled:hover { - color: #333; - outline: none; - background-color: transparent !important; - cursor: default; -} -/* - Icons -*/ -.re-icon { - font-family: 'RedactorFont'; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -.re-icon i:before { - position: relative; - font-size: 14px; -} -.re-video:before { - content: "\e600"; -} -.re-unorderedlist:before { - content: "\e601"; -} -.re-undo:before { - content: "\e602"; -} -.re-underline:before { - content: "\e603"; -} -.re-textdirection:before { - content: "\e604"; -} -.re-fontcolor:before { - content: "\e605"; -} -.re-table:before { - content: "\e606"; -} -.re-redo:before { - content: "\e607"; -} -.re-quote:before { - content: "\e608"; -} -.re-outdent:before { - content: "\e609"; -} -.re-orderedlist:before { - content: "\e60a"; -} -.re-link:before { - content: "\e60b"; -} -.re-horizontalrule:before { - content: "\e60c"; -} -.re-italic:before { - content: "\e60d"; -} -.re-indent:before { - content: "\e60e"; -} -.re-image:before { - content: "\e60f"; -} -.re-fullscreen:before { - content: "\e610"; -} -.re-normalscreen:before { - content: "\e611"; -} -.re-formatting:before { - content: "\e612"; -} -.re-fontsize:before { - content: "\e613"; -} -.re-fontfamily:before { - content: "\e614"; -} -.re-deleted:before { - content: "\e615"; -} -.re-html:before { - content: "\e616"; -} -.re-clips:before { - content: "\e617"; -} -.re-bold:before { - content: "\e618"; -} -.re-backcolor:before { - content: "\e619"; -} -.re-file:before { - content: "\e61a"; -} -.re-alignright:before { - content: "\e61b"; -} -.re-alignment:before, -.re-alignleft:before { - content: "\e61c"; -} -.re-alignjustify:before { - content: "\e61d"; -} -.re-aligncenter:before { - content: "\e61e"; -} -.re-gallery:before { - content: "\e61f"; -} -/* - Toolbar tooltip -*/ -.redactor-toolbar-tooltip { - position: absolute; - z-index: 1054; - text-align: center; - top: 0; - left: 0; - background: #000; - color: #fff; - padding: 5px 8px; - line-height: 1; - font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif; - font-size: 12px; - border-radius: 2px; -} -/* - Dropdown -*/ -.redactor-dropdown { - position: absolute; - top: 28px; - left: 0; - padding: 0; - min-width: 220px; - max-height: 254px; - overflow: auto; - background-color: #fff; - box-shadow: 0 1px 7px rgba(0, 0, 0, 0.25); - font-size: 14px; - font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif; - line-height: 1.6em; -} -.redactor-dropdown a { - display: block; - padding: 10px 15px; - color: #000; - text-decoration: none; - border-bottom: 1px solid rgba(0, 0, 0, 0.07); -} -.redactor-dropdown a:last-child { - border-bottom: none; -} -.redactor-dropdown a:hover { - background-color: #1f78d8; - color: #fff !important; - text-decoration: none; -} -/* - IMAGE BOX -*/ -#redactor-image-box { - position: relative; - max-width: 100%; - display: inline-block; - line-height: 0; - outline: 1px dashed rgba(0, 0, 0, 0.6); -} -#redactor-image-editter { - position: absolute; - z-index: 5; - top: 50%; - left: 50%; - margin-top: -11px; - margin-left: -18px; - line-height: 1; - background-color: #000; - color: #fff; - font-size: 11px; - padding: 7px 10px; - cursor: pointer; -} -#redactor-image-resizer { - position: absolute; - z-index: 2; - line-height: 1; - cursor: nw-resize; - bottom: -4px; - right: -5px; - border: 1px solid #fff; - background-color: #000; - width: 8px; - height: 8px; -} -/* - LINK TOOLTIP -*/ -.redactor-link-tooltip { - position: absolute; - z-index: 49999; - padding: 10px; - line-height: 1; - display: inline-block; - background-color: #000; - color: #555 !important; -} -.redactor-link-tooltip, -.redactor-link-tooltip a { - font-size: 12px; - font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif; -} -.redactor-link-tooltip a { - color: #ccc; - margin: 0 5px; - text-decoration: none; -} -.redactor-link-tooltip a:hover { - color: #fff; -} -/* - DROPAREA -*/ -#redactor-droparea { - position: relative; - overflow: hidden; - padding: 140px 20px; - border: 3px dashed rgba(0, 0, 0, 0.1); -} -#redactor-droparea.drag-hover { - background: rgba(200, 222, 250, 0.75); -} -#redactor-droparea.drag-drop { - background: rgba(250, 248, 200, 0.5); -} -#redactor-droparea-placeholder { - text-align: center; - font-size: 12px; - color: rgba(0, 0, 0, 0.7); -} -/* - PROGRESS -*/ -#redactor-progress { - position: fixed; - top: 0; - left: 0; - width: 100%; - z-index: 1000000; - height: 10px; -} -#redactor-progress span { - display: block; - width: 100%; - height: 100%; - background-color: #3d58a8; - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); - -webkit-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; - background-size: 40px 40px; -} -@-webkit-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -@-o-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -@keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -/* - MODAL -*/ -#redactor-modal-overlay { - position: fixed; - top: 0; - left: 0; - margin: auto; - overflow: auto; - width: 100%; - height: 100%; - background-color: #000 !important; - filter: alpha(opacity=30); - -moz-opacity: 0.3; - opacity: 0.3; -} -#redactor-modal-box { - position: fixed; - top: 0; - left: 0; - bottom: 0; - right: 0; - overflow-x: hidden; - overflow-y: auto; -} -#redactor-modal { - position: relative; - margin: auto; - margin-bottom: 20px; - padding: 0; - background: #fff; - color: #000; - font-size: 14px !important; - font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif; - box-shadow: 0 1px 70px rgba(0, 0, 0, 0.5); -} -#redactor-modal header { - padding: 30px 40px 5px 40px; - font-size: 18px; - font-weight: bold; -} -#redactor-modal section { - padding: 30px 40px 50px 40px; -} -#redactor-modal label { - display: block; - float: none !important; - margin: 15px 0 3px 0 !important; - padding: 0; -} -#redactor-modal input[type="radio"], -#redactor-modal input[type="checkbox"] { - position: relative; - top: -1px; -} -#redactor-modal select { - width: 100%; -} -#redactor-modal input[type="text"], -#redactor-modal input[type="password"], -#redactor-modal input[type="email"], -#redactor-modal input[type="url"], -#redactor-modal textarea { - position: relative; - z-index: 2; - margin: 0; - padding: 5px 4px; - height: 28px; - border: 1px solid #ccc; - border-radius: 1px; - background-color: white; - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) inset; - color: #333; - width: 100%; - font-size: 14px; - font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif; - -moz-transition: border 0.3s ease-in; - transition: border 0.3s ease-in; -} -#redactor-modal input[type="text"]:focus, -#redactor-modal input[type="password"]:focus, -#redactor-modal input[type="email"]:focus, -#redactor-modal input[type="url"]:focus, -#redactor-modal textarea:focus { - outline: none; - border-color: #5ca9e4; - box-shadow: 0 0 0 2px rgba(70, 161, 231, 0.3), 0 1px 2px rgba(0, 0, 0, 0.2) inset; -} -#redactor-modal input[type="text"].redactor-input-error, -#redactor-modal input[type="password"].redactor-input-error, -#redactor-modal input[type="email"].redactor-input-error, -#redactor-modal input[type="url"].redactor-input-error, -#redactor-modal textarea.redactor-input-error { - border-color: #e82f2f; - box-shadow: 0 0 0 2px rgba(232, 47, 47, 0.3), 0 1px 2px rgba(0, 0, 0, 0.2) inset; -} -#redactor-modal textarea { - display: block; - margin-top: 4px; - line-height: 1.4em; -} -/* - Tabs in Modal -*/ -#redactor-modal-tabber { - margin-bottom: 15px; - font-size: 12px; -} -#redactor-modal-tabber a { - border: 1px solid #ddd; - line-height: 1; - padding: 8px 15px; - margin-right: -1px; - text-decoration: none; - color: #000; -} -#redactor-modal-tabber a:hover { - background-color: #1f78d8; - border-color: #1f78d8; - color: #fff; -} -#redactor-modal-tabber a.active { - cursor: default; - background-color: #ddd; - border-color: #ddd; - color: rgba(0, 0, 0, 0.6); -} -/* - List in Modal -*/ -#redactor-modal #redactor-modal-list { - margin-left: 0; - padding-left: 0; - list-style: none; - max-height: 250px; - overflow-x: scroll; -} -#redactor-modal #redactor-modal-list li { - border-bottom: 1px solid #ddd; -} -#redactor-modal #redactor-modal-list li:last-child { - border-bottom: none; -} -#redactor-modal #redactor-modal-list a { - padding: 10px 5px; - color: #000; - text-decoration: none; - font-size: 13px; - display: block; - position: relative; -} -#redactor-modal #redactor-modal-list a:hover { - background-color: #eee; -} -#redactor-modal-close { - position: absolute; - top: 10px; - right: 10px; - width: 30px; - height: 30px; - text-align: right; - color: #bbb; - font-size: 30px; - font-weight: 300; - cursor: pointer; -} -#redactor-modal-close:hover { - color: #000; -} -#redactor-modal footer button { - position: relative; - width: 100%; - padding: 14px 16px; - margin: 0; - outline: none; - border: none; - background-color: #ddd; - color: #000; - text-align: center; - text-decoration: none; - font-weight: normal; - font-size: 12px; - font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif; - line-height: 1; - cursor: pointer; -} -#redactor-modal footer button:hover { - color: #777; - background: none; - background: #bbb; - text-decoration: none; -} -#redactor-modal footer button.redactor-modal-delete-btn { - background: none; - color: #fff; - background-color: #b52525; -} -#redactor-modal footer button.redactor-modal-delete-btn:hover { - color: rgba(255, 255, 255, 0.6); - background-color: #881b1b; -} -#redactor-modal footer button.redactor-modal-action-btn { - background: none; - color: #fff; - background-color: #2461b5; -} -#redactor-modal footer button.redactor-modal-action-btn:hover { - color: rgba(255, 255, 255, 0.6); - background-color: #1a4580; -} -/* - ############################################## - - DROPDOWN FORMATTING - - ############################################## -*/ -.redactor-dropdown .redactor-formatting-blockquote { - color: rgba(0, 0, 0, 0.4); - font-style: italic; -} -.redactor-dropdown .redactor-formatting-pre { - font-family: monospace, sans-serif; -} -.redactor-dropdown .redactor-formatting-h1 { - font-size: 36px; - line-height: 36px; - font-weight: bold; -} -.redactor-dropdown .redactor-formatting-h2 { - font-size: 24px; - line-height: 36px; - font-weight: bold; -} -.redactor-dropdown .redactor-formatting-h3 { - font-size: 21px; - line-height: 30px; - font-weight: bold; -} -.redactor-dropdown .redactor-formatting-h4 { - font-size: 18px; - line-height: 26px; - font-weight: bold; -} -.redactor-dropdown .redactor-formatting-h5 { - font-size: 16px; - line-height: 23px; - font-weight: bold; -} -/* - ############################################## - - CONTENT STYLES - - ############################################## -*/ -.redactor-editor code, -.redactor-editor pre { - font-family: Menlo, Monaco, monospace, sans-serif; -} -.redactor-editor div, -.redactor-editor p, -.redactor-editor ul, -.redactor-editor ol, -.redactor-editor table, -.redactor-editor dl, -.redactor-editor blockquote, -.redactor-editor pre { - font-size: 14px; - line-height: 1.6em; -} -.redactor-editor a { - color: #15c; - text-decoration: underline; -} -.redactor-editor object, -.redactor-editor embed, -.redactor-editor video, -.redactor-editor img { - max-width: 100%; - width: auto; -} -.redactor-editor video, -.redactor-editor img { - height: auto; -} -.redactor-editor div, -.redactor-editor p, -.redactor-editor ul, -.redactor-editor ol, -.redactor-editor table, -.redactor-editor dl, -.redactor-editor figure, -.redactor-editor blockquote, -.redactor-editor pre { - margin: 0; - margin-bottom: 15px; - border: none; - background: none; - box-shadow: none; -} -.redactor-editor iframe, -.redactor-editor object, -.redactor-editor hr { - margin-bottom: 15px; -} -.redactor-editor blockquote { - margin-left: 1.6em !important; - padding-left: 0; - color: #777; - font-style: italic; -} -.redactor-editor ul, -.redactor-editor ol { - padding-left: 2em; -} -.redactor-editor ul ul, -.redactor-editor ol ol, -.redactor-editor ul ol, -.redactor-editor ol ul { - margin: 2px; - padding: 0; - padding-left: 2em; - border: none; -} -.redactor-editor dl dt { - font-weight: bold; -} -.redactor-editor dd { - margin-left: 1em; -} -.redactor-editor table { - border-collapse: collapse; - font-size: 1em; - width: 100%; -} -.redactor-editor table td, -.redactor-editor table th { - padding: 5px; - border: 1px solid #ddd; - vertical-align: top; -} -.redactor-editor table thead td, -.redactor-editor table th { - font-weight: bold; - border-bottom-color: #888; -} -.redactor-editor code { - background-color: #d8d7d7; -} -.redactor-editor pre { - overflow: auto; - padding: 1em; - border: 1px solid #ddd; - border-radius: 3px; - background: #f8f8f8; - white-space: pre; - font-size: 90%; -} -.redactor-editor hr { - display: block; - height: 1px; - border: 0; - border-top: 1px solid #ccc; -} -.redactor-editor h1, -.redactor-editor h2, -.redactor-editor h3, -.redactor-editor h4, -.redactor-editor h5, -.redactor-editor h6 { - font-weight: bold; - color: #000; - padding: 0; - background: none; - text-rendering: optimizeLegibility; - margin: 0 0 .5em 0; -} -.redactor-editor h1, -.redactor-editor h2, -.redactor-editor h3, -.redactor-editor h4 { - line-height: 1.3; -} -.redactor-editor h1 { - font-size: 36px; -} -.redactor-editor h2 { - font-size: 24px; - margin-bottom: .7em; -} -.redactor-editor h3 { - font-size: 21px; -} -.redactor-editor h4 { - font-size: 18px; -} -.redactor-editor h5 { - font-size: 16px; -} -.redactor-editor h6 { - font-size: 12px; - text-transform: uppercase; -} diff --git a/app/assets/stylesheets/legacy_application.scss b/app/assets/stylesheets/legacy_application.scss deleted file mode 100644 index 0eb8ded99..000000000 --- a/app/assets/stylesheets/legacy_application.scss +++ /dev/null @@ -1,48 +0,0 @@ -@import "font-awesome-sprockets"; -@import 'font-awesome'; - -@import 'legacy/variables'; -@import 'legacy/mixins'; - -// Vendor -@import 'legacy/vendor/abn-tree'; -@import 'legacy/vendor/redactor/redactor'; - -// Twitter Bootstrap and overridden styles -@import 'legacy/bootstrap-cortex'; - -// Application-wide styling -@import 'legacy/cortex'; - -// Directives -@import 'legacy/directives/file-selector'; -@import 'legacy/directives/youtube-selector'; - -// States -@import 'legacy/states/locales.edit'; -@import 'legacy/states/localizations.edit'; -@import 'legacy/states/media.edit'; -@import 'legacy/states/media.grid'; -@import 'legacy/states/media.manage'; -@import 'legacy/states/media.new'; -@import 'legacy/states/media.bulk'; -@import 'legacy/states/posts.edit'; -@import 'legacy/states/posts.edit.classify'; -@import 'legacy/states/posts.edit.display'; -@import 'legacy/states/posts.edit.info'; -@import 'legacy/states/posts.edit.seo'; -@import 'legacy/states/posts.manage'; -@import 'legacy/states/tenant.manage'; -@import 'legacy/states/users.edit'; -@import 'legacy/states/users.facets'; -@import 'legacy/states/users.profile'; -@import 'legacy/states/users.bulk'; -@import 'legacy/states/credentials.new'; -@import 'legacy/states/credentials.edit'; -@import 'legacy/states/webpages.manage'; -@import 'legacy/states/webpages.new'; -@import 'legacy/states/webpages.edit'; - -@import 'ng-tags-input/ng-tags-input'; - -@import 'angular-bootstrap-toggle-switch/style/bootstrap3/angular-toggle-switch-bootstrap-3.scss'; diff --git a/app/controllers/authentication/sessions_controller.rb b/app/controllers/authentication/sessions_controller.rb index d58bc2485..35997e3b5 100644 --- a/app/controllers/authentication/sessions_controller.rb +++ b/app/controllers/authentication/sessions_controller.rb @@ -1,11 +1,2 @@ class Authentication::SessionsController < Devise::SessionsController - def after_sign_in_path_for(_resource) - if params[:legacy] == '1' - session[:legacy] = true - legacy_root_path - else - session[:legacy] = false - root_path - end - end end diff --git a/app/controllers/dashboards_controller.rb b/app/controllers/dashboards_controller.rb index 7e8fcfe9b..f7c029eed 100644 --- a/app/controllers/dashboards_controller.rb +++ b/app/controllers/dashboards_controller.rb @@ -1,7 +1,3 @@ class DashboardsController < AdminController add_breadcrumb 'Dashboard', :dashboards_path - - def index - redirect_to legacy_root_path if session[:legacy] - end end diff --git a/app/controllers/hello_world_controller.rb b/app/controllers/hello_world_controller.rb deleted file mode 100644 index a8f38ef25..000000000 --- a/app/controllers/hello_world_controller.rb +++ /dev/null @@ -1,5 +0,0 @@ -class HelloWorldController < ApplicationController - def index - @hello_world_props = { name: "Stranger" } - end -end diff --git a/app/controllers/legacy_controller.rb b/app/controllers/legacy_controller.rb deleted file mode 100644 index 4a9299b73..000000000 --- a/app/controllers/legacy_controller.rb +++ /dev/null @@ -1,21 +0,0 @@ -class LegacyController < ApplicationController - before_action :authenticate_user!, :add_gon - - def index - render layout: 'legacy_application' - end - - private - - def add_gon - gon.push({ - current_user: current_user.as_json, - settings: { - cortex_base_url: "#{root_url}api/v1", - paging: { - defaultPerPage: 10 - } - } - }) - end -end diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb index 4c6a7c6ad..4ff48cbde 100644 --- a/app/helpers/dashboard_helper.rb +++ b/app/helpers/dashboard_helper.rb @@ -1,18 +1,6 @@ module DashboardHelper def news_feed - news_feed = [] - - if news_feed_tenant - params = Hashr.new(page: 1, per_page: 10) - posts_last_updated_at = Post.last_updated_at - cache_key = "news-feed-#{posts_last_updated_at}" - - news_feed = Rails.cache.fetch(cache_key, expires_in: 30.minutes, race_condition_ttl: 10) do - GetPosts.call(params: params, tenant: news_feed_tenant, published: true).posts.to_a - end - end - - news_feed + [] # need to re-implement this feature using Beta Cortex blogposts end def news_feed_tenant diff --git a/app/helpers/youtube_helper.rb b/app/helpers/youtube_helper.rb deleted file mode 100644 index 07d4ac768..000000000 --- a/app/helpers/youtube_helper.rb +++ /dev/null @@ -1,18 +0,0 @@ -module YoutubeHelper - def self.fetch_info(video_id) - video = Yt::Video.new id: video_id - - info = {} - info[:url] = "https://www.youtube.com/v/#{video_id}" - info[:thumbnail] = video.thumbnail_url - info[:title] = video.title - info[:channel_id] = video.channel_id - info[:channel_title] = video.channel_title - info[:authors] = [info[:channel_title]] - info[:duration] = video.duration - info[:description] = video.description - info[:source_published_at] = DateTime.parse(video.published_at.to_s) - - info - end -end diff --git a/app/interactors/get_multiple_media.rb b/app/interactors/get_multiple_media.rb deleted file mode 100644 index e5e74cb29..000000000 --- a/app/interactors/get_multiple_media.rb +++ /dev/null @@ -1,23 +0,0 @@ -class GetMultipleMedia - include Interactor - - SEARCH_PARAMS = %w(q).freeze - - def call - media = ::Media - - if has_search_params? - media = media.search_with_params(context.params, context.tenant) - else - media = media.show_all(context.tenant) - end - - context.media = media - end - - private - - def has_search_params? - (context.params.to_h.keys & SEARCH_PARAMS).any? - end -end diff --git a/app/interactors/get_post.rb b/app/interactors/get_post.rb deleted file mode 100644 index c99453274..000000000 --- a/app/interactors/get_post.rb +++ /dev/null @@ -1,11 +0,0 @@ -class GetPost - include Interactor - - def call - post = ::Post - post = post.find_by_tenant_id(context.tenant) if context.tenant - post = post.published if context.published - post = post.find_by_id_or_slug(context.id) - context.post = post - end -end diff --git a/app/interactors/get_posts.rb b/app/interactors/get_posts.rb deleted file mode 100644 index f356202f1..000000000 --- a/app/interactors/get_posts.rb +++ /dev/null @@ -1,23 +0,0 @@ -class GetPosts - include Interactor - - SEARCH_PARAMS = %w(q categories industries type job_phase post_type author tags).freeze - - def call - posts = ::Post - - if has_search_params? - posts = posts.search_with_params(context.params, context.tenant, context.published) - else - posts = posts.show_all(context.tenant, context.published) - end - - context.posts = posts - end - - private - - def has_search_params? - (context.params.to_h.keys & SEARCH_PARAMS).any? - end -end diff --git a/app/interactors/get_related_posts.rb b/app/interactors/get_related_posts.rb deleted file mode 100644 index 60fda0e7b..000000000 --- a/app/interactors/get_related_posts.rb +++ /dev/null @@ -1,9 +0,0 @@ -class GetRelatedPosts - include Interactor - - def call - related = context.post.related(context.tenant, context.published) - - context.posts = related - end -end diff --git a/app/interactors/get_single_media.rb b/app/interactors/get_single_media.rb deleted file mode 100644 index 4a6986e29..000000000 --- a/app/interactors/get_single_media.rb +++ /dev/null @@ -1,10 +0,0 @@ -class GetSingleMedia - include Interactor - - def call - media = ::Media - media = media.find_by_tenant_id(context.tenant) if context.tenant - media = media.find_by id: context.id - context.media = media - end -end diff --git a/app/interactors/get_users.rb b/app/interactors/get_users.rb deleted file mode 100644 index 409901a9d..000000000 --- a/app/interactors/get_users.rb +++ /dev/null @@ -1,23 +0,0 @@ -class GetUsers - include Interactor - - SEARCH_PARAMS = %w{q} - - def call - users = ::User - - if has_search_params? - users = users.search_with_params(context.params, context.tenant_id) - else - users = users.show_all(context.tenant_id) - end - - context.users = users - end - - private - - def has_search_params? - Array(context.params.keys & SEARCH_PARAMS).length > 0 - end -end diff --git a/app/interactors/get_webpage_feed.rb b/app/interactors/get_webpage_feed.rb deleted file mode 100644 index 4c50a76e9..000000000 --- a/app/interactors/get_webpage_feed.rb +++ /dev/null @@ -1,19 +0,0 @@ -class GetWebpageFeed - include Interactor - - def call - webpage = ::Webpage - webpage = webpage.find_by_tenant_id(context.tenant) if context.tenant - webpage = webpage.agnostic_find_by_url(context.params.url) - - context.webpage = webpage - end - - private - - def protocol_agnostic_url(url) - uri = Addressable::URI.parse(url) - path = uri.path == '/' ? uri.path : uri.path.chomp('/') - "://#{uri.authority}#{path}" - end -end diff --git a/app/interactors/get_webpages.rb b/app/interactors/get_webpages.rb deleted file mode 100644 index 78fe8f9c8..000000000 --- a/app/interactors/get_webpages.rb +++ /dev/null @@ -1,23 +0,0 @@ -class GetWebpages - include Interactor - - SEARCH_PARAMS = %w(q).freeze - - def call - webpages = ::Webpage - - if has_search_params? - webpages = webpages.search_with_params(context.params, context.tenant) - else - webpages = webpages.show_all(context.tenant) - end - - context.webpages = webpages - end - - private - - def has_search_params? - (context.params.to_h.keys & SEARCH_PARAMS).any? - end -end diff --git a/app/jobs/bulk_create_media_job.rb b/app/jobs/bulk_create_media_job.rb deleted file mode 100644 index e60822135..000000000 --- a/app/jobs/bulk_create_media_job.rb +++ /dev/null @@ -1,88 +0,0 @@ -require 'csv' -require 'zip' - -class BulkCreateMediaJob < ApplicationJob - queue_as :default - - def perform(bulk_job, current_user) - @bulk_job = bulk_job - metadata_file = Paperclip.io_adapters.for(@bulk_job.metadata).read - assets_file = Paperclip.io_adapters.for(@bulk_job.assets).read - - Zip::File.open_buffer(assets_file) do |zip_file| - write_status('Opened Assets ZIP') - - CSV.parse(metadata_file, { :headers => true, :col_sep => ',' }) do |row| - row_hash = row.to_hash - begin - media_attributes = generate_media_attributes(zip_file, row_hash) - rescue Exception => e - write_status(e.message) - next - end - - media = ::Media.find_by_id(row_hash['ID']) - if media - begin - media.update!(media_attributes) - write_status("Processed '#{row_hash['Display Name']}'. Updated existing Media with ID #{row_hash['ID']}.") - rescue Exception => e - write_status("Error processing '#{row_hash['Display Name']}'. Failed to update existing Media with ID #{row_hash['ID']}. Exception details: #{e.message}") - end - else - begin - media = ::Media.new(media_attributes) - media.user = current_user - media.save! - write_status("Processed '#{row_hash['Display Name']}'. Created new Media with ID #{media.id}.") - rescue Exception => e - write_status("Error processing '#{row_hash['Display Name']}'. Failed to create Media. Exception details: #{e.message}") - end - end - end - end - end - - private - - def generate_media_attributes(zip_file, row_hash) - media_attributes = { - name: row_hash['Display Name'], - description: row_hash['Description'], - deactive_at: row_hash['Expiration'], - tag_list: row_hash['Tags'], - type: row_hash['Type (Media, Youtube)'] - } - - media_attributes = strip_attributes(media_attributes) - - if row_hash['Type (Media, Youtube)'] == 'Media' - begin - media_attachment = zip_file.get_entry(row_hash['Filename']) - rescue - raise "Error finding or processing '#{row_hash['Filename']}' in Assets ZIP. Exception details: #{$!}" - end - media_attributes[:attachment] = StringIO.new(media_attachment.get_input_stream.read) - media_attributes[:attachment_file_name] = row_hash['Filename'] - else - media_attributes[:video_id] = row_hash['Youtube ID'] - end - - media_attributes - end - - def write_status(message) - @bulk_job.status = message - @bulk_job.log ||= [] - @bulk_job.log << message - - @bulk_job.save! - end - - def strip_attributes(attributes) - # Don't update nil attributes, but do clear out attributes with a value of 'N/A' - attributes.compact.transform_values do |attribute_value| - attribute_value == 'N/A' ? nil : attribute_value - end - end -end diff --git a/app/jobs/bulk_create_users_job.rb b/app/jobs/bulk_create_users_job.rb deleted file mode 100644 index ff4cde10e..000000000 --- a/app/jobs/bulk_create_users_job.rb +++ /dev/null @@ -1,61 +0,0 @@ -require 'csv' - -class BulkCreateUsersJob < ApplicationJob - queue_as :default - - def perform(bulk_job) - @bulk_job = bulk_job - metadata_file = Paperclip.io_adapters.for(@bulk_job.metadata).read - - CSV.parse(metadata_file, { :headers => true, :col_sep => ',' }) do |row| - row_hash = row.to_hash - begin - user_attributes = generate_user_attributes(row_hash) - rescue Exception => e - write_status(e.message) - next - end - - user = ::User.find_by_id(row_hash['ID']) - if user - begin - user.update!(user_attributes) - write_status("Processed '#{row_hash['Email']}'. Updated existing User with ID #{row_hash['ID']}.") - rescue Exception => e - write_status("Error processing '#{row_hash['Email']}'. Failed to update existing User with ID #{row_hash['ID']}. Exception details: #{e.message}") - end - else - begin - user = ::User.create!(user_attributes) - write_status("Processed '#{row_hash['Email']}'. Created new User with ID #{user.id}.") - rescue Exception => e - write_status("Error processing '#{row_hash['Email']}'. Failed to create User. Exception details: #{e.message}") - end - end - end - end - - private - - def generate_user_attributes(row_hash) - user_attributes = { - email: row_hash['Email'], - firstname: row_hash['First Name'], - lastname: row_hash['Last Name'], - admin: row_hash['Is Admin? (true or false)'], - tenant_id: row_hash['Tenant ID'], - password: 'welcome1', - password_confirmation: 'welcome1' - } - - user_attributes - end - - def write_status(message) - @bulk_job.status = message - @bulk_job.log ||= [] - @bulk_job.log << message - - @bulk_job.save! - end -end diff --git a/app/jobs/cache_bust_webpage_job.rb b/app/jobs/cache_bust_webpage_job.rb deleted file mode 100644 index 1a7833ff6..000000000 --- a/app/jobs/cache_bust_webpage_job.rb +++ /dev/null @@ -1,15 +0,0 @@ -class CacheBustWebpageJob < ApplicationJob - queue_as :default - - def perform(url) - r = Excon.get(get_cache_buster_url(url)) - raise "Error while executing cache buster request\nStatus: #{r.status}\nBody: #{r.body}" if r.status >= 300 - end - - private - - def get_cache_buster_url(url) - uri = Addressable::URI.parse(url) - "#{uri.scheme}://#{uri.authority}/cache?path=#{Addressable::URI.encode(uri.path)}" - end -end diff --git a/app/jobs/youtube_media_job.rb b/app/jobs/youtube_media_job.rb deleted file mode 100644 index c744f6e74..000000000 --- a/app/jobs/youtube_media_job.rb +++ /dev/null @@ -1,35 +0,0 @@ -class YoutubeMediaJob < ApplicationJob - queue_as :default - - def perform(media) - info = YoutubeHelper::fetch_info(media.video_id) - - media.url = info[:url] - media.title = info[:title] - media.authors = info[:authors] - media.duration = info[:duration] - media.channel_id = info[:channel_id] - media.channel_title = info[:channel_title] - media.source_published_at = info[:published] - media.video_description = info[:description] - - # Fetch thumbnail - r = Excon.get(info[:thumbnail]) - - raise "Error while requesting Youtube thumbnail\nStatus: #{r.status}\nBody: #{r.body}" if r.status >= 300 - - tmp = Tempfile.new([media.video_id, '.jpg'], Dir.tmpdir) - - begin - tmp.binmode - tmp.write(r.body) - tmp.rewind - media.attachment = tmp - ensure - tmp.close - tmp.unlink - end - - media.save! - end -end diff --git a/app/models/abilities/user_ability.rb b/app/models/abilities/user_ability.rb index ef6241431..6af0aee74 100644 --- a/app/models/abilities/user_ability.rb +++ b/app/models/abilities/user_ability.rb @@ -7,31 +7,18 @@ def allowed(user, subject) if subject.is_a? Class if subject == User; abilities += user_class_abilities(user) elsif subject == Tenant; abilities += tenant_class_abilities(user) - elsif subject == Post; abilities += post_class_abilities(user) - elsif subject == Media; abilities += media_class_abilities(user) - elsif subject == Category; abilities += category_class_abilities(user) elsif subject == Localization; abilities += localization_class_abilities(user) elsif subject == Locale; abilities += locale_class_abilities(user) elsif subject == Application; abilities += application_class_abilities(user); - elsif subject == BulkJob; abilities += bulk_job_class_abilities(user); - elsif subject == Document; abilities += document_class_abilities(user); - elsif subject == Webpage; abilities += webpage_class_abilities(user); - elsif subject == Snippet; abilities += snippet_class_abilities(user); elsif subject == ContentType; abilities += content_type_class_abilities(user); elsif subject == ContentItem; abilities += content_item_class_abilities(user); end else if subject.kind_of? User; abilities += user_abilities(user, subject) elsif subject.kind_of? Tenant; abilities += tenant_abilities(user, subject) - elsif subject.kind_of? Post; abilities += post_abilities(user, subject) - elsif subject.kind_of? Media; abilities += media_abilities(user, subject) elsif subject.kind_of? Localization; abilities += localization_abilities(user, subject) elsif subject.kind_of? Locale; abilities += locale_abilities(user, subject) elsif subject.kind_of? Application; abilities += application_abilities(user, subject) - elsif subject.kind_of? BulkJob; abilities += bulk_job_abilities(user, subject) - elsif subject.kind_of? Document; abilities += document_abilities(user, subject) - elsif subject.kind_of? Webpage; abilities += webpage_abilities(user, subject) - elsif subject.kind_of? Snippet; abilities += snippet_abilities(user, subject) elsif subject.kind_of? ContentType; abilities += content_type_abilities(user, subject) elsif subject.kind_of? ContentItem; abilities += content_item_abilities(user, subject) end @@ -77,26 +64,6 @@ def tenant_class_abilities(user) end end - def post_abilities(user, post) - [:view, :update, :delete] - end - - def post_class_abilities(user) - [:view, :create] - end - - def media_abilities(user, media) - [:view, :update, :delete] - end - - def media_class_abilities(user) - [:view, :create] - end - - def category_class_abilities(user) - [:view] - end - def localization_abilities(user, localization) [:view, :update, :delete] end @@ -129,46 +96,6 @@ def application_class_abilities(user) end end - def bulk_job_abilities(user, bulk_job) - [:view, :update, :delete] - end - - def bulk_job_class_abilities(user) - [:view, :create] - end - - def document_abilities(user, document) - [:view, :update, :delete] - end - - def document_class_abilities(user) - [:view, :create] - end - - def webpage_abilities(user, webpage) - if user.is_admin? - [:view, :update, :delete] - else - [:view] - end - end - - def webpage_class_abilities(user) - if user.is_admin? - [:view, :create] - else - [:view] - end - end - - def snippet_abilities(user, snippet) - [:view, :update, :delete] - end - - def snippet_class_abilities(user) - [:view, :create] - end - def content_type_abilities(user, snippet) [:view] end diff --git a/app/models/author.rb b/app/models/author.rb deleted file mode 100644 index 1819e98a1..000000000 --- a/app/models/author.rb +++ /dev/null @@ -1,10 +0,0 @@ -class Author < ApplicationRecord - include HasGravatar - include HasFirstnameLastname - - scope :published, -> { joins(:posts).where('authors.user_id IS NOT NULL AND posts.published_at <= ?', DateTime.now) } - - store_accessor :sites, :personal, :facebook, :twitter, :google - belongs_to :user, touch: true - has_many :posts -end diff --git a/app/models/bulk_job.rb b/app/models/bulk_job.rb deleted file mode 100644 index 51efc62d7..000000000 --- a/app/models/bulk_job.rb +++ /dev/null @@ -1,13 +0,0 @@ -class BulkJob < ApplicationRecord - belongs_to :user - - serialize :log - - has_attached_file :metadata - has_attached_file :assets - - # Restore content type validation for :metadata once Rails/Paperclip fixes downloaded CSVs (from S3) content type showing as 'application/force-download' - validates_attachment :metadata, :presence => true - validates_attachment_content_type :assets, :content_type => ['application/zip'] - validates_presence_of :content_type -end diff --git a/app/models/category.rb b/app/models/category.rb deleted file mode 100644 index df34cd952..000000000 --- a/app/models/category.rb +++ /dev/null @@ -1,8 +0,0 @@ -class Category < ApplicationRecord - acts_as_nested_set - scope :job_phases, -> { where(depth: 0) } - scope :categories, -> { where(depth: 1) } - - belongs_to :user - has_and_belongs_to_many :posts -end diff --git a/app/models/concerns/searchable.rb b/app/models/concerns/searchable.rb deleted file mode 100644 index 1fd9acb2a..000000000 --- a/app/models/concerns/searchable.rb +++ /dev/null @@ -1,45 +0,0 @@ -module Searchable - extend ActiveSupport::Concern - - included do - include Elasticsearch::Model - include Elasticsearch::Model::Callbacks - index_name [Rails.env, model_name.collection.gsub(/\//, '-')].join('_') - - class << self - def query_massage q - return '*' if q.nil? or q.empty? - result = q.chomp.strip - return '*' if result.nil? or result.empty? - result.index(/\s|\-/).nil? ? "#{result}*" : result - end - - def term_search(field, q) - result = { - term: { field => q } - } - end - - def terms_search(field, q) - result = { - terms: { field => q } - } - end - - def range_search(field, type, q) - result = { - range: { field => { type => q } } - } - end - - def published_filter - # Bring in documents based on Draft status, Published date met, or either: Expired date not yet met, or Expired date null - [ - {bool: {must: [term_search(:draft, false)]}}, - {bool: {must: [range_search(:published_at, :lte, DateTime.now.to_s)]}}, - {bool: {should: [range_search(:expired_at, :gte, DateTime.now.to_s), {bool: {must_not: {exists: { field: :expired_at }}}}]}} - ] - end - end - end -end diff --git a/app/models/concerns/searchable_media.rb b/app/models/concerns/searchable_media.rb deleted file mode 100644 index a951e51e9..000000000 --- a/app/models/concerns/searchable_media.rb +++ /dev/null @@ -1,57 +0,0 @@ -module SearchableMedia - extend ActiveSupport::Concern - - included do - include Searchable - - settings :analysis => { - :analyzer => { - :taxon_analyzer => { - :type => 'custom', - :tokenizer => 'standard', - :filter => %w(standard lowercase ngram) - } - } - } do - mapping do - indexes :id, :type => :integer, :index => :not_analyzed - indexes :tenant_id, :type => :integer, :index => :not_analyzed - indexes :name, :analyzer => :snowball - indexes :created_by, :analyzer => :keyword - indexes :file_name, :analyzer => :keyword - indexes :description, :analyzer => :snowball - indexes :tag_list, :type => :string, :analyzer => :keyword - indexes :created_at, :type => :date, :include_in_all => false - indexes :taxon, :analyzer => :taxon_analyzer - indexes :meta, :type => :object - end - end - - def as_indexed_json(options = {}) - json = as_json(options) - json[:created_by] = user.fullname - json[:tags] = tag_list.to_a - json[:taxon] = create_taxon - json[:tenant_id] = user.tenant.id - json - end - end - - module ClassMethods - # TODO: Rewrite to handle facets - def search_with_params(params, tenant) - query = { multi_match: { fields: %w(name^2 _all), query: query_massage(params[:q]) } } - filter = { term: { tenant_id: tenant.id } } - bool = { bool: { must: [query], filter: [filter] } } - - search query: bool - end - - def show_all(tenant) - filter = { term: { tenant_id: tenant.id } } - bool = { bool: { filter: [filter] } } - - search query: bool, sort: [{ created_at: { order: 'desc' } }] - end - end -end diff --git a/app/models/concerns/searchable_onet_occupation.rb b/app/models/concerns/searchable_onet_occupation.rb deleted file mode 100644 index 5f717dffe..000000000 --- a/app/models/concerns/searchable_onet_occupation.rb +++ /dev/null @@ -1,21 +0,0 @@ -module SearchableOnetOccupation - extend ActiveSupport::Concern - - included do - include Searchable - - mapping do - indexes :id, :type => :integer, :index => :not_analyzed - indexes :soc, :analyzer => 'keyword' - indexes :title, :analyzer => 'snowball' - indexes :description, :analyzer => 'snowball' - end - end - - module ClassMethods - def search_with_params(params) - query = self.query_massage(params[:q]) - self.search query - end - end -end diff --git a/app/models/concerns/searchable_post.rb b/app/models/concerns/searchable_post.rb deleted file mode 100644 index 16ef872da..000000000 --- a/app/models/concerns/searchable_post.rb +++ /dev/null @@ -1,122 +0,0 @@ -module SearchablePost - extend ActiveSupport::Concern - - included do - include Searchable - - mapping do - indexes :title, :analyzer => :snowball - indexes :body, :analyzer => :snowball - indexes :draft, :type => :boolean - indexes :short_description, :analyzer => :snowball - indexes :copyright_owner, :analyzer => :keyword - indexes :author, :analyzer => :keyword - indexes :created_at, :type => :date, :include_in_all => false - indexes :published_at, :type => :date, :include_in_all => false - indexes :expired_at, :type => :date, :include_in_all => false - indexes :tags, :analyzer => :keyword - indexes :categories, :analyzer => :keyword - indexes :job_phase, :analyzer => :keyword - indexes :type, :analyzer => :keyword - indexes :industries, :analyzer => :keyword - indexes :is_published, :type => :boolean - indexes :is_sticky, :type => :boolean - - indexes :id, :type => :integer, :index => :not_analyzed - indexes :tenant_id, :type => :integer, :index => :not_analyzed - indexes :tag_list, :type => :text, :index => :not_analyzed - end - - def as_indexed_json(options = {}) - json = as_json(only: [:id, :title, :body, :draft, :short_description, :copyright_owner, - :created_at, :published_at, :expired_at, :job_phase, :type, :is_sticky]) - json[:categories] = categories.collect { |c| c.name } - json[:industries] = industries.collect { |i| i.soc } - json[:tags] = tag_list.to_a - json[:author] = author ? author.fullname : custom_author - json[:tenant_id] = user.tenant.id - json[:is_published] = self.published? - json - end - - def related(tenant, published = nil) - bool = {bool: {should: [], filter: [{term: {tenant_id: tenant.id}}]}} - - if published - bool[:bool][:filter] << ::Post.published_filter - end - - mlt = [{ - more_like_this: { - fields: %w(title short_description job_phase categories tags), - docs: [ - { - _id: id - } - ], - min_doc_freq: 1, - min_term_freq: 1, - include: false - } - } - ] - - bool[:bool][:should] << mlt - ::Post.search query: bool - end - end - - class_methods do - def search_with_params(params, tenant, published = nil) - q = params[:q] - categories = params[:categories] - job_phase = params[:job_phase] - post_type = params[:post_type] - industries = params[:industries] - author = params[:author] - tags = params[:tags] - - bool = {bool: {must: [], filter: [{term: {tenant_id: tenant.id}}]}} - - if q - bool[:bool][:must] << {multi_match: {fields: %w(title^2 _all), query: query_massage(q)}} - end - if categories - bool[:bool][:filter] << terms_search(:categories, categories.split(',')) - end - if job_phase - bool[:bool][:filter] << terms_search(:job_phase, job_phase.split(',')) - end - if post_type - bool[:bool][:filter] << terms_search(:type, post_type.split(',')) - end - if industries - bool[:bool][:filter] << terms_search(:industries, industries.split(',')) - end - if author - bool[:bool][:filter] << term_search(:author, author) - end - if tags - bool[:bool][:filter] << terms_search(:tags, tags.split(',')) - end - - if published - bool[:bool][:filter] << published_filter - search query: bool, sort: [{is_sticky: {order: 'desc'}, published_at: {order: 'desc'}}] - else - search query: bool - end - end - - def show_all(tenant, published = nil) - bool = {bool: {filter: [{term: {tenant_id: tenant.id}}]}} - - if published - bool[:bool][:filter] << published_filter - search query: bool, sort: [{is_sticky: {order: 'desc'}, published_at: {order: 'desc'}}] - else - search query: bool, sort: [{is_sticky: {order: 'desc'}, created_at: {order: 'desc'}}] - end - end - end -end diff --git a/app/models/concerns/searchable_user.rb b/app/models/concerns/searchable_user.rb deleted file mode 100644 index 94bb20d0f..000000000 --- a/app/models/concerns/searchable_user.rb +++ /dev/null @@ -1,38 +0,0 @@ -module SearchableUser - extend ActiveSupport::Concern - - included do - include Searchable - - mapping do - indexes :id, :type => :integer, :index => :not_analyzed - indexes :tenant_id, :type => :integer, :index => :not_analyzed - indexes :email, :analyzer => :snowball - indexes :fullname, :analyzer => :keyword - indexes :created_at, :type => :date, :include_in_all => false - end - - def as_indexed_json(options = {}) - json = as_json(options) - json[:tenant_id] = tenant.id - json - end - end - - module ClassMethods - def search_with_params(params, tenant_id) - query = { match: { '_all': query_massage(params[:q]) } } - filter = { term: { tenant_id: tenant_id } } - bool = { bool: { must: [query], filter: [filter] } } - - search query: bool - end - - def show_all(tenant_id) - filter = { term: { tenant_id: tenant_id } } - bool = { bool: { filter: [filter] } } - - search query: bool, sort: [{ created_at: { order: 'desc' } }] - end - end -end diff --git a/app/models/concerns/searchable_webpage.rb b/app/models/concerns/searchable_webpage.rb deleted file mode 100644 index 6854bb5f0..000000000 --- a/app/models/concerns/searchable_webpage.rb +++ /dev/null @@ -1,61 +0,0 @@ -module SearchableWebpage - extend ActiveSupport::Concern - - included do - include Searchable - - mapping do - indexes :name, :analyzer => :snowball - indexes :url, :analyzer => :keyword - indexes :dynamic_yield_sku, :analyzer => :keyword - indexes :dynamic_yield_category, :analyzer => :keyword - indexes :created_by, :analyzer => :keyword - indexes :created_at, :type => :date, :include_in_all => false - indexes :deleted_at, :type => :date, :include_in_all => false - indexes :updated_at, :type => :date, :include_in_all => false - - indexes :id, :type => :integer, :index => :not_analyzed - indexes :tenant_id, :type => :integer, :index => :not_analyzed - indexes :user_id, :type => :integer, :index => :not_analyzed - indexes :thumbnail_file_name, :type => :string, :index => :not_analyzed - indexes :thumbnail_content_type, :type => :string, :index => :not_analyzed - indexes :thumbnail_file_size, :type => :long, :index => :not_analyzed - indexes :thumbnail_updated_at, :type => :date, :index => :not_analyzed - indexes :seo_title, :type => :string, :index => :not_analyzed - indexes :seo_description, :type => :string, :index => :not_analyzed - indexes :noindex, :type => :boolean, :index => :not_analyzed - indexes :nofollow, :type => :boolean, :index => :not_analyzed - indexes :nosnippet, :type => :boolean, :index => :not_analyzed - indexes :noodp, :type => :boolean, :index => :not_analyzed - indexes :noarchive, :type => :boolean, :index => :not_analyzed - indexes :noimageindex, :type => :boolean, :index => :not_analyzed - indexes :tables_widget, :type => :nested, :enabled => false - indexes :accordion_group_widget, :type => :nested, :enabled => false - indexes :charts_widget, :type => :nested, :enabled => false - end - - def as_indexed_json(options = {}) - json = as_json(options) - json[:created_by] = user.fullname - json[:tenant_id] = user.tenant.id - json - end - end - - module ClassMethods - def search_with_params(params, tenant) - query = { multi_match: { fields: %w(name^2 _all), query: query_massage(params[:q]) } } - filter = { term: { tenant_id: tenant.id } } - bool = { bool: { must: [query], filter: [filter] } } - - search query: bool - end - - def show_all(tenant) - filter = { term: { tenant_id: tenant.id } } - bool = { bool: { filter: [filter] } } - - search query: bool, sort: [{ created_at: { order: 'desc' } }] - end - end -end diff --git a/app/models/concerns/taxon.rb b/app/models/concerns/taxon.rb deleted file mode 100644 index c07efb1f3..000000000 --- a/app/models/concerns/taxon.rb +++ /dev/null @@ -1,34 +0,0 @@ -module Taxon - extend ActiveSupport::Concern - - included do - def taxon - @taxon ||= create_taxon - end - - def taxon=(taxon) - @taxon = taxon - end - - def self.taxon_class_name taxon_name=nil - @taxon_class_name = taxon_name || @taxon_class_name || self.name - end - - def self.taxon_class_name=(taxon_name) - @taxon_class_name = taxon_name - end - - private - - def create_taxon - module_type = self.class.taxon_class_name.first.upcase - taxon_date = created_at.strftime("%y%m%d") - "#{module_type}#{taxon_type}#{taxon_date}#{taxon_created_at_index}" - end - - def taxon_created_at_index - # Returns count of assets created that day as hex - '%04x' % self.class.with_deleted.where(created_at: Time.new(created_at.year, created_at.month, created_at.day)..created_at).count - end - end -end diff --git a/app/models/document.rb b/app/models/document.rb deleted file mode 100644 index b197c6e2f..000000000 --- a/app/models/document.rb +++ /dev/null @@ -1,7 +0,0 @@ -class Document < ApplicationRecord - acts_as_paranoid - - belongs_to :user - has_many :snippets - has_many :webpages, through: :snippets -end diff --git a/app/models/media.rb b/app/models/media.rb deleted file mode 100644 index 352d3211b..000000000 --- a/app/models/media.rb +++ /dev/null @@ -1,91 +0,0 @@ -module PaperclipExtensions - module Attachment - def arbitrary_url_for(pattern, style_name = :original) - Paperclip::Interpolations.interpolate pattern, self, style_name - end - end -end - -class Media < ApplicationRecord - include SearchableMedia - include Taxon - include FindByTenant - - acts_as_taggable - acts_as_paranoid - - belongs_to :user - has_and_belongs_to_many :posts - - default_scope { order('created_at DESC') } - - scope :consumed, lambda { joins(:posts).where('posts.id is not null') } - - serialize :dimensions - - has_attached_file :attachment, - :styles => { - :large => {geometry: '1800x1800>', format: :jpg}, - :medium => {geometry: '800x800>', format: :jpg}, - :default => {geometry: '300x300>', format: :jpg}, - :mini => {geometry: '100x100>', format: :jpg}, - :micro => {geometry: '50x50>', format: :jpg}, - :ar_post => {geometry: '1140x', format: :jpg} - }, - :processors => [:thumbnail, :paperclip_optimizer], - :preserve_files => 'true', - # :path => ':class/:attachment/:style-:id.:extension' - :path => ':class/:attachment/careerbuilder-:style-:id.:extension', - :s3_headers => { 'Cache-Control' => 'public, max-age=315576000' } - - before_post_process :can_thumb? - - validates_attachment :attachment, - :presence => true, - :unless => :skip_attachment_validation, - :content_type => {:content_type => Cortex.config.media.allowed_media_types.to_a.collect { |allowed| allowed[:type] }}, - :size => {:in => 0..Cortex.config.media.max_size_mb.to_i.megabytes} - - validates :type, inclusion: {in: %w(Media Youtube)} - - Paperclip::Attachment.include PaperclipExtensions::Attachment - - def consumed? - Media.consumed.include?(self) - end - - # Human friendly content type generalization - def content_type - if (attachment_content_type =~ /(excel)|(spreadsheet)/) != nil - 'spreadsheet' - elsif (attachment_content_type =~ /(^application\/vnd\.)|(^application\/msword)/) != nil - 'doc' - elsif attachment_content_type =~ /pdf/ - 'pdf' - elsif attachment_content_type =~ /zip/ - 'archive' - else - attachment_content_type.match(/(\w+)\//)[1] - end - end - - def url - attachment.url - end - - def can_thumb? - Cortex.config.media.allowed_media_types.to_a.select { |allowed| allowed[:thumb] && allowed[:type] == attachment_content_type } != [] - end - - def skip_attachment_validation - false - end - - private - - def taxon_type - if attachment_content_type - Cortex.config.media.allowed_media_types.to_a.find { |t| t[:type] == attachment_content_type }[:taxon_type] - end - end -end diff --git a/app/models/media_types/youtube.rb b/app/models/media_types/youtube.rb deleted file mode 100644 index 28c6510d5..000000000 --- a/app/models/media_types/youtube.rb +++ /dev/null @@ -1,22 +0,0 @@ -class Youtube < Media - # index_name 'media' - index_name [Rails.env, 'media'].join('_') - document_type 'media' - taxon_class_name 'media' - - store_accessor :meta, :url, :duration, :video_id, :title, :authors, :channel_id, :source_published_at, :video_description, :channel_title - - validates :video_id, presence: true - - def content_type - 'youtube' - end - - def skip_attachment_validation - true - end - - def taxon_type - 'VID' - end -end diff --git a/app/models/observers/media_observer.rb b/app/models/observers/media_observer.rb deleted file mode 100644 index 24d640e7d..000000000 --- a/app/models/observers/media_observer.rb +++ /dev/null @@ -1,38 +0,0 @@ -class MediaObserver < ActiveRecord::Observer - def before_save(media) - extract_dimensions(media) - generate_digest(media) - end - - def before_destroy(media) - prevent_consumed_deletion(media) - end - - private - - def image?(media) - media.attachment_content_type =~ %r{^(image|(x-)?application)/(bmp|gif|jpeg|jpg|pjpeg|png|x-png)$} - end - - def extract_dimensions(media) - return unless image?(media) - tempfile = media.attachment.queued_for_write[:original] - unless tempfile.nil? - geometry = Paperclip::Geometry.from_file(tempfile) - media.dimensions = [geometry.width.to_i, geometry.height.to_i] - end - end - - def generate_digest(media) - tempfile = media.attachment.queued_for_write[:original] - unless tempfile.nil? - media.digest = Digest::SHA1.file(tempfile.path).to_s - end - end - - def prevent_consumed_deletion(media) - if media.consumed? - raise Cortex::Exceptions::ResourceConsumed - end - end -end diff --git a/app/models/observers/post_observer.rb b/app/models/observers/post_observer.rb deleted file mode 100644 index 7ad71730f..000000000 --- a/app/models/observers/post_observer.rb +++ /dev/null @@ -1,21 +0,0 @@ -class PostObserver < ActiveRecord::Observer - def before_save(post) - update_media!(post) - end - - private - - def update_media!(post) - post.media = find_all_associated_media(post) - end - - def find_all_associated_media(post) - find_media_from_body(post).push(post.featured_media, post.tile_media).compact.uniq - end - - def find_media_from_body(post) - document = Nokogiri::HTML::Document.parse(post.body) - media_ids = document.xpath('//@data-media-id').map{|element| element.to_s } - Media.find(media_ids) - end -end diff --git a/app/models/observers/tenant_observer.rb b/app/models/observers/tenant_observer.rb deleted file mode 100644 index e414143e6..000000000 --- a/app/models/observers/tenant_observer.rb +++ /dev/null @@ -1,11 +0,0 @@ -class TenantObserver < ActiveRecord::Observer - def before_save(tenant) - init(tenant) - end - - private - - def init(tenant) - tenant.subdomain ||= tenant.name.mb_chars.normalize(:kd).downcase.gsub(/[^a-z0-9]/, '').to_s - end -end diff --git a/app/models/observers/user_observer.rb b/app/models/observers/user_observer.rb deleted file mode 100644 index 0b4b2266f..000000000 --- a/app/models/observers/user_observer.rb +++ /dev/null @@ -1,21 +0,0 @@ -class UserObserver < ActiveRecord::Observer - def after_create(user) - add_author(user) - end - - def before_destroy(user) - prevent_consumed_deletion(user) - end - - private - - def add_author(user) - user.author = Author.create(user_id: user.id, firstname: user.firstname, lastname: user.lastname, email: user.email) - end - - def prevent_consumed_deletion(user) - if user.referenced? - raise Cortex::Exceptions::ResourceConsumed - end - end -end diff --git a/app/models/observers/youtube_observer.rb b/app/models/observers/youtube_observer.rb deleted file mode 100644 index 1fe243bb7..000000000 --- a/app/models/observers/youtube_observer.rb +++ /dev/null @@ -1,5 +0,0 @@ -class YoutubeObserver < ActiveRecord::Observer - def after_commit(media) - YoutubeMediaJob.perform_later(media) - end -end diff --git a/app/models/onet.rb b/app/models/onet.rb deleted file mode 100644 index 938ad3409..000000000 --- a/app/models/onet.rb +++ /dev/null @@ -1,5 +0,0 @@ -module Onet - def self.table_name_prefix - 'onet_' - end -end diff --git a/app/models/onet/occupation.rb b/app/models/onet/occupation.rb deleted file mode 100644 index 2f194b557..000000000 --- a/app/models/onet/occupation.rb +++ /dev/null @@ -1,13 +0,0 @@ -module Onet - class Occupation < ApplicationRecord - include SearchableOnetOccupation - - has_one :post - - # ONET represents its hierarchy in its SOC code - industries always have 0000 after the dash, - # and the two-digit identifier before the dash represents the industry code itself. - scope :industries, -> { - where('soc like ?', '%0000%') - } - end -end diff --git a/app/models/post.rb b/app/models/post.rb deleted file mode 100644 index 8fa4f1862..000000000 --- a/app/models/post.rb +++ /dev/null @@ -1,75 +0,0 @@ -class Post < ApplicationRecord - include SearchablePost - include FindByTenant - - default_scope -> { includes(:categories, :media, :industries) } - scope :published, -> { where('published_at <= ? and draft = ? and (expired_at >= ? OR expired_at is null)', DateTime.now, false, DateTime.now) } - scope :last_updated_at, -> { order(updated_at: :desc).select('updated_at').first.updated_at } - scope :find_by_body_text, ->(query) { where("body LIKE :query", query: "%#{query}%") } - - acts_as_taggable - acts_as_taggable_on :seo_keywords - - has_and_belongs_to_many :media, class_name: 'Media' - has_and_belongs_to_many :categories - has_and_belongs_to_many :industries, class_name: '::Onet::Occupation', - association_foreign_key: 'onet_occupation_id' - belongs_to :author - belongs_to :user # TODO: rename creator - belongs_to :featured_media, class_name: 'Media' - belongs_to :tile_media, class_name: 'Media' - belongs_to :primary_category, class_name: 'Category' - belongs_to :primary_industry, class_name: '::Onet::Occupation' - - validate :unique_slug?, :primary_category_must_be_in_categories, :primary_industry_must_be_in_industries - validates :title, presence: true, length: { minimum: 1, maximum: 255 } - validates :type, :job_phase, :display, presence: true, allow_nil: false - validates :slug, presence: true, length: { minimum: 1, maximum: 255 } - - enum job_phase: ['Discovery', 'Find the Job', 'Get the Job', 'On the Job'] - enum display: [:large, :medium, :small] - - validates :type, inclusion: { in: %w(Post ArticlePost InfographicPost PromoPost VideoPost) } - - def published? - !(draft || expired? || pending?) - end - - def expired? - expired_at ? expired_at <= DateTime.now : false - end - - def pending? - published_at ? published_at >= DateTime.now : false - end - - class << self - def find_by_id_or_slug(id_or_slug) - if id_or_slug.to_s =~ /^\d+$/ - Post.find_by id: id_or_slug.to_i - else - Post.find_by slug: id_or_slug - end - end - end - - private - - def unique_slug? - if Post.find_by_user_tenant(user).where.not(id: id).exists?(slug: slug) - errors.add :slug, 'has already been taken in this tenant' - end - end - - def primary_category_must_be_in_categories - unless categories.to_a.empty? || categories.collect{ |c| c.id}.include?(primary_category_id) - errors.add(:primary_category_id, 'must be in categories') - end - end - - def primary_industry_must_be_in_industries - unless industries.to_a.empty? || industries.collect{ |i| i.id}.include?(primary_industry_id) - errors.add(:primary_industry_id, 'must be in industries') - end - end -end diff --git a/app/models/post_types/article_post.rb b/app/models/post_types/article_post.rb deleted file mode 100644 index ed2c62657..000000000 --- a/app/models/post_types/article_post.rb +++ /dev/null @@ -1,11 +0,0 @@ -class ArticlePost < Post - index_name [Rails.env, 'posts'].join('_') - document_type 'post' - - validates :copyright_owner, presence: true, length: { minimum: 1, maximum: 255 } - validates :short_description, presence: true, length: { minimum: 25, maximum: 255 } - validates :tag_list, :seo_keyword_list, :seo_title, :seo_description, length: { maximum: 255 } - - # TODO: Figure out a way to get this properly abstracted - enum display: [:large, :medium, :small] -end diff --git a/app/models/post_types/infographic_post.rb b/app/models/post_types/infographic_post.rb deleted file mode 100644 index 542717907..000000000 --- a/app/models/post_types/infographic_post.rb +++ /dev/null @@ -1,7 +0,0 @@ -class InfographicPost < Post - index_name [Rails.env, 'posts'].join('_') - document_type 'post' - - # TODO: Figure out a way to get this properly abstracted - enum display: [:large, :medium, :small] -end diff --git a/app/models/post_types/promo_post.rb b/app/models/post_types/promo_post.rb deleted file mode 100644 index 1557e564a..000000000 --- a/app/models/post_types/promo_post.rb +++ /dev/null @@ -1,10 +0,0 @@ -class PromoPost < Post - index_name [Rails.env, 'posts'].join('_') - document_type 'post' - store_accessor :meta, :destination_url, :call_to_action - - # TODO: Figure out a way to get this properly abstracted - enum display: [:large, :medium, :small] - - validates :destination_url, :call_to_action, presence: true, allow_nil: false -end diff --git a/app/models/post_types/video_post.rb b/app/models/post_types/video_post.rb deleted file mode 100644 index 44213d72e..000000000 --- a/app/models/post_types/video_post.rb +++ /dev/null @@ -1,11 +0,0 @@ -class VideoPost < Post - index_name [Rails.env, 'posts'].join('_') - document_type 'post' - - validates :copyright_owner, presence: true, length: { minimum: 1, maximum: 255 } - validates :short_description, presence: true, length: { minimum: 25, maximum: 255 } - validates :tag_list, :seo_keyword_list, :seo_title, :seo_description, length: { maximum: 255 } - - # TODO: Figure out a way to get this properly abstracted - enum display: [:large, :medium, :small] -end diff --git a/app/models/snippet.rb b/app/models/snippet.rb deleted file mode 100644 index 4c1ecaf51..000000000 --- a/app/models/snippet.rb +++ /dev/null @@ -1,13 +0,0 @@ -class Snippet < ApplicationRecord - include FindByTenant - - scope :find_by_body_text, ->(query) { joins(:document).where("documents.body LIKE :query", query: "%#{query}%") } - - acts_as_paranoid - - belongs_to :user - belongs_to :webpage - belongs_to :document - - accepts_nested_attributes_for :document -end diff --git a/app/models/tenant.rb b/app/models/tenant.rb index ff65197ea..307d2b9fa 100644 --- a/app/models/tenant.rb +++ b/app/models/tenant.rb @@ -11,6 +11,8 @@ class Tenant < ApplicationRecord validates_presence_of :name validates_associated :owner + before_save :init + def is_organization? self.root? end @@ -18,4 +20,10 @@ def is_organization? def has_children? !self.leaf? end + + private + + def init + self.subdomain ||= self.name.mb_chars.normalize(:kd).downcase.gsub(/[^a-z0-9]/, '').to_s + end end diff --git a/app/models/user.rb b/app/models/user.rb index a3e1be6aa..346037663 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -3,7 +3,6 @@ class User < ApplicationRecord include HasGravatar include HasFirstnameLastname - include SearchableUser # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :rememberable, :trackable, :validatable, :recoverable @@ -11,11 +10,7 @@ class User < ApplicationRecord rolify belongs_to :tenant - has_one :author - has_many :media has_many :tenants - has_many :posts - has_many :posts, through: :authors has_many :localizations has_many :locales has_many :role_permissions, through: :roles @@ -24,8 +19,10 @@ class User < ApplicationRecord validates_presence_of :email, :tenant, :firstname, :lastname + before_destroy :prevent_consumed_deletion + def referenced? - [Media, Post, Locale, Localization, BulkJob].find do |resource| + [ContentItem].find do |resource| true if resource.where(user: self).count > 0 end end @@ -67,6 +64,10 @@ def allowed_permissions(resource_class, permission) permissions.select { |perm| perm.resource_type == resource_class.to_s && perm.name == permission } end + def prevent_consumed_deletion + raise Cortex::Exceptions::ResourceConsumed if referenced? + end + class << self def authenticate(username, password) user = User.find_by_email(username) diff --git a/app/models/webpage.rb b/app/models/webpage.rb deleted file mode 100644 index 26124304e..000000000 --- a/app/models/webpage.rb +++ /dev/null @@ -1,79 +0,0 @@ -class Webpage < ApplicationRecord - include FindByTenant - include SearchableWebpage - - serialize :tables_widget - serialize :charts_widget - - scope :agnostic_guess_by_url, ->(url) { where('url LIKE :url', url: "%#{url}%") } - - acts_as_paranoid - acts_as_taggable_on :seo_keywords - - belongs_to :user - has_many :snippets, inverse_of: :webpage - has_many :documents, through: :snippets, :dependent => :destroy - - accepts_nested_attributes_for :snippets - - def self.agnostic_find_by_url(url) - url = protocol_agnostic_url(url) - agnostic_guess_by_url(url).find { |webpage| protocol_agnostic_url(webpage.url) == url } - end - - def tables_widget_yaml - tables_widget.to_yaml - end - - def tables_widget_yaml= p - self.tables_widget = YAML.load(p) - end - - def tables_widget_json - tables_widget.to_json - end - - def tables_widget_json= p - self.tables_widget = JSON.parse(p, quirks_mode: true) # Quirks mode will let us parse a null JSON object - end - - def charts_widget_yaml - charts_widget.to_yaml - end - - def charts_widget_yaml= p - self.charts_widget = YAML.load(p) - end - - def charts_widget_json - charts_widget.to_json - end - - def charts_widget_json= p - self.charts_widget = JSON.parse(p, quirks_mode: true) # Quirks mode will let us parse a null JSON object - end - - def accordion_group_widget_yaml - accordion_group_widget.to_yaml - end - - def accordion_group_widget_yaml= p - self.accordion_group_widget = YAML.load(p) - end - - def accordion_group_widget_json - accordion_group_widget.to_json - end - - def accordion_group_widget_json= p - self.accordion_group_widget = JSON.parse(p, quirks_mode: true) # Quirks mode will let us parse a null JSON object - end - - private - - def self.protocol_agnostic_url(url) - uri = Addressable::URI.parse(url) - path = uri.path == '/' ? uri.path : uri.path.chomp('/') - "://#{uri.authority}#{path}" - end -end diff --git a/app/views/authentication/sessions/new.html.haml b/app/views/authentication/sessions/new.html.haml index 90b595e59..6f82c68e6 100644 --- a/app/views/authentication/sessions/new.html.haml +++ b/app/views/authentication/sessions/new.html.haml @@ -1,4 +1,20 @@ .mdl-cell.mdl-cell--4-col.mdl-cell--12-col-tablet .mdl-grid.mdl-card .mdl-cell.mdl-cell--12-col - = render 'partials/authentication/login_tabs' + = form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| + .mdl-textfield.mdl-js-textfield + = f.email_field :email, autofocus: true, class: 'mdl-textfield__input' + = f.label :email, class: 'mdl-textfield__label' + .mdl-textfield.mdl-js-textfield + = f.password_field :password, autocomplete: "off", class: 'mdl-textfield__input' + = f.label :password, class: 'mdl-textfield__label' + - if devise_mapping.rememberable? + = f.label :remember_me, class: 'mdl-switch mdl-js-switch mdl-js-ripple-effect' do + = f.check_box :remember_me, value: true, class: 'mdl-switch__input' + %span.mdl-switch__label + Remember me + %br/ + %br/ + + = f.submit "Log in", class: 'mdl-button mdl-js-button mdl-button--raised mdl-button--colored' + = render "authentication/shared/links" diff --git a/app/views/hello_world/index.html.haml b/app/views/hello_world/index.html.haml deleted file mode 100644 index 74651680e..000000000 --- a/app/views/hello_world/index.html.haml +++ /dev/null @@ -1,4 +0,0 @@ -%h1 Hello World -= react_component("HelloWorldApp", props: @hello_world_props) - -= cell(Plugins::Core::ReactTestCell).(:show) diff --git a/app/views/layouts/legacy_application.haml b/app/views/layouts/legacy_application.haml deleted file mode 100644 index 1b110830b..000000000 --- a/app/views/layouts/legacy_application.haml +++ /dev/null @@ -1,15 +0,0 @@ -!!! 5 -%html{lang: 'en', :'ng-app' => 'cortex'} - %head - %meta{content: 'IE=edge', 'http-equiv' => 'X-UA-Compatible'} - %meta{charset: 'utf-8'} - %meta{name: 'viewport', content: 'width=device-width, height=device-height, initial-scale=1.0, user-scalable=0'} - %title Cortex Administration - = favicon_link_tag 'favicon.ico' - = stylesheet_link_tag :legacy_application - = csrf_meta_tags - %body.default{:'ng-controller' => 'CortexCtrl', :'ng-cloak' => ''} - = yield - = Gon::Base.render_data - = javascript_include_tag :legacy_application - = render 'layouts/google_analytics' if extra_config.google_analytics_id? diff --git a/app/views/legacy/index.html.haml b/app/views/legacy/index.html.haml deleted file mode 100644 index 0b5892fb7..000000000 --- a/app/views/legacy/index.html.haml +++ /dev/null @@ -1 +0,0 @@ -%div{'ui-view' => ''} diff --git a/app/views/partials/authentication/_login_tabs.html.haml b/app/views/partials/authentication/_login_tabs.html.haml deleted file mode 100644 index b41d216cf..000000000 --- a/app/views/partials/authentication/_login_tabs.html.haml +++ /dev/null @@ -1,26 +0,0 @@ -.mdl-tabs.mdl-js-tabs.mdl-js-ripple-effect - .mdl-tabs__tab-bar - %a.mdl-tabs__tab.login_tab.is-active{:href => "#legacy-panel"} Legacy - %a.mdl-tabs__tab.login_tab{:href => "#admin-panel"} Beta - #legacy-panel.mdl-tabs__panel.is-active - #admin-panel.mdl-tabs__panel - - = form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| - .mdl-textfield.mdl-js-textfield - = f.email_field :email, autofocus: true, class: 'mdl-textfield__input' - = f.label :email, class: 'mdl-textfield__label' - .mdl-textfield.mdl-js-textfield - = f.password_field :password, autocomplete: "off", class: 'mdl-textfield__input' - = f.label :password, class: 'mdl-textfield__label' - - if devise_mapping.rememberable? - = f.label :remember_me, class: 'mdl-switch mdl-js-switch mdl-js-ripple-effect' do - = f.check_box :remember_me, value: true, class: 'mdl-switch__input' - %span.mdl-switch__label - Remember me - %br/ - %br/ - - = hidden_field_tag(:legacy, 1, class: 'legacy_value') - - = f.submit "Log in", class: 'mdl-button mdl-js-button mdl-button--raised mdl-button--colored' - = render "authentication/shared/links" diff --git a/bower.json b/bower.json index ceb699d62..cf7a22b79 100644 --- a/bower.json +++ b/bower.json @@ -14,34 +14,9 @@ "dependencies": { "underscore": "~> 1.8.3", "momentjs": "~> 2.12.0", - "angular": "~> 1.2", - "angular-animate": "~> 1.2", - "angular-resource": "~> 1.2", - "angular-cookies": "~> 1.2", - "angular-ui-router": "~> 0.2", - "angular-bootstrap": "~> 0.12", - "angular-flash": "~> 0.1.14", - "angular-bootstrap-datetimepicker": "~> 0.3.8", - "angular-redactor": "~> 1.1.6", - "ng-file-upload": "~> 3.2.4", - "ng-table": "~> 0.5.4", "bootstrap-sass-official": "~> 3.3.7", - "ng-tags-input": "~> 2.3.0", - "angular-sanitize": "~> 1.5.0", - "bootstrap-switch": "~> 3.3.2", - "angular-bootstrap-toggle-switch": "~> 0.5.5", - "angular-validation-match": "< 1.4", - "jqueryui-timepicker-addon": "~> 1.6", "clipboard": "~> 1.5.16" }, - "devDependencies": { - "angular-mocks": "~> 1.2", - "sinonjs": "~> 1.12.2", - "sinon-ng": "~> 0.1.2", - "angular-debaser": "~> 0.3.2" - }, - "resolutions": { - "angular": "1.2.32" - } + "devDependencies": {} } diff --git a/config/application.rb b/config/application.rb index 2587cfa20..b23d0f6b2 100644 --- a/config/application.rb +++ b/config/application.rb @@ -7,15 +7,12 @@ module Cortex class Application < Rails::Application - config.angular_templates.module_name = 'cortex.templates' config.i18n.enforce_available_locales = true - config.eager_load_paths += %W(#{config.root}/lib #{config.root}/lib/helpers #{config.root}/lib/breadcrumbs #{config.root}/app/models/media_types #{config.root}/app/models/post_types #{config.root}/app/models/observers) + config.eager_load_paths += %W(#{config.root}/lib #{config.root}/lib/helpers #{config.root}/lib/breadcrumbs) config.active_record.default_timezone = :utc - config.active_record.observers = :media_observer, :post_observer, :tenant_observer, :user_observer, :youtube_observer config.active_job.queue_adapter = :sidekiq - config.assets.image_optim = false config.assets.paths << Rails.root.join('vendor', 'assets', 'bower_components') ActsAsTaggableOn.remove_unused_tags = true @@ -37,8 +34,5 @@ class Application < Rails::Application config.generators do |generator| generator.orm :active_record, primary_key_type: :uuid end - - # Needed until there is a better fix for Paperclip. https://github.com/thoughtbot/paperclip/issues/1924#issuecomment-123927367 - Paperclip.options[:content_type_mappings] = {:csv => 'text/plain'} end end diff --git a/config/config.yml b/config/config.yml index 8872e859f..c7edb9675 100644 --- a/config/config.yml +++ b/config/config.yml @@ -8,10 +8,6 @@ development: &defaults cors: allowed_origins: <%= ENV['CORS_ALLOWED_ORIGINS'] %> allowed_origins_regex: <%= ENV['CORS_ALLOWED_ORIGINS_REGEX'] %> - media: - max_size_mb: <%= ENV['MEDIA_MAX_SIZE_MB'] || 100 %> - onet: - version: <%= ENV['ONET_VERSION'] || '18.1' %> development: <<: *defaults diff --git a/config/environments/development.rb b/config/environments/development.rb index 43055cb2b..22ddf607b 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -33,33 +33,6 @@ config.cache_store = :redis_store, ENV['CACHE_URL'], { :namespace => ENV['REDIS_NAMESPACE'] || 'cortex_dev' } end - if ENV['S3_BUCKET_NAME'].to_s != '' - config.paperclip_defaults = { - :storage => :s3, - :s3_credentials => { - :access_key_id => ENV['AWS_ACCESS_KEY_ID'], - :secret_access_key => ENV['AWS_SECRET_ACCESS_KEY'] - }, - :s3_region => ENV['S3_REGION'], - :bucket => ENV['S3_BUCKET_NAME'], - :url => ':s3_alias_url', - :path => '/:class/:attachment/:id_partition/:style/:filename', - :s3_host_alias => ENV['S3_HOST_ALIAS'], - :s3_protocol => ENV['S3_PROTOCOL'] - } - else - Paperclip.options[:command_path] = '/usr/local/bin/' - config.paperclip_defaults = { - storage: :fog, - fog_host: ENV['FOG_HOST'], - fog_directory: '', - fog_credentials: { - provider: 'Local', - local_root: "#{Rails.root}/public" - } - } - end - Sidekiq.configure_server do |config| config.redis = { :namespace => ENV['REDIS_NAMESPACE'] || 'cortex_dev' } unless ENV['DEPLOYED'] end @@ -68,11 +41,6 @@ config.redis = { :namespace => ENV['REDIS_NAMESPACE'] || 'cortex_dev' } unless ENV['DEPLOYED'] end - Yt.configure do |config| - config.log_level = :debug - config.api_key = ENV['YOUTUBE_API_KEY'] - end - config.action_mailer.default_url_options = {:host => ENV['HOST']} config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { diff --git a/config/environments/production.rb b/config/environments/production.rb index 2a3dea0f5..ee9fc3306 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -64,26 +64,6 @@ # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false - Paperclip.options[:command_path] = '/usr/local/bin/' - - config.paperclip_defaults = { - :storage => :s3, - :s3_credentials => { - :access_key_id => ENV['AWS_ACCESS_KEY_ID'], - :secret_access_key => ENV['AWS_SECRET_ACCESS_KEY'] - }, - :s3_region => ENV['S3_REGION'], - :bucket => ENV['S3_BUCKET_NAME'], - :url => ':s3_alias_url', - :path => '/:class/:attachment/:id_partition/:style/:filename', - :s3_host_alias => ENV['S3_HOST_ALIAS'], - :s3_protocol => ENV['S3_PROTOCOL'] - } - - Yt.configure do |config| - config.api_key = ENV['YOUTUBE_API_KEY'] - end - config.action_mailer.raise_delivery_errors = true config.action_mailer.default_url_options = {:host => ENV['HOST']} config.action_mailer.delivery_method = :smtp diff --git a/config/environments/staging.rb b/config/environments/staging.rb index 5cf5fd658..3fadd4631 100644 --- a/config/environments/staging.rb +++ b/config/environments/staging.rb @@ -75,27 +75,6 @@ # Use default logging formatter so that PID and timestamp are not suppressed. config.log_formatter = ::Logger::Formatter.new - Paperclip.options[:command_path] = '/usr/local/bin/' - - config.paperclip_defaults = { - :storage => :s3, - :s3_credentials => { - :access_key_id => ENV['AWS_ACCESS_KEY_ID'], - :secret_access_key => ENV['AWS_SECRET_ACCESS_KEY'] - }, - :s3_region => ENV['S3_REGION'], - :bucket => ENV['S3_BUCKET_NAME'], - :url => ':s3_alias_url', - :path => '/:class/:attachment/:id_partition/:style/:filename', - :s3_host_alias => ENV['S3_HOST_ALIAS'], - :s3_protocol => ENV['S3_PROTOCOL'] - } - - Yt.configure do |config| - config.log_level = :debug - config.api_key = ENV['YOUTUBE_API_KEY'] - end - config.action_mailer.raise_delivery_errors = true config.action_mailer.default_url_options = {:host => ENV['HOST']} config.action_mailer.delivery_method = :smtp diff --git a/config/environments/test.rb b/config/environments/test.rb index 70d8f2138..ea13af0e1 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -37,8 +37,6 @@ config.cache_store = :redis_store, ENV['CACHE_URL'], { :namespace => 'cortex_test' } - Fog.mock! - Sidekiq.configure_server do |config| config.redis = { :namespace => 'cortex_test' } end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 9764d950f..7f2e6fe57 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -12,9 +12,6 @@ Rails.application.config.assets.precompile += %w( authentication.scss ) Rails.application.config.assets.precompile += %w( authentication.js ) -Rails.application.config.assets.precompile += %w( legacy_application.scss ) -Rails.application.config.assets.precompile += %w( legacy_application.js ) - Rails.application.config.assets.precompile += %w( ckeditor/* ) # Add client/assets/ folders to asset pipeline's search path. # If you do not want to move existing images and fonts from your Rails app diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb index d3d7aabd9..14152e817 100644 --- a/config/initializers/doorkeeper.rb +++ b/config/initializers/doorkeeper.rb @@ -36,11 +36,9 @@ # For more information go to https://github.com/applicake/doorkeeper/wiki/Using-Scopes default_scopes :public - optional_scopes 'view:users', 'modify:users', 'view:tenants', 'modify:tenants', 'view:posts', - 'modify:posts', 'view:media', 'modify:media', 'view:applications', 'modify:applications', - 'view:bulk_jobs', 'modify:bulk_jobs', 'view:documents', 'modify:documents', - 'view:snippets', 'modify:snippets', 'view:webpages', 'modify:webpages', 'view:content_types', - 'modify:content_types', 'view:content_items', 'modify:content_items' + optional_scopes 'view:users', 'modify:users', 'view:tenants', 'modify:tenants', 'view:applications', + 'modify:applications', 'view:content_types', 'modify:content_types', 'view:content_items', + 'modify:content_items' # Change the way client credentials are retrieved from the request object. # By default it retrieves first from the `HTTP_AUTHORIZATION` header, then diff --git a/config/initializers/load_config.rb b/config/initializers/load_config.rb index 1b42cc0f8..495ed2804 100644 --- a/config/initializers/load_config.rb +++ b/config/initializers/load_config.rb @@ -1,19 +1,6 @@ module Cortex def self.config - @config ||= load_config - end - - private - - def self.load_config - c = Hashr.new(Rails.application.config_for(:config)) - c.media.allowed_media_types = Hashr.new(self.load_yaml("#{Rails.root}/config/media_types.yml")).allowed - c - end - - def self.load_yaml(file) - # interpolate file with ERB to allow templating (<%= ENV['...'] %>) - YAML.load(ERB.new(File.new(file).read).result) + @config ||= Hashr.new(Rails.application.config_for(:config)) end end diff --git a/config/initializers/paperclip.rb b/config/initializers/paperclip.rb deleted file mode 100644 index ae0bd7c7d..000000000 --- a/config/initializers/paperclip.rb +++ /dev/null @@ -1,13 +0,0 @@ -module Paperclip - class HashieMashUploadedFileAdapter < AbstractAdapter - def initialize(target) - @tempfile, @content_type, @size = target.tempfile, target.type, target.tempfile.size - self.original_filename = target.filename - end - - end -end - -Paperclip.io_adapters.register Paperclip::HashieMashUploadedFileAdapter do |target| - target.is_a? Hashie::Mash -end diff --git a/config/initializers/paperclip_optimizer.rb b/config/initializers/paperclip_optimizer.rb deleted file mode 100644 index 92b1f41f6..000000000 --- a/config/initializers/paperclip_optimizer.rb +++ /dev/null @@ -1,26 +0,0 @@ -Paperclip::PaperclipOptimizer.default_options = { - allow_lossy: true, - skip_missing_workers: false, - verbose: true, - jpegoptim: { - allow_lossy: true, - strip: :all, - max_quality: 90 - }, - advpng: false, - gifsicle: { - interlace: true - }, - jhead: false, - jpegrecompress: false, - jpegtran: false, - optipng: false, - pngcrush: false, - pngout: false, - pngquant: { - allow_lossy: true, - quality: 33..50, - speed: 3 - }, - svgo: false -} diff --git a/config/locales/en.yml b/config/locales/en.yml index d2bc59113..00a339557 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -6,7 +6,3 @@ en: modify:tenants: Make changes to, create and delete, tenants you control view:users: View users you control modify:users: Make changes to, create and delete, users you control - view:posts: View posts you control - modify:posts: Make changes to, create and delete, posts you control - view:media: View media you control - modify:media: Make changes to, create and delete, media you control diff --git a/config/media_types.yml b/config/media_types.yml deleted file mode 100644 index 28f16af3a..000000000 --- a/config/media_types.yml +++ /dev/null @@ -1,59 +0,0 @@ -allowed: - - type: image/jpeg - thumb: True - taxon_type: IMG - - type: image/jpg - thumb: True - taxon_type: IMG - - type: image/pjpeg - thumb: True - taxon_type: IMG - - type: image/png - thumb: True - taxon_type: IMG - - type: image/gif - thumb: True - taxon_type: IMG - - type: image/bmp - thumb: True - taxon_type: IMG - - type: image/x-png - thumb: True - taxon_type: IMG - - type: application/pdf - thumb: False - taxon_type: DOC - - type: application/vnd.ms-excel - taxon_type: DOC - - type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet - taxon_type: DOC - - type: application/msword - taxon_type: DOC - - type: application/vnd.openxmlformats-officedocument.wordprocessingml.document - taxon_type: DOC - - type: text/plain - taxon_type: DOC - - type: application/zip - taxon_type: DOC - - type: video/avi - taxon_type: VID - - type: video/msvideo - taxon_type: VID - - type: video/x-msvideo - taxon_type: VID - - type: video/quicktime - taxon_type: VID - - type: video/mp4 - taxon_type: VID - - type: audio/mpeg - taxon_type: AUD - - type: audio/mp3 - taxon_type: AUD - - type: audio/x-mp3 - taxon_type: AUD - - type: audio/mpeg3 - taxon_type: AUD - - type: audio/x-mpeg3 - taxon_type: AUD - - type: audio/mpg - taxon_type: AUD diff --git a/config/routes.rb b/config/routes.rb index a37ae11cc..c66961ff7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,10 +1,8 @@ require 'sidekiq/web' Cortex::Application.routes.draw do - get 'hello_world', to: 'hello_world#index' mount JasmineRails::Engine => '/specs' if defined?(JasmineRails) root 'dashboards#index' - get 'legacy', to: 'legacy#index', as: :legacy_root scope '/admin' do resources :dashboards diff --git a/custom_content_readme.md b/custom_content_readme.md deleted file mode 100644 index 02885ad53..000000000 --- a/custom_content_readme.md +++ /dev/null @@ -1,150 +0,0 @@ -# Custom Content ReadMe - -## Table of Contents -- [Custom Content](#custom-content) - - [Purpose of Custom Content](#custom-content-purpose) - - [Vocabulary](#vocabulary) - - [Creating a New Content Type](#creating-a-new-content-type) - - [Creating a New Content Item](#creating-a-new-content-item) - - [Creating a New Field Type](#creating-a-new-field-type) - - [Creating a New Field](#creating-a-new-field) - - [Metadata](#metadata) - - [Text Field Type Metadata](#text-field-type-metadata) - - [Tree Field Type Metadata](#tree-field-type-metadata) - -### Purpose of Custom Content -Custom content types enable administrators and developers to compose content structures out of predetermined FieldTypes and with appropriate validations. - -### Vocabulary -
ContentType
A collection of Fields which represents a category of content that you want on your site
- -
Field
The association between a ContentType and a FieldType. It tells the ContentType which FieldType to use, the validations you want to run on the content when saving this Field, and any relevant metadata for the field.
- -
FieldType
Describes the characteristics of some piece of data that can be used to compose a ContentType. For example, if a ContentType needs a string of text, that would be a TextFieldType, a pdf would be a DocumentFileFieldType, and so on.
- -
ContentItem
An instance of a ContentType, it is a piece of content that gets saved to the database (i.e. a blog post). It consists of multiple FieldItems. ContentItem:FieldItem::ContentType:Field
- -
FieldItem
Each FieldItem represents a component of the ContentItem to which it belongs. So if the ContentItem is a blog post, there would be a FieldItem for the title, another for the body, another for an associated image, etc.
- - -### Creating a New Content Type -Say you want to create a ContentType called AwesomeBlogPost that has 4 fields: a Title (TextFieldType), a Body (TextFieldType), a Video (YoutubeFieldType), and an Image (ImageFileFieldType). - -Each FieldType has a number of validations that can potentially be run. You choose which validations to use when creating a Field using that FieldType. The Field will store the name you specify, the validations you choose to run, and the position of that Field relative to other Fields in the same ContentType. - -So, in AwesomeBlogPost you would specify that the Field named "Title" is a TextFieldType which comes first, its presence is required, and it should be a maximum of 50 characters; the Field named "Body" is a TextFieldType which comes second and should have a maximum of 1000 characters; the Field named "Video" is a YoutubeFieldType which comes third; and the Field named "Image" is an ImageFileFieldType which comes last and must be a jpg under 1MB. - -``` -ct = ContentType.new(name: "AwesomeBlogPost", description: "The kind of blog post that goes on my Awesome Site", creator_id: 1) - -ct.fields.new(name: "Title", field_type: "text_field_type", validations: { presence: true, length: { maximum: 50 } }, metadata: { placeholder: "This is the title" }) - -ct.fields.new(name: "Body", field_type: "text_field_type", validations: { length: {maximum: 1000 } }) - -ct.fields.new(name: "Video", field_type: "youtube_field_type" }) - -ct.fields.new(name: "Image", field_type: "image_file_field_type", validations: content_type: { content_type: "image/jpeg" }, size: { less_than: 1.megabyte }) - -ct.save -``` - -### Creating a New Content Item -A ContentItem is composed of FieldItems. A ContentItem represents the actual content that writers create. When a user creates a blog post of type AwesomeBlog, the content she inputs for each Field is stored in a corresponding FieldItem as 'data.' - -### Validations -Each FieldType defines the validations that can be run on a FieldItem's data. It should have a hash where the keys are the different types of validations that can be run, and the values are method names that will be called to determine if the requested Field validation is legitimate: -``` -VALIDATION_TYPES = { - length: :valid_length_validation?, - presence: :valid_presence_validation? -}.freeze -``` - -In order to define the validations that can be run, we use the [validators defined by Rails](https://github.com/rails/rails/tree/master/activemodel/lib/active_model/validations). You can also write [custom validators](http://guides.rubyonrails.org/active_record_validations.html#custom-validators) that would be used in the same way. This makes it easy to adhere to the same syntax used with ActiveRecord validations. When creating a Field, first it checks to ensure that the requested validations are consistent with the validations its FieldType provides, e.g. if a TextFieldType supports presence and length validations, you will not be able to add a numericality validation. Then the FieldType tests to see that any requested Field validations are allowed by instantiating the associated Validator and catching any ArgumentError or NoMethodError that gets thrown. If an error is thrown, then the syntax or content of the Field validation is incorrect somehow. If there is no error, then the Field validation is allowed. - -The Field validations themselves are run when creating a ContentItem and its associated FieldItems. A ContentItem is only considered valid if all of its FieldItems are valid. To determine validity, the FieldItem instantiates the FieldType, passes in its data, and tells the FieldType to run the validations hash specified by the Field. - -``` -class TextFieldType - def text_length - validator = LengthValidator.new(validations[:length].merge(attributes: [:text])) - validator.validate_each(self, :text, text) - end -end -``` - -### Creating a New Field Type -A FieldType must keep track of the sorts of validations it can run and be able to run all or a subset of those validations on the data passed to it (namely, the data in a field item). It must also be able to check that the validations given it are ones that Rails validators can actually run. The file name for a new FieldType should end in '_field_type.rb' - -### Creating a New Field -Some stuff about Fields, fields have metadata. - -### Metadata -Metadata encompasses information about fields that don't necessarily fit under any of the other attributes. Metadata is entered by the User creating the Content Type. - -#### Text Field Type -Typically for Text Field Types, the metadata will allow the User creating the field to specify display properties. The most common example of this is probably the use of Placeholder text. It will typically only be passing a String. - -``` -ct.fields.new( - name: "Title", - field_type: "text_field_type", - metadata: { placeholder: "This is the title" } -) -``` - -#### Tree Field Type -Tree Field Types depend fairly heavily on metadata, the metadata in Tree Field Types enumerates the structure for hierarchical data. As an Admin this metadata is used to specify the ```allowed_values``` a User can select, any selections made will then be validated against what was specified in ```allowed_values```. - -The Tree Field Type can be used in two fairly different ways: To represent simple lists / dropdown selections and also to represent hierarchical data structures. The expected values as well as simple exmaples are below: - -__Simple Lists__ - -A Simple list is any data that would go into a Dropdown in the view, these items do not need to necessarily relate to one another, but could have a general theme in common. Below we have a simple image to illustrate this: - -![Simple List Image](https://cloud.githubusercontent.com/assets/8419757/16248100/b023e68a-37d2-11e6-97df-187c2c07fb33.png) - -And the data representation of this list: - -```ruby -{ - :allowed_values => [ - { :name => "Art", :id => 1, :children => [] }, - { :name => "Computers", :id => 2, :children => [] }, - { :name => "Management", :id => 3, :children => [] }, - { :name => "Action", :id => 4, :children => [] } - ] -} -``` - -__Hierarchical Data__ - -A good example of actual Tree based data structures would be a family tree, below we have a family tree of House Stark from popular ficton to illustrate: - -![House Stark Image](https://cloud.githubusercontent.com/assets/8419757/16248101/b4135118-37d2-11e6-815c-e42262c47e63.png) - -And the data representation of this tree: - -```ruby -{ - :allowed_values => [ - { :name => "Rickon Stark", :id => 1, :children => [ - { :name => "Brandon Stark", :id => 2, :children => [] }, - { :name => "Eddard Stark", :id => 3, :children => [ - { :name => "Robb Stark", :id => 6, :children => [] }, - { :name => "Sansa Stark", :id => 7, :children => [] }, - { :name => "Arya Stark", :id => 8, :children => [] }, - { :name => "Bran Stark", :id => 9, :children => [] }, - { :name => "Rickon Stark II", :id => 10, :children => [] }, - ] - }, - { :name => "Lyanna Stark", :id => 4, :children => [ - { :name => "Jon Snow", :id => 11, :children => [] }, - ] - }, - { :name => "Benjen Stark", :id => 5, :children => [] } - ] - } - ] -} -``` diff --git a/db/migrate/20131209200118_create_assets.rb b/db/migrate/20131209200118_create_assets.rb deleted file mode 100644 index de9431f8e..000000000 --- a/db/migrate/20131209200118_create_assets.rb +++ /dev/null @@ -1,16 +0,0 @@ -class CreateAssets < ActiveRecord::Migration - def change - create_table :assets do |t| - t.string :name, index: true - t.belongs_to :user, index: true - t.attachment :attachment - t.string :dimensions - t.text :description - t.string :alt - t.boolean :active - t.datetime :deactive_at - - t.timestamps - end - end -end diff --git a/db/migrate/20131217175945_create_posts.rb b/db/migrate/20131217175945_create_posts.rb deleted file mode 100644 index 756b880ef..000000000 --- a/db/migrate/20131217175945_create_posts.rb +++ /dev/null @@ -1,17 +0,0 @@ -class CreatePosts < ActiveRecord::Migration - def change - create_table :posts do |t| - t.integer :user_id, null: false, index: true - t.string :title - t.string :type - t.datetime :published_at - t.datetime :expired_at - t.datetime :deleted_at - t.boolean :draft, null: false, default: true - t.integer :comment_count, null: false, default: 0 - t.text :body - - t.timestamps - end - end -end diff --git a/db/migrate/20131217182128_create_categories.rb b/db/migrate/20131217182128_create_categories.rb deleted file mode 100644 index 0fa52d0a8..000000000 --- a/db/migrate/20131217182128_create_categories.rb +++ /dev/null @@ -1,14 +0,0 @@ -class CreateCategories < ActiveRecord::Migration - def change - create_table :categories do |t| - t.string :name - t.integer :user_id, null: false, index: true - t.integer :parent_id, index: true - t.integer :lft, index: true - t.integer :rgt, index: true - t.integer :depth, index: true - - t.timestamps - end - end -end diff --git a/db/migrate/20131217191914_create_join_table_posts_assets.rb b/db/migrate/20131217191914_create_join_table_posts_assets.rb deleted file mode 100644 index 34c5c626d..000000000 --- a/db/migrate/20131217191914_create_join_table_posts_assets.rb +++ /dev/null @@ -1,8 +0,0 @@ -class CreateJoinTablePostsAssets < ActiveRecord::Migration - def change - create_join_table :posts, :media do |t| - # t.index [:asset_id, :post_id] - # t.index [:post_id, :asset_id] - end - end -end diff --git a/db/migrate/20131217192026_create_join_table_posts_categories.rb b/db/migrate/20131217192026_create_join_table_posts_categories.rb deleted file mode 100644 index f4315b0cf..000000000 --- a/db/migrate/20131217192026_create_join_table_posts_categories.rb +++ /dev/null @@ -1,8 +0,0 @@ -class CreateJoinTablePostsCategories < ActiveRecord::Migration - def change - create_join_table :posts, :categories do |t| - # t.index [:post_id, :category_id] - # t.index [:category_id, :post_id] - end - end -end diff --git a/db/migrate/20140103155949_add_digest_column_to_assets.rb b/db/migrate/20140103155949_add_digest_column_to_assets.rb deleted file mode 100644 index 34fcf03d2..000000000 --- a/db/migrate/20140103155949_add_digest_column_to_assets.rb +++ /dev/null @@ -1,10 +0,0 @@ -class AddDigestColumnToAssets < ActiveRecord::Migration - def up - execute 'DELETE FROM assets' - add_column :assets, :digest, :string, null: false - end - - def down - raise ActiveRecord::IrreversibleMigration, "Can't recover deleted assets" - end -end diff --git a/db/migrate/20140107165546_add_deleted_at_to_assets.rb b/db/migrate/20140107165546_add_deleted_at_to_assets.rb deleted file mode 100644 index 9a0e55f9c..000000000 --- a/db/migrate/20140107165546_add_deleted_at_to_assets.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddDeletedAtToAssets < ActiveRecord::Migration - def change - add_column :assets, :deleted_at, :datetime - end -end diff --git a/db/migrate/20140121175828_add_post_fields.rb b/db/migrate/20140121175828_add_post_fields.rb deleted file mode 100644 index 5848598b9..000000000 --- a/db/migrate/20140121175828_add_post_fields.rb +++ /dev/null @@ -1,33 +0,0 @@ -class AddPostFields < ActiveRecord::Migration - def change - Post.destroy_all - - add_column :posts, :short_description, :string - add_column :posts, :job_phase, :integer, null: false - add_column :posts, :display, :integer, null: false - add_column :posts, :featured_image_url, :string - add_column :posts, :notes, :text - add_column :posts, :copyright_owner, :string - add_column :posts, :seo_title, :string - add_column :posts, :seo_description, :string - add_column :posts, :seo_preview, :string - - remove_column :posts, :type - add_column :posts, :type, :integer, null: false - end - - def down - remove_column :posts, :short_description, :string - remove_column :posts, :job_phase, :integer - remove_column :posts, :display, :integer - remove_column :posts, :featured_image_url, :string - remove_column :posts, :notes, :text - remove_column :posts, :copyright_owner, :string - remove_column :posts, :seo_title, :string - remove_column :posts, :seo_description, :string - remove_column :posts, :seo_preview, :string - - remove_column :posts, :type - add_column :posts, :type, :string - end -end diff --git a/db/migrate/20140130220423_add_author_to_posts.rb b/db/migrate/20140130220423_add_author_to_posts.rb deleted file mode 100644 index 294aa972a..000000000 --- a/db/migrate/20140130220423_add_author_to_posts.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddAuthorToPosts < ActiveRecord::Migration - def change - add_column :posts, :author, :string - end -end diff --git a/db/migrate/20140204165827_rename_assets_media.rb b/db/migrate/20140204165827_rename_assets_media.rb deleted file mode 100644 index 2af92823f..000000000 --- a/db/migrate/20140204165827_rename_assets_media.rb +++ /dev/null @@ -1,9 +0,0 @@ -class RenameAssetsMedia < ActiveRecord::Migration - def up - rename_table :assets, :media - end - - def down - rename_table :media, :assets - end -end diff --git a/db/migrate/20140401042719_change_medium_column.rb b/db/migrate/20140401042719_change_medium_column.rb deleted file mode 100644 index 4d8fde598..000000000 --- a/db/migrate/20140401042719_change_medium_column.rb +++ /dev/null @@ -1,5 +0,0 @@ -class ChangeMediumColumn < ActiveRecord::Migration - def change - rename_column :media_posts, :medium_id, :media_id - end -end diff --git a/db/migrate/20140513190327_add_slug_to_posts.rb b/db/migrate/20140513190327_add_slug_to_posts.rb deleted file mode 100644 index 2f490165f..000000000 --- a/db/migrate/20140513190327_add_slug_to_posts.rb +++ /dev/null @@ -1,13 +0,0 @@ -class AddSlugToPosts < ActiveRecord::Migration - def up - add_column :posts, :slug, :string - execute "UPDATE posts SET slug=lower(concat(replace(title, ' ', '-'), '-', id))" - change_column :posts, :slug, :string, :null => false - add_index :posts, :slug, :unique => true - end - - def down - remove_index :posts, :slug - remove_column :posts, :slug - end -end diff --git a/db/migrate/20140514042944_change_featured_image_url_to_featured_media.rb b/db/migrate/20140514042944_change_featured_image_url_to_featured_media.rb deleted file mode 100644 index f64a9cc0a..000000000 --- a/db/migrate/20140514042944_change_featured_image_url_to_featured_media.rb +++ /dev/null @@ -1,6 +0,0 @@ -class ChangeFeaturedImageUrlToFeaturedMedia < ActiveRecord::Migration - def change - remove_column :posts, :featured_image_url, :string - add_column :posts, :featured_media_id, :integer, index: true - end -end diff --git a/db/migrate/20140521162855_create_onet_occupations.rb b/db/migrate/20140521162855_create_onet_occupations.rb deleted file mode 100644 index da829d4f5..000000000 --- a/db/migrate/20140521162855_create_onet_occupations.rb +++ /dev/null @@ -1,11 +0,0 @@ -class CreateOnetOccupations < ActiveRecord::Migration - def change - create_table :onet_occupations do |t| - t.string :soc - t.string :title - t.text :description - - t.timestamps - end - end -end diff --git a/db/migrate/20140527164025_add_industry_association_to_posts.rb b/db/migrate/20140527164025_add_industry_association_to_posts.rb deleted file mode 100644 index 7aaa37421..000000000 --- a/db/migrate/20140527164025_add_industry_association_to_posts.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddIndustryAssociationToPosts < ActiveRecord::Migration - def change - add_column :posts, :industry_id, :integer, index: true - end -end diff --git a/db/migrate/20140611152327_add_primary_industry_and_category_to_post.rb b/db/migrate/20140611152327_add_primary_industry_and_category_to_post.rb deleted file mode 100644 index 15ac1c605..000000000 --- a/db/migrate/20140611152327_add_primary_industry_and_category_to_post.rb +++ /dev/null @@ -1,23 +0,0 @@ -class AddPrimaryIndustryAndCategoryToPost < ActiveRecord::Migration - def up - rename_column :posts, :industry_id, :primary_industry_id - add_column :posts, :primary_category_id, :integer, index: true - execute 'UPDATE posts p SET primary_category_id=cp.category_id ' + - 'FROM categories_posts cp WHERE p.id=cp.post_id' - change_column :posts, :primary_category_id, :integer, index: true - - create_join_table :posts, :onet_occupations do |t| - # t.index [:post_id, :onet_occupation_id] - # t.index [:onet_occupation_id, :post_id] - end - - execute 'INSERT INTO onet_occupations_posts (post_id, onet_occupation_id) ' + - 'SELECT id, primary_industry_id FROM posts WHERE primary_industry_id IS NOT NULL' - end - - def down - rename_column :posts, :primary_industry_id, :industry_id - remove_column :posts, :primary_category_id - drop_join_table :posts, :onet_occupations - end -end diff --git a/db/migrate/20140616153725_add_meta_to_media.rb b/db/migrate/20140616153725_add_meta_to_media.rb deleted file mode 100644 index 8ac46def4..000000000 --- a/db/migrate/20140616153725_add_meta_to_media.rb +++ /dev/null @@ -1,14 +0,0 @@ -class AddMetaToMedia < ActiveRecord::Migration - def up - execute 'CREATE EXTENSION IF NOT EXISTS hstore' - add_column :media, :meta, :hstore - add_column :media, :type, :string, default: 'Media', null: false - change_column :media, :digest, :string, null: true - end - - def down - execute 'DROP EXTENSION IF EXISTS hstore' - remove_column :media, :meta - remove_column :media, :type - end -end diff --git a/db/migrate/20140617200632_add_tile_media_to_post.rb b/db/migrate/20140617200632_add_tile_media_to_post.rb deleted file mode 100644 index 8e70a31bd..000000000 --- a/db/migrate/20140617200632_add_tile_media_to_post.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddTileMediaToPost < ActiveRecord::Migration - def change - add_column :posts, :tile_media_id, :integer, index: true - end -end diff --git a/db/migrate/20140707205234_add_meta_and_rename_type_for_posts.rb b/db/migrate/20140707205234_add_meta_and_rename_type_for_posts.rb deleted file mode 100644 index f82196748..000000000 --- a/db/migrate/20140707205234_add_meta_and_rename_type_for_posts.rb +++ /dev/null @@ -1,11 +0,0 @@ -class AddMetaAndRenameTypeForPosts < ActiveRecord::Migration - def up - add_column :posts, :meta, :hstore - add_column :posts, :post_type, :string, default: 'Post', null: false - end - - def down - remove_column :posts, :post_type - remove_column :posts, :meta - end -end diff --git a/db/migrate/20140708174329_change_post_inheritence_column.rb b/db/migrate/20140708174329_change_post_inheritence_column.rb deleted file mode 100644 index 04a78acd0..000000000 --- a/db/migrate/20140708174329_change_post_inheritence_column.rb +++ /dev/null @@ -1,24 +0,0 @@ -class ChangePostInheritenceColumn < ActiveRecord::Migration - def up - # enum type: [:article, :video, :infographic, :promo] - execute "UPDATE posts SET post_type='ArticlePost' WHERE type=0" - execute "UPDATE posts SET post_type='VideoPost' WHERE type=1" - execute "UPDATE posts SET post_type='InfographicPost' WHERE type=2" - execute "UPDATE posts SET post_type='PromoPost' WHERE type=3" - - remove_column :posts, :type - rename_column :posts, :post_type, :type - add_index :posts, :type - end - - def down - remove_index :posts, :type - rename_column :posts, :type, :post_type - add_column :posts, :type, :integer, default: 0, null: false - - execute "UPDATE posts SET type=0 WHERE post_type='ArticlePost'" - execute "UPDATE posts SET type=1 WHERE post_type='VideoPost'" - execute "UPDATE posts SET type=2 WHERE post_type='InfographicPost'" - execute "UPDATE posts SET type=3 WHERE post_type='PromoPost'" - end -end diff --git a/db/migrate/20140709174247_create_author.rb b/db/migrate/20140709174247_create_author.rb deleted file mode 100644 index 7ca5d22c0..000000000 --- a/db/migrate/20140709174247_create_author.rb +++ /dev/null @@ -1,24 +0,0 @@ -class CreateAuthor < ActiveRecord::Migration - def up - - rename_column :posts, :author, :custom_author - - create_table :authors do |t| - t.string :firstname - t.string :lastname - t.string :email - t.hstore :sites # personal, facebook, twitter, G+, etc. - t.string :title - t.text :bio - t.belongs_to :user - end - add_index :authors, :user_id - - execute 'INSERT INTO authors (firstname, lastname, email, user_id) SELECT firstname, lastname, email, id FROM users' - end - - def down - drop_table :authors - rename_column :posts, :custom_author, :author - end -end diff --git a/db/migrate/20140718145229_add_author_id_to_posts.rb b/db/migrate/20140718145229_add_author_id_to_posts.rb deleted file mode 100644 index e3ed2d8fa..000000000 --- a/db/migrate/20140718145229_add_author_id_to_posts.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddAuthorIdToPosts < ActiveRecord::Migration - def change - add_column :posts, :author_id, :integer - add_index :posts, :author_id - end -end diff --git a/db/migrate/20140724182815_allow_null_post_slug.rb b/db/migrate/20140724182815_allow_null_post_slug.rb deleted file mode 100644 index b30f6fd36..000000000 --- a/db/migrate/20140724182815_allow_null_post_slug.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AllowNullPostSlug < ActiveRecord::Migration - def change - change_column :posts, :slug, :string - end -end diff --git a/db/migrate/20150406045848_create_bulk_jobs.rb b/db/migrate/20150406045848_create_bulk_jobs.rb deleted file mode 100644 index c00a94fbc..000000000 --- a/db/migrate/20150406045848_create_bulk_jobs.rb +++ /dev/null @@ -1,19 +0,0 @@ -class CreateBulkJobs < ActiveRecord::Migration - def change - create_table :bulk_jobs, :id => false do |t| - t.uuid :id, primary_key: true, default: 'uuid_generate_v4()' - t.string :content_type, :null => false - t.belongs_to :user - t.string :status - t.text :log - t.attachment :metadata - t.attachment :assets - - t.timestamps null: false - end - - add_index :bulk_jobs, :id - add_index :bulk_jobs, :content_type - add_index :bulk_jobs, :user_id - end -end diff --git a/db/migrate/20150512195610_create_documents.rb b/db/migrate/20150512195610_create_documents.rb deleted file mode 100644 index 1bfba120a..000000000 --- a/db/migrate/20150512195610_create_documents.rb +++ /dev/null @@ -1,12 +0,0 @@ -class CreateDocuments < ActiveRecord::Migration - def change - create_table :documents do |t| - t.integer :user_id, null: false, index: true - t.string :name - t.text :body - t.datetime :deleted_at - - t.timestamps null: false - end - end -end diff --git a/db/migrate/20150512195637_create_webpages.rb b/db/migrate/20150512195637_create_webpages.rb deleted file mode 100644 index 7aa86af18..000000000 --- a/db/migrate/20150512195637_create_webpages.rb +++ /dev/null @@ -1,13 +0,0 @@ -class CreateWebpages < ActiveRecord::Migration - def change - create_table :webpages do |t| - t.integer :user_id, null: false, index: true - t.string :name - t.string :url - t.attachment :thumbnail - t.datetime :deleted_at - - t.timestamps null: false - end - end -end diff --git a/db/migrate/20150512200711_create_join_table_snippets.rb b/db/migrate/20150512200711_create_join_table_snippets.rb deleted file mode 100644 index cb7d06eba..000000000 --- a/db/migrate/20150512200711_create_join_table_snippets.rb +++ /dev/null @@ -1,14 +0,0 @@ -class CreateJoinTableSnippets < ActiveRecord::Migration - def change - create_join_table :webpages, :documents, table_name: 'snippets' do |t| - t.column :id, :primary_key - t.integer :user_id, null: false, index: true - t.datetime :deleted_at - - t.timestamps null: false - - # t.index [:webpage_id, :document_id] - # t.index [:document_id, :webpage_id] - end - end -end diff --git a/db/migrate/20150713025436_add_is_wysiwyg_to_posts.rb b/db/migrate/20150713025436_add_is_wysiwyg_to_posts.rb deleted file mode 100644 index 5abf345f2..000000000 --- a/db/migrate/20150713025436_add_is_wysiwyg_to_posts.rb +++ /dev/null @@ -1,7 +0,0 @@ -class AddIsWysiwygToPosts < ActiveRecord::Migration - def change - change_table :posts do |t| - t.boolean :is_wysiwyg, default: true - end - end -end diff --git a/db/migrate/20151106163438_add_seo_fields_to_webpage.rb b/db/migrate/20151106163438_add_seo_fields_to_webpage.rb deleted file mode 100644 index 7e2dfb092..000000000 --- a/db/migrate/20151106163438_add_seo_fields_to_webpage.rb +++ /dev/null @@ -1,12 +0,0 @@ -class AddSeoFieldsToWebpage < ActiveRecord::Migration - def change - add_column :webpages, :seo_title, :string - add_column :webpages, :seo_description, :text - add_column :webpages, :noindex, :bool, default: false - add_column :webpages, :nofollow, :bool, default: false - add_column :webpages, :nosnippet, :bool, default: false - add_column :webpages, :noodp, :bool, default: false - add_column :webpages, :noarchive, :bool, default: false - add_column :webpages, :noimageindex, :bool, default: false - end -end diff --git a/db/migrate/20160415032630_add_seo_keywords_to_webpage.rb b/db/migrate/20160415032630_add_seo_keywords_to_webpage.rb deleted file mode 100644 index c6b13a013..000000000 --- a/db/migrate/20160415032630_add_seo_keywords_to_webpage.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddSeoKeywordsToWebpage < ActiveRecord::Migration - def change - add_column :webpages, :seo_keywords, :text - end -end diff --git a/db/migrate/20160505224605_rename_seo_keywords_to_seo_keywords_old.rb b/db/migrate/20160505224605_rename_seo_keywords_to_seo_keywords_old.rb deleted file mode 100644 index 8f4d49cb4..000000000 --- a/db/migrate/20160505224605_rename_seo_keywords_to_seo_keywords_old.rb +++ /dev/null @@ -1,10 +0,0 @@ -# The reason this is renaming seo_keywords to seo_keywords_old is that -# acts_as_taggable has now reserved the method #seo_keywords to mean a -# list of tags. Since we still need to extract the data from the old -# seo_keywords I renamed it, allowing us to target it in the next migration. - -class RenameSeoKeywordsToSeoKeywordsOld < ActiveRecord::Migration - def change - rename_column :webpages, :seo_keywords, :seo_keywords_old - end -end diff --git a/db/migrate/20160505224658_move_webpage_seo_keyword_data_to_seo_keyword_list.rb b/db/migrate/20160505224658_move_webpage_seo_keyword_data_to_seo_keyword_list.rb deleted file mode 100644 index dfb193b3f..000000000 --- a/db/migrate/20160505224658_move_webpage_seo_keyword_data_to_seo_keyword_list.rb +++ /dev/null @@ -1,16 +0,0 @@ -# Pretty straight forward - is a block that moves all the string data from -# seo_keywords_old (recently renamed) to the acts_as_taggable list using the -# #add method. This is done to preserve existing data before this refactor was -# made. - -class MoveWebpageSeoKeywordDataToSeoKeywordList < ActiveRecord::Migration - def change - Webpage.all.each do |w| - unless w.seo_keywords_old.nil? - keywords = w.seo_keywords_old.split(" ") - keywords.each { |k| w.seo_keyword_list.add(k) } - w.save - end - end - end -end diff --git a/db/migrate/20160505224930_remove_seo_keyword_old_from_webpages.rb b/db/migrate/20160505224930_remove_seo_keyword_old_from_webpages.rb deleted file mode 100644 index ecacd53d6..000000000 --- a/db/migrate/20160505224930_remove_seo_keyword_old_from_webpages.rb +++ /dev/null @@ -1,8 +0,0 @@ -# Deletes the seo_keywords_old column since we no longer need it after extracting -# the data into seo_keyword_list. - -class RemoveSeoKeywordOldFromWebpages < ActiveRecord::Migration - def change - remove_column :webpages, :seo_keywords_old - end -end diff --git a/db/migrate/20160615194511_add_seo_fields_to_post.rb b/db/migrate/20160615194511_add_seo_fields_to_post.rb deleted file mode 100644 index 2270045f7..000000000 --- a/db/migrate/20160615194511_add_seo_fields_to_post.rb +++ /dev/null @@ -1,10 +0,0 @@ -class AddSeoFieldsToPost < ActiveRecord::Migration - def change - add_column :posts, :noindex, :bool, default: false - add_column :posts, :nofollow, :bool, default: false - add_column :posts, :nosnippet, :bool, default: false - add_column :posts, :noodp, :bool, default: false - add_column :posts, :noarchive, :bool, default: false - add_column :posts, :noimageindex, :bool, default: false - end -end diff --git a/db/migrate/20160906210044_remove_uniqueness_from_post_slug_index.rb b/db/migrate/20160906210044_remove_uniqueness_from_post_slug_index.rb deleted file mode 100644 index 6b10779f5..000000000 --- a/db/migrate/20160906210044_remove_uniqueness_from_post_slug_index.rb +++ /dev/null @@ -1,6 +0,0 @@ -class RemoveUniquenessFromPostSlugIndex < ActiveRecord::Migration - def change - remove_index :posts, :slug - add_index :posts, :slug - end -end diff --git a/db/migrate/20161221220406_add_dynamic_yield_metadata_to_webpages.rb b/db/migrate/20161221220406_add_dynamic_yield_metadata_to_webpages.rb deleted file mode 100644 index d604f6a4f..000000000 --- a/db/migrate/20161221220406_add_dynamic_yield_metadata_to_webpages.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddDynamicYieldMetadataToWebpages < ActiveRecord::Migration[5.0] - def change - add_column :webpages, :dynamic_yield_sku, :string - add_column :webpages, :dynamic_yield_category, :string - end -end diff --git a/db/migrate/20161228215134_add_sticky_boolean_to_posts_legacy.rb b/db/migrate/20161228215134_add_sticky_boolean_to_posts_legacy.rb deleted file mode 100644 index bb3844ea8..000000000 --- a/db/migrate/20161228215134_add_sticky_boolean_to_posts_legacy.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddStickyBooleanToPostsLegacy < ActiveRecord::Migration[5.0] - def change - add_column :posts, :is_sticky, :boolean, default: false - end -end diff --git a/db/migrate/20170327182543_add_tables_widget_to_webpage.rb b/db/migrate/20170327182543_add_tables_widget_to_webpage.rb deleted file mode 100644 index 681e5c5e2..000000000 --- a/db/migrate/20170327182543_add_tables_widget_to_webpage.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddTablesWidgetToWebpage < ActiveRecord::Migration[5.0] - def change - add_column :webpages, :tables_widget, :jsonb - end -end diff --git a/db/migrate/20170519201648_add_charts_widget_to_webpage.rb b/db/migrate/20170519201648_add_charts_widget_to_webpage.rb deleted file mode 100644 index 5d88d8c10..000000000 --- a/db/migrate/20170519201648_add_charts_widget_to_webpage.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddChartsWidgetToWebpage < ActiveRecord::Migration[5.0] - def change - add_column :webpages, :charts_widget, :jsonb - end -end diff --git a/db/migrate/20170525015850_add_accordion_group_widget_to_webpage.rb b/db/migrate/20170525015850_add_accordion_group_widget_to_webpage.rb deleted file mode 100644 index 49b2166d7..000000000 --- a/db/migrate/20170525015850_add_accordion_group_widget_to_webpage.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddAccordionGroupWidgetToWebpage < ActiveRecord::Migration[5.0] - def change - add_column :webpages, :accordion_group_widget, :jsonb - end -end diff --git a/db/migrate/20170531215319_make_webpage_url_case_insensitive.rb b/db/migrate/20170531215319_make_webpage_url_case_insensitive.rb deleted file mode 100644 index 52cea0b14..000000000 --- a/db/migrate/20170531215319_make_webpage_url_case_insensitive.rb +++ /dev/null @@ -1,6 +0,0 @@ -class MakeWebpageUrlCaseInsensitive < ActiveRecord::Migration[5.0] - def change - enable_extension :citext - change_column :webpages, :url, :citext - end -end diff --git a/db/schema.rb b/db/schema.rb index a7efa7be7..1ce7ca329 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,13 +10,11 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170531215319) do +ActiveRecord::Schema.define(version: 20170417185915) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" - enable_extension "hstore" enable_extension "uuid-ossp" - enable_extension "citext" create_table "applications", force: :cascade do |t| t.string "name" @@ -27,58 +25,6 @@ t.index ["tenant_id"], name: "index_applications_on_tenant_id", using: :btree end - create_table "authors", force: :cascade do |t| - t.string "firstname" - t.string "lastname" - t.string "email" - t.hstore "sites" - t.string "title" - t.text "bio" - t.integer "user_id" - t.index ["user_id"], name: "index_authors_on_user_id", using: :btree - end - - create_table "bulk_jobs", id: :uuid, default: -> { "uuid_generate_v4()" }, force: :cascade do |t| - t.string "content_type", null: false - t.integer "user_id" - t.string "status" - t.text "log" - t.string "metadata_file_name" - t.string "metadata_content_type" - t.integer "metadata_file_size" - t.datetime "metadata_updated_at" - t.string "assets_file_name" - t.string "assets_content_type" - t.integer "assets_file_size" - t.datetime "assets_updated_at" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["content_type"], name: "index_bulk_jobs_on_content_type", using: :btree - t.index ["id"], name: "index_bulk_jobs_on_id", using: :btree - t.index ["user_id"], name: "index_bulk_jobs_on_user_id", using: :btree - end - - create_table "categories", force: :cascade do |t| - t.string "name" - t.integer "user_id", null: false - t.integer "parent_id" - t.integer "lft" - t.integer "rgt" - t.integer "depth" - t.datetime "created_at" - t.datetime "updated_at" - t.index ["depth"], name: "index_categories_on_depth", using: :btree - t.index ["lft"], name: "index_categories_on_lft", using: :btree - t.index ["parent_id"], name: "index_categories_on_parent_id", using: :btree - t.index ["rgt"], name: "index_categories_on_rgt", using: :btree - t.index ["user_id"], name: "index_categories_on_user_id", using: :btree - end - - create_table "categories_posts", id: false, force: :cascade do |t| - t.integer "post_id", null: false - t.integer "category_id", null: false - end - create_table "content_items", id: :uuid, default: -> { "uuid_generate_v4()" }, force: :cascade do |t| t.uuid "content_type_id" t.datetime "created_at", null: false @@ -134,16 +80,6 @@ t.index ["id"], name: "index_decorators_on_id", using: :btree end - create_table "documents", force: :cascade do |t| - t.integer "user_id", null: false - t.string "name" - t.text "body" - t.datetime "deleted_at" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["user_id"], name: "index_documents_on_user_id", using: :btree - end - create_table "field_items", id: :uuid, default: -> { "uuid_generate_v4()" }, force: :cascade do |t| t.uuid "field_id" t.uuid "content_item_id" @@ -213,33 +149,6 @@ t.index ["user_id"], name: "index_localizations_on_user_id", using: :btree end - create_table "media", force: :cascade do |t| - t.string "name" - t.integer "user_id" - t.string "attachment_file_name" - t.string "attachment_content_type" - t.integer "attachment_file_size" - t.datetime "attachment_updated_at" - t.string "dimensions" - t.text "description" - t.string "alt" - t.boolean "active" - t.datetime "deactive_at" - t.datetime "created_at" - t.datetime "updated_at" - t.string "digest" - t.datetime "deleted_at" - t.hstore "meta" - t.string "type", default: "Media", null: false - t.index ["name"], name: "index_media_on_name", using: :btree - t.index ["user_id"], name: "index_media_on_user_id", using: :btree - end - - create_table "media_posts", id: false, force: :cascade do |t| - t.integer "post_id", null: false - t.integer "media_id", null: false - end - create_table "oauth_access_grants", force: :cascade do |t| t.integer "resource_owner_id", null: false t.integer "application_id", null: false @@ -280,19 +189,6 @@ t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true, using: :btree end - create_table "onet_occupations", force: :cascade do |t| - t.string "soc" - t.string "title" - t.text "description" - t.datetime "created_at" - t.datetime "updated_at" - end - - create_table "onet_occupations_posts", id: false, force: :cascade do |t| - t.integer "post_id", null: false - t.integer "onet_occupation_id", null: false - end - create_table "permissions", force: :cascade do |t| t.string "name" t.string "resource_type" @@ -301,48 +197,6 @@ t.integer "resource_id" end - create_table "posts", force: :cascade do |t| - t.integer "user_id", null: false - t.string "title" - t.datetime "published_at" - t.datetime "expired_at" - t.datetime "deleted_at" - t.boolean "draft", default: true, null: false - t.integer "comment_count", default: 0, null: false - t.text "body" - t.datetime "created_at" - t.datetime "updated_at" - t.string "short_description" - t.integer "job_phase", null: false - t.integer "display", null: false - t.text "notes" - t.string "copyright_owner" - t.string "seo_title" - t.string "seo_description" - t.string "seo_preview" - t.string "custom_author" - t.string "slug", null: false - t.integer "featured_media_id" - t.integer "primary_industry_id" - t.integer "primary_category_id" - t.integer "tile_media_id" - t.hstore "meta" - t.string "type", default: "Post", null: false - t.integer "author_id" - t.boolean "is_wysiwyg", default: true - t.boolean "noindex", default: false - t.boolean "nofollow", default: false - t.boolean "nosnippet", default: false - t.boolean "noodp", default: false - t.boolean "noarchive", default: false - t.boolean "noimageindex", default: false - t.boolean "is_sticky", default: false - t.index ["author_id"], name: "index_posts_on_author_id", using: :btree - t.index ["slug"], name: "index_posts_on_slug", using: :btree - t.index ["type"], name: "index_posts_on_type", using: :btree - t.index ["user_id"], name: "index_posts_on_user_id", using: :btree - end - create_table "role_permissions", force: :cascade do |t| t.integer "role_id" t.integer "permission_id" @@ -360,16 +214,6 @@ t.index ["name"], name: "index_roles_on_name", using: :btree end - create_table "snippets", force: :cascade do |t| - t.integer "webpage_id", null: false - t.integer "document_id", null: false - t.integer "user_id", null: false - t.datetime "deleted_at" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["user_id"], name: "index_snippets_on_user_id", using: :btree - end - create_table "taggings", force: :cascade do |t| t.integer "tag_id" t.string "taggable_type" @@ -450,31 +294,4 @@ t.index ["user_id", "role_id"], name: "index_users_roles_on_user_id_and_role_id", using: :btree end - create_table "webpages", force: :cascade do |t| - t.integer "user_id", null: false - t.string "name" - t.citext "url" - t.string "thumbnail_file_name" - t.string "thumbnail_content_type" - t.integer "thumbnail_file_size" - t.datetime "thumbnail_updated_at" - t.datetime "deleted_at" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "seo_title" - t.text "seo_description" - t.boolean "noindex", default: false - t.boolean "nofollow", default: false - t.boolean "nosnippet", default: false - t.boolean "noodp", default: false - t.boolean "noarchive", default: false - t.boolean "noimageindex", default: false - t.string "dynamic_yield_sku" - t.string "dynamic_yield_category" - t.jsonb "tables_widget" - t.jsonb "charts_widget" - t.jsonb "accordion_group_widget" - t.index ["user_id"], name: "index_webpages_on_user_id", using: :btree - end - end diff --git a/db/seeds.rb b/db/seeds.rb index 623bf11e5..099e374ae 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1,24 +1,10 @@ # Create root tenant and user tenant_seed = SeedData.cortex_tenant user_seed = tenant_seed.creator -initial_post_seed = SeedData.initial_post - -initial_post = Post.find_by_slug(initial_post_seed.slug) || ArticlePost.new(title: initial_post_seed.title, - body: initial_post_seed.body, - short_description: initial_post_seed.short_description, - slug: initial_post_seed.slug, - draft: false, - published_at: Time.now, - job_phase: initial_post_seed.job_phase, - display: initial_post_seed.display, - copyright_owner: initial_post_seed.copyright_owner, - author: Author.first) existing_tenant = Tenant.find_by_name(tenant_seed.name) -if existing_tenant - initial_post.user = existing_tenant.owner -else +unless existing_tenant cortex_tenant = Tenant.new(name: tenant_seed.name) cortex_tenant.owner = User.new(email: user_seed.email, @@ -30,8 +16,4 @@ admin: true) cortex_tenant.save! - - initial_post.user = cortex_tenant.owner end - -initial_post.save! diff --git a/db/seeds.yml b/db/seeds.yml index 438a8847f..a4711950f 100644 --- a/db/seeds.yml +++ b/db/seeds.yml @@ -2,119 +2,11 @@ defaults: &defaults initial_post: title: 'Welcome to Cortex!' slug: 'initial-news-post' - job_phase: 'Discovery' - display: 'medium' - short_description: 'This is an initial test news ArticlePost for Cortex that you can delete' - copyright_owner: 'Cortex CMS' + description: 'This is an initial test news ArticlePost for Cortex that you can delete' body: 'Your initial superadministrator user credentials are:

Email: admin@cortexcms.org
Password: welcome1

Please change them in deployed environments.' cortex_tenant: name: 'cortex' creator: {email: 'admin@cortexcms.org', firstname: 'Cortex', lastname: 'Admin', password: 'welcome1'} - categories: - - name: Discovery - children: - - {name: Assessments} - - {name: Job Trends} - - {name: CareerBuilder Updates} - - {name: General} - - - name: Find the Job - children: - - {name: How to Search} - - {name: Networking} - - {name: The Right Job} - - {name: Who's Hiring} - - {name: Personal Branding} - - {name: General} - - - name: Get the Job - children: - - {name: Cover Letters} - - {name: Resumes} - - {name: Interviews} - - {name: Negotiation} - - {name: Following Up} - - {name: General} - - - name: On the Job - children: - - {name: Workplace} - - {name: Benefits} - - {name: Bosses} - - {name: Coworkers} - - {name: Promotions & Raises} - - {name: Work/Life Balance} - - {name: Salary} - - {name: General} - onet_industries: - - soc: '11-0000' - title: 'Management' - - - soc: '13-0000' - title: 'Business and Financial Operations' - - - soc: '15-0000' - title: 'Computer and Mathematical' - - - soc: '17-0000' - title: 'Architecture and Engineering' - - - soc: '19-0000' - title: 'Life, Physical, and Social Science' - - - soc: '21-0000' - title: 'Community and Social Service' - - - soc: '23-0000' - title: 'Legal' - - - soc: '25-0000' - title: 'Education, Training, and Library' - - - soc: '27-0000' - title: 'Arts, Design, Entertainment, Sports, and Media' - - - soc: '29-0000' - title: 'Healthcare Practitioners and Technical' - - - soc: '31-0000' - title: 'Healthcare Support' - - - soc: '33-0000' - title: 'Protective Service' - - - soc: '35-0000' - title: 'Food Preparation and Serving Related' - - - soc: '37-0000' - title: 'Building and Grounds Cleaning and Maintenance' - - - soc: '39-0000' - title: 'Personal Care and Service' - - - soc: '41-0000' - title: 'Sales and Related' - - - soc: '43-0000' - title: 'Office and Administrative Support' - - - soc: '45-0000' - title: 'Farming, Fishing, and Forestry' - - - soc: '47-0000' - title: 'Construction and Extraction' - - - soc: '49-0000' - title: 'Installation, Maintenance, and Repair' - - - soc: '51-0000' - title: 'Production' - - - soc: '53-0000' - title: 'Transportation and Material Moving' - - - soc: '55-0000' - title: 'Military Specific' test: <<: *defaults diff --git a/lib/tasks/cortex.rake b/lib/tasks/cortex.rake index 08d4b1c69..65eee612a 100644 --- a/lib/tasks/cortex.rake +++ b/lib/tasks/cortex.rake @@ -16,299 +16,11 @@ namespace :cortex do end end - desc 'Add categories from seeds.yml' - task :create_categories => :environment do - user = User.find_by_email(SeedData.cortex_tenant.creator.email) - SeedData.categories.each do |parent_category_seed| - parent = Category.find_by_name(parent_category_seed[:name]) - unless parent - puts "Creating #{parent_category_seed[:name]}" - parent = Category.create(name: parent_category_seed[:name], user_id: user.id) - end - parent_category_seed[:children].each do |child_category_seed| - child = Category.find_by(name: child_category_seed[:name], parent_id: parent.id) - unless child - puts " Creating #{child_category_seed[:name]}" - Category.create(name: child_category_seed[:name], parent_id: parent.id, user_id: user.id) - end - end - end - end - desc 'Force re-creation of all elasticsearch mappings' task :rebuild_indexes => :environment do - [Post, Media, Onet::Occupation, Webpage, User].each do |klass| + [ContentItem].each do |klass| klass.__elasticsearch__.create_index! force: true klass.import end end - - desc 'Find and replace text in any AR model and attribute' - task :replace => :environment do - - find = ENV['FIND'] - replace = ENV['REPLACE'] - tenant = ENV['TENANT'] - model, field = ENV['ATTRIBUTE'].split(":") - scope = ENV['SCOPE'] - - if [find, replace, tenant, model, field].include? nil - puts "You need to set env vars for FIND, REPLACE, ATTRIBUTE (i.e. 'Snippet:title') /or/ SCOPE and TENANT to use this" - next - end - - puts "Searching for #{model} with the text '#{find}' in tenant #{tenant}" - - if scope - matching_objects = Object.const_get(model).find_by_tenant_id(tenant).send(scope.to_sym, find) - else - matching_objects = Object.const_get(model).find_by_tenant_id(tenant).where("#{field} LIKE ?", "%#{find}%") - end - - # puts "This will replace text in #{matching_snippets.count} snippet(s) and #{matching_posts.count} post(s)" - - puts "Would you like to continue? (yes)" - confirmation = STDIN.gets.chomp - - next unless confirmation == "yes" or confirmation == "" - - matching_objects.all.each do |object| - puts "Replacing text in #{object}" - object.send(field).gsub! find, replace - object.save - end - - end - - namespace :snippets do - desc 'Find text in snippets' - task :find, [:text, :tenant_id] => :environment do |t, args| - if [args[:text], args[:tenant_id]].include? nil - puts "You need to pass parameters for 'text' and 'tenant' to use this" - next - end - - puts "Searching for Snippets with the text '#{args[:text]}' in tenant #{args[:tenant_id]}" - matching_snippets = Snippet.find_by_tenant_id(args[:tenant_id]).find_by_body_text(args[:text]) - - puts "There are #{matching_snippets.count} matching snippet(s)" - - puts 'Display snippet values? (yes)' - confirmation = STDIN.gets.chomp - - matching_snippets.all.each do |snippet| - puts "Found text in snippet with name: '#{snippet.document.name}' and ID: '#{snippet.id}' on Webpage URL: #{snippet.webpage.url}" - puts "Value: #{snippet.document.body}" if confirmation == 'yes' or confirmation == '' - end - end - - desc 'Find and replace text in snippets' - task :replace => :environment do - - find = ENV['FIND'] - replace = ENV['REPLACE'] - tenant = ENV['TENANT'] - - if [find, replace, tenant].include? nil - puts "You need to set env vars for FIND, REPLACE and TENANT to use this" - next - end - - - # Replace text in Snippets and in Posts - puts "Searching for Snippets with the text '#{find}' in tenant #{tenant}" - matching_snippets = Snippet.find_by_tenant_id(tenant).find_by_body_text(find) - - puts "Searching for Posts with the text '#{find}' in tenant #{tenant}" - matching_posts = Post.find_by_tenant_id(tenant).find_by_body_text(find) - - puts "This will replace text in #{matching_snippets.count} snippet(s) and #{matching_posts.count} post(s)" - - puts "Would you like to continue? (yes)" - confirmation = STDIN.gets.chomp - - next unless confirmation == "yes" or confirmation == "" - - matching_snippets.all.each do |snippet| - puts "Replacing text in #{snippet.document.name} on #{snippet.webpage.url}" - snippet.document.body.gsub! find, replace - snippet.document.save - end - - matching_posts.all.each do |post| - puts "Replacing text in '#{post.title}'" - post.body.gsub! find, replace - post.save - end - - end - - desc 'Remove orphaned snippets' - task :deorphan => :environment do - puts "Orphaned Snippet removal begun.." - - orphaned_snippets = Snippet.where([ - "user_id NOT IN (?) OR document_id NOT IN (?) OR webpage_id NOT IN (?)", - User.select("id"), - Document.select("id"), - Webpage.select("id") - ]) - - orphaned_snippets.each do |orphaned_snippet| - orphaned_snippet.document.destroy - orphaned_snippet.destroy - puts "Destroyed orphaned snippet: '#{orphaned_snippet.document.name}' with ID: '#{orphaned_snippet.id}'" - end - end - - desc 'Removed unused snippets' - task :simplify => :environment do - puts "Unused Snippet removal begun.." - - Webpage.all.each do |webpage| - # Download the template... - puts "Fetching template for #{webpage.url}" - - begin - template = Nokogiri::HTML open(webpage.url) - template_snippets = template.xpath("//snippet").map {|element| element['id']} - - # Find all snippets for this webpage that aren't in the array above and delete them - unused_snippets = Snippet.joins(:document).where([ - "webpage_id = (?) AND documents.name NOT IN (?)", - webpage.id, - template_snippets - ]).order(created_at: :desc) - - unused_snippets.each do |unused_snippet| - unused_snippet.document.destroy - unused_snippet.destroy - puts "Destroyed unused snippet: '#{unused_snippet.document.name}' with ID: '#{unused_snippet.id}'" - end - rescue Exception => e - puts "Error processing unused snippet removal for Webpage.\nError message: #{e.message}\nTrace: #{e.backtrace.inspect}" - end - end - end - - desc 'Remove duplicate snippets' - task :dedupe => :environment do - puts "Snippet de-duplication begun.." - - Webpage.all.each do |webpage| - puts "De-duplicating Snippets for Webpage: #{webpage.url}" - - snippets = webpage.snippets - snippets_deduped = snippets.to_a.uniq { |snippet| snippet.document.name } # Use natural sort order to de-dupe Snippets - leaked_snippets = snippets - snippets_deduped # Take difference of Snippets minus 'Actual Snippets' - - leaked_snippets.each do |leaked_snippet| - leaked_snippet.document.destroy - leaked_snippet.destroy - puts "Destroyed leaked duplicate snippet: '#{leaked_snippet.document.name}' with ID: '#{leaked_snippet.id}'" - end - end - end - - desc 'Remove leaked data by deleting duplicates and orphans' - task :unleak => :environment do - # First, remove all orphaned snippets, where orphaning can occur on user, document or webpage - Rake::Task['cortex:snippets:deorphan'].execute - Rake::Task['cortex:snippets:simplify'].execute - Rake::Task['cortex:snippets:dedupe'].execute - end - end - - namespace :onet do - desc 'Download ONET database' - task :fetch => :environment do - fetch_onet_db - end - - desc 'Provision ONET database' - task :provision => :environment do - provision_onet_db - end - - desc 'Download and provision ONET database' - task :fetch_and_provision => :environment do - fetch_onet_db - provision_onet_db - end - end - - namespace :media do - desc 'Update existing Media assets on S3 with new URL structure. Specify new structure in model, then pass old_path with the previous structure, i.e.: ":class/:attachment/:style-:id.:extension"' - task :update_url, [:old_path] => :environment do |t, args| - s3 = Aws::S3::Client.new(region: ENV['S3_REGION'], access_key_id: ENV['AWS_ACCESS_KEY_ID'], secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']) - unless args[:old_path] - puts '"old_path" argument must be set' - end - - Media.find_each do |media| - unless media.attachment_file_name.blank? - object_key = media.attachment.arbitrary_url_for args[:old_path] - - begin - previous_filename = media.attachment_file_name - image = s3.get_object({bucket: ENV['S3_BUCKET_NAME'], key: object_key}).body - puts "Re-saving image attachment #{media.id} - #{media.attachment_file_name}" - media.attachment = image - media.attachment_file_name = previous_filename - media.save - # if there are multiple styles (thumbnail, etc), recreate them: - media.attachment.reprocess! - rescue => ex - puts "An error of type #{ex.class} occurred, message is: '#{ex.message}'" - end - end - end - end - end -end - -private - -def fetch_onet_db - puts "Downloading ONET db: #{onet_package_name}.." - - response = Faraday.new('https://www.onetcenter.org').get "/dl_files/#{onet_package_name}.zip" - - open(Rails.root.join('tmp', "#{onet_package_name}.zip"), 'wb') { |file| file.write(response.body) } - sh "unzip -o #{Rails.root.join('tmp', "#{onet_package_name}.zip")} -d #{Rails.root.join('tmp')}" -end - -def provision_onet_db - seed_industries - provision_onet_occupations -end - -def provision_onet_occupations - puts 'Provisioning ONET Occupations..' - - first = true - CSV.foreach(Rails.root.join('tmp', onet_package_name, 'Occupation Data.txt'), :headers => %w(soc title description), :col_sep => "\t") do |row| - if first - # Absolutely gross, CSV's foreach doesn't give us a counter, and no way to skip the first row when defining your own headers, so... - first = false - next - end - - Onet::Occupation.create!(row.to_hash) - end -end - -def seed_industries - puts 'Seeding Industries (Job Families)..' - industries_seed = SeedData.onet_industries - - industries_seed.each do |industry| - unless Onet::Occupation.find_by soc: industry[:soc] - Onet::Occupation.create!(industry) - end - end -end - -def onet_package_name - "db_#{(Cortex.config.onet.version.to_s || '18.1').gsub('.', '_')}" end diff --git a/lib/tasks/employer/blog.rake b/lib/tasks/employer/blog.rake index be7d98a1e..f89d7d4b2 100644 --- a/lib/tasks/employer/blog.rake +++ b/lib/tasks/employer/blog.rake @@ -35,21 +35,6 @@ namespace :employer do tree end - def onet_tree - tree = Tree.new - - industries_seed = SeedData.onet_industries - - industries_seed.each do |industry| - tree.add_node({name: industry[:title]}) - end - - Onet::Occupation.industries.each do |onet_code| - end - - tree - end - puts "Creating Employer Blog ContentType..." blog = ContentType.new({ name: "Employer Blog", diff --git a/public/bulk_templates/media.csv b/public/bulk_templates/media.csv deleted file mode 100644 index 984537b4b..000000000 --- a/public/bulk_templates/media.csv +++ /dev/null @@ -1 +0,0 @@ -ID,Display Name,Description,Expiration,Tags,"Type (Media, Youtube)",Filename,Youtube ID ,Test Image,This is a great description,,"test,image,media",Media,rat 8.jpg, 1,Updated Media Test,This media was updated by the bulk uploader,2015-04-23,,Media,rat 8.jpg, ,Video Thingy,Some description here,,"video,test,youtube",Youtube,,uBqaOs6omrI \ No newline at end of file diff --git a/public/bulk_templates/users.csv b/public/bulk_templates/users.csv deleted file mode 100644 index 74a3d38a8..000000000 --- a/public/bulk_templates/users.csv +++ /dev/null @@ -1 +0,0 @@ -ID,Email,First Name,Last Name,Is Admin? (true or false),Tenant ID ,test@user1.com,Test,User1,FALSE,1 5,test@userupdate.com,Test,UserUpdate,TRUE,1 ,test@user2.com,Test,User2,FALSE,1 \ No newline at end of file diff --git a/public/ckeditor-plugins/media-selector/icons/media.png b/public/ckeditor-plugins/media-selector/icons/media.png deleted file mode 100644 index 68f70305b..000000000 Binary files a/public/ckeditor-plugins/media-selector/icons/media.png and /dev/null differ diff --git a/public/ckeditor-plugins/media-selector/plugin.js b/public/ckeditor-plugins/media-selector/plugin.js deleted file mode 100644 index 9dcd1541e..000000000 --- a/public/ckeditor-plugins/media-selector/plugin.js +++ /dev/null @@ -1,30 +0,0 @@ -(function (global) { - 'use strict'; - - global.CKEDITOR.plugins.add('media-selector', { - icons: 'media', - init: function (editor) { - editor.addCommand('insertMedia', { - exec: function (editor) { - var mediaLibraryModal = $('#media-library-modal'); - mediaLibraryModal.modal('open'); - - global.media_select = {}; - global.media_select_defer = $.Deferred(); - global.media_select_defer.promise(global.media_select); - - global.media_select.done(function (media) { - editor.insertHtml(global.utility.getMediaHtml(media)); - mediaLibraryModal.modal('close'); - }); - } - }); - - editor.ui.addButton('Media', { - label: 'Insert Media', - command: 'insertMedia', - toolbar: 'insert' - }); - } - }); -}(this)); diff --git a/public/ckeditor-plugins/sourcedialog/dialogs/sourcedialog.js b/public/ckeditor-plugins/sourcedialog/dialogs/sourcedialog.js deleted file mode 100644 index d194e26e2..000000000 --- a/public/ckeditor-plugins/sourcedialog/dialogs/sourcedialog.js +++ /dev/null @@ -1,79 +0,0 @@ -/** - * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or http://ckeditor.com/license - */ - -CKEDITOR.dialog.add( 'sourcedialog', function( editor ) { - var size = CKEDITOR.document.getWindow().getViewPaneSize(); - - // Make it maximum 800px wide, but still fully visible in the viewport. - var width = Math.min( size.width - 70, 800 ); - - // Make it use 2/3 of the viewport height. - var height = size.height / 1.5; - - // Store old editor data to avoid unnecessary setData. - var oldData; - - return { - title: editor.lang.sourcedialog.title, - minWidth: 100, - minHeight: 100, - - onShow: function() { - this.setValueOf( 'main', 'data', oldData = editor.getData() ); - }, - - onOk: ( function() { - function setData( dialog, newData ) { - // [IE8] Focus editor before setting selection to avoid setting data on - // locked selection, because in case of inline editor, it won't be - // unlocked before editable's HTML is altered. (#11585) - editor.focus(); - editor.setData( newData, function() { - dialog.hide(); - - // Ensure correct selection. - var range = editor.createRange(); - range.moveToElementEditStart( editor.editable() ); - range.select(); - } ); - } - - return function() { - // Remove CR from input data for reliable comparison with editor data. - var newData = this.getValueOf( 'main', 'data' ).replace( /\r/g, '' ), - that = this; - - // Avoid unnecessary setData. Also preserve selection - // when user changed his mind and goes back to wysiwyg editing. - if ( newData === oldData ) - return true; - - setTimeout( function() { - setData( that, newData ); - } ); - - // Don't let the dialog close before setData is over, to hide - // from user blinking caused by selection restoring and setting new data. - return false; - }; - } )(), - - contents: [ { - id: 'main', - label: editor.lang.sourcedialog.title, - elements: [ { - type: 'textarea', - id: 'data', - dir: 'ltr', - inputStyle: 'cursor:auto;' + - 'width:' + width + 'px;' + - 'height:' + height + 'px;' + - 'tab-size:4;' + - 'text-align:left;', - 'class': 'cke_source' - } ] - } ] - }; -} ); diff --git a/public/ckeditor-plugins/sourcedialog/icons/hidpi/sourcedialog-rtl.png b/public/ckeditor-plugins/sourcedialog/icons/hidpi/sourcedialog-rtl.png deleted file mode 100644 index adf4af3c9..000000000 Binary files a/public/ckeditor-plugins/sourcedialog/icons/hidpi/sourcedialog-rtl.png and /dev/null differ diff --git a/public/ckeditor-plugins/sourcedialog/icons/hidpi/sourcedialog.png b/public/ckeditor-plugins/sourcedialog/icons/hidpi/sourcedialog.png deleted file mode 100644 index b4d0a15a4..000000000 Binary files a/public/ckeditor-plugins/sourcedialog/icons/hidpi/sourcedialog.png and /dev/null differ diff --git a/public/ckeditor-plugins/sourcedialog/icons/sourcedialog-rtl.png b/public/ckeditor-plugins/sourcedialog/icons/sourcedialog-rtl.png deleted file mode 100644 index 27d1ba881..000000000 Binary files a/public/ckeditor-plugins/sourcedialog/icons/sourcedialog-rtl.png and /dev/null differ diff --git a/public/ckeditor-plugins/sourcedialog/icons/sourcedialog.png b/public/ckeditor-plugins/sourcedialog/icons/sourcedialog.png deleted file mode 100644 index e44db3798..000000000 Binary files a/public/ckeditor-plugins/sourcedialog/icons/sourcedialog.png and /dev/null differ diff --git a/public/ckeditor-plugins/sourcedialog/lang/af.js b/public/ckeditor-plugins/sourcedialog/lang/af.js deleted file mode 100644 index 6cd8c493a..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/af.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'af', { - toolbar: 'Bron', - title: 'Bron' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/ar.js b/public/ckeditor-plugins/sourcedialog/lang/ar.js deleted file mode 100644 index e1b28c368..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/ar.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'ar', { - toolbar: 'المصدر', - title: 'المصدر' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/bg.js b/public/ckeditor-plugins/sourcedialog/lang/bg.js deleted file mode 100644 index 7d2b841d1..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/bg.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'bg', { - toolbar: 'Източник', - title: 'Източник' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/bn.js b/public/ckeditor-plugins/sourcedialog/lang/bn.js deleted file mode 100644 index 3292a0d9d..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/bn.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'bn', { - toolbar: 'সোর্স', - title: 'সোর্স' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/bs.js b/public/ckeditor-plugins/sourcedialog/lang/bs.js deleted file mode 100644 index 434490a66..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/bs.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'bs', { - toolbar: 'HTML kôd', - title: 'HTML kôd' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/ca.js b/public/ckeditor-plugins/sourcedialog/lang/ca.js deleted file mode 100644 index 1ad1cb5ea..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/ca.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'ca', { - toolbar: 'Codi font', - title: 'Codi font' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/cs.js b/public/ckeditor-plugins/sourcedialog/lang/cs.js deleted file mode 100644 index 3940a399d..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/cs.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'cs', { - toolbar: 'Zdroj', - title: 'Zdroj' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/cy.js b/public/ckeditor-plugins/sourcedialog/lang/cy.js deleted file mode 100644 index 6c03bee18..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/cy.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'cy', { - toolbar: 'HTML', - title: 'HTML' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/da.js b/public/ckeditor-plugins/sourcedialog/lang/da.js deleted file mode 100644 index 0d94abe02..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/da.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'da', { - toolbar: 'Kilde', - title: 'Kilde' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/de.js b/public/ckeditor-plugins/sourcedialog/lang/de.js deleted file mode 100644 index e27d313f9..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/de.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'de', { - toolbar: 'Quellcode', - title: 'Quellcode' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/el.js b/public/ckeditor-plugins/sourcedialog/lang/el.js deleted file mode 100644 index 7c75dd3fb..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/el.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'el', { - toolbar: 'Κώδικας', - title: 'Κώδικας' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/en-au.js b/public/ckeditor-plugins/sourcedialog/lang/en-au.js deleted file mode 100644 index 607cdd663..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/en-au.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'en-au', { - toolbar: 'Source', - title: 'Source' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/en-ca.js b/public/ckeditor-plugins/sourcedialog/lang/en-ca.js deleted file mode 100644 index 767a3d358..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/en-ca.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'en-ca', { - toolbar: 'Source', - title: 'Source' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/en-gb.js b/public/ckeditor-plugins/sourcedialog/lang/en-gb.js deleted file mode 100644 index 3961c7110..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/en-gb.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'en-gb', { - toolbar: 'Source', - title: 'Source' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/en.js b/public/ckeditor-plugins/sourcedialog/lang/en.js deleted file mode 100644 index 8204c4921..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/en.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'en', { - toolbar: 'Source', - title: 'Source' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/eo.js b/public/ckeditor-plugins/sourcedialog/lang/eo.js deleted file mode 100644 index 6f5f279ab..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/eo.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'eo', { - toolbar: 'Fonto', - title: 'Fonto' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/es.js b/public/ckeditor-plugins/sourcedialog/lang/es.js deleted file mode 100644 index aaf85a48c..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/es.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'es', { - toolbar: 'Fuente HTML', - title: 'Fuente HTML' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/et.js b/public/ckeditor-plugins/sourcedialog/lang/et.js deleted file mode 100644 index 69dfd3a31..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/et.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'et', { - toolbar: 'Lähtekood', - title: 'Lähtekood' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/eu.js b/public/ckeditor-plugins/sourcedialog/lang/eu.js deleted file mode 100644 index 2ec118876..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/eu.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'eu', { - toolbar: 'HTML Iturburua', - title: 'HTML Iturburua' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/fa.js b/public/ckeditor-plugins/sourcedialog/lang/fa.js deleted file mode 100644 index 08acc9ddd..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/fa.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'fa', { - toolbar: 'منبع', - title: 'منبع' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/fi.js b/public/ckeditor-plugins/sourcedialog/lang/fi.js deleted file mode 100644 index c73e7300e..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/fi.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'fi', { - toolbar: 'Koodi', - title: 'Koodi' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/fo.js b/public/ckeditor-plugins/sourcedialog/lang/fo.js deleted file mode 100644 index 8073885d5..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/fo.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'fo', { - toolbar: 'Kelda', - title: 'Kelda' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/fr-ca.js b/public/ckeditor-plugins/sourcedialog/lang/fr-ca.js deleted file mode 100644 index 46d11872b..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/fr-ca.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'fr-ca', { - toolbar: 'Source', - title: 'Source' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/fr.js b/public/ckeditor-plugins/sourcedialog/lang/fr.js deleted file mode 100644 index 31c7a6f82..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/fr.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'fr', { - toolbar: 'Source', - title: 'Source' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/gl.js b/public/ckeditor-plugins/sourcedialog/lang/gl.js deleted file mode 100644 index aeadd6fa7..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/gl.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'gl', { - toolbar: 'Orixe', - title: 'Orixe' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/gu.js b/public/ckeditor-plugins/sourcedialog/lang/gu.js deleted file mode 100644 index 9f40cb143..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/gu.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'gu', { - toolbar: 'મૂળ કે પ્રાથમિક દસ્તાવેજ', - title: 'મૂળ કે પ્રાથમિક દસ્તાવેજ' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/he.js b/public/ckeditor-plugins/sourcedialog/lang/he.js deleted file mode 100644 index 472a92a99..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/he.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'he', { - toolbar: 'מקור', - title: 'מקור' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/hi.js b/public/ckeditor-plugins/sourcedialog/lang/hi.js deleted file mode 100644 index 49d828096..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/hi.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'hi', { - toolbar: 'सोर्स', - title: 'सोर्स' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/hr.js b/public/ckeditor-plugins/sourcedialog/lang/hr.js deleted file mode 100644 index 8ebd2bb30..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/hr.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'hr', { - toolbar: 'Kôd', - title: 'Kôd' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/hu.js b/public/ckeditor-plugins/sourcedialog/lang/hu.js deleted file mode 100644 index c52fe23d0..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/hu.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'hu', { - toolbar: 'Forráskód', - title: 'Forráskód' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/id.js b/public/ckeditor-plugins/sourcedialog/lang/id.js deleted file mode 100644 index 9ec1b06d3..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/id.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'id', { - toolbar: 'Sumber', - title: 'Sumber' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/is.js b/public/ckeditor-plugins/sourcedialog/lang/is.js deleted file mode 100644 index a231623c9..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/is.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'is', { - toolbar: 'Kóði', - title: 'Kóði' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/it.js b/public/ckeditor-plugins/sourcedialog/lang/it.js deleted file mode 100644 index 5bdb4cfb1..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/it.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'it', { - toolbar: 'Sorgente', - title: 'Sorgente' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/ja.js b/public/ckeditor-plugins/sourcedialog/lang/ja.js deleted file mode 100644 index dbd1bc5fe..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/ja.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'ja', { - toolbar: 'ソース', - title: 'ソース' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/ka.js b/public/ckeditor-plugins/sourcedialog/lang/ka.js deleted file mode 100644 index 6db7a54af..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/ka.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'ka', { - toolbar: 'კოდები', - title: 'კოდები' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/km.js b/public/ckeditor-plugins/sourcedialog/lang/km.js deleted file mode 100644 index ef358b00b..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/km.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'km', { - toolbar: 'អក្សរ​កូដ', - title: 'អក្សរ​កូដ' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/ko.js b/public/ckeditor-plugins/sourcedialog/lang/ko.js deleted file mode 100644 index 6eefb1a2a..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/ko.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'ko', { - toolbar: '소스', - title: '소스' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/ku.js b/public/ckeditor-plugins/sourcedialog/lang/ku.js deleted file mode 100644 index 599df6eb7..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/ku.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'ku', { - toolbar: 'سەرچاوە', - title: 'سەرچاوە' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/lt.js b/public/ckeditor-plugins/sourcedialog/lang/lt.js deleted file mode 100644 index 2f289a93e..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/lt.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'lt', { - toolbar: 'Šaltinis', - title: 'Šaltinis' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/lv.js b/public/ckeditor-plugins/sourcedialog/lang/lv.js deleted file mode 100644 index 15612a122..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/lv.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'lv', { - toolbar: 'HTML kods', - title: 'HTML kods' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/mn.js b/public/ckeditor-plugins/sourcedialog/lang/mn.js deleted file mode 100644 index d2c5d3d1c..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/mn.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'mn', { - toolbar: 'Код', - title: 'Код' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/ms.js b/public/ckeditor-plugins/sourcedialog/lang/ms.js deleted file mode 100644 index cac896f58..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/ms.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'ms', { - toolbar: 'Sumber', - title: 'Sumber' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/nb.js b/public/ckeditor-plugins/sourcedialog/lang/nb.js deleted file mode 100644 index 1b8cbd274..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/nb.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'nb', { - toolbar: 'Kilde', - title: 'Kilde' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/nl.js b/public/ckeditor-plugins/sourcedialog/lang/nl.js deleted file mode 100644 index 95a4cedde..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/nl.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'nl', { - toolbar: 'Broncode', - title: 'Broncode' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/no.js b/public/ckeditor-plugins/sourcedialog/lang/no.js deleted file mode 100644 index 8d8b2a054..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/no.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'no', { - toolbar: 'Kilde', - title: 'Kilde' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/pl.js b/public/ckeditor-plugins/sourcedialog/lang/pl.js deleted file mode 100644 index fc9e91b69..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/pl.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'pl', { - toolbar: 'Źródło dokumentu', - title: 'Źródło dokumentu' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/pt-br.js b/public/ckeditor-plugins/sourcedialog/lang/pt-br.js deleted file mode 100644 index 154e966a3..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/pt-br.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'pt-br', { - toolbar: 'Código-Fonte', - title: 'Código-Fonte' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/pt.js b/public/ckeditor-plugins/sourcedialog/lang/pt.js deleted file mode 100644 index 0c743481b..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/pt.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'pt', { - toolbar: 'Fonte', - title: 'Fonte' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/ro.js b/public/ckeditor-plugins/sourcedialog/lang/ro.js deleted file mode 100644 index f9794bfed..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/ro.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'ro', { - toolbar: 'Sursa', - title: 'Sursa' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/ru.js b/public/ckeditor-plugins/sourcedialog/lang/ru.js deleted file mode 100644 index 7a244aea7..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/ru.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'ru', { - toolbar: 'Исходник', - title: 'Источник' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/si.js b/public/ckeditor-plugins/sourcedialog/lang/si.js deleted file mode 100644 index 4ca20d01e..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/si.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'si', { - toolbar: 'මුලාශ්‍රය', - title: 'මුලාශ්‍රය' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/sk.js b/public/ckeditor-plugins/sourcedialog/lang/sk.js deleted file mode 100644 index 2b2bce3e1..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/sk.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'sk', { - toolbar: 'Zdroj', - title: 'Zdroj' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/sl.js b/public/ckeditor-plugins/sourcedialog/lang/sl.js deleted file mode 100644 index a2105b1ef..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/sl.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'sl', { - toolbar: 'Izvorna koda', - title: 'Izvorna koda' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/sq.js b/public/ckeditor-plugins/sourcedialog/lang/sq.js deleted file mode 100644 index 468cba243..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/sq.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'sq', { - toolbar: 'Burimi', - title: 'Burimi' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/sr-latn.js b/public/ckeditor-plugins/sourcedialog/lang/sr-latn.js deleted file mode 100644 index 1ebdf12da..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/sr-latn.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'sr-latn', { - toolbar: 'Kôd', - title: 'Kôd' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/sr.js b/public/ckeditor-plugins/sourcedialog/lang/sr.js deleted file mode 100644 index f9a1560a2..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/sr.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'sr', { - toolbar: 'Kôд', - title: 'Kôд' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/sv.js b/public/ckeditor-plugins/sourcedialog/lang/sv.js deleted file mode 100644 index 472182520..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/sv.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'sv', { - toolbar: 'Källa', - title: 'Källa' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/th.js b/public/ckeditor-plugins/sourcedialog/lang/th.js deleted file mode 100644 index 4a2f3852f..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/th.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'th', { - toolbar: 'ดูรหัส HTML', - title: 'ดูรหัส HTML' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/tr.js b/public/ckeditor-plugins/sourcedialog/lang/tr.js deleted file mode 100644 index 6cf3da37e..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/tr.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'tr', { - toolbar: 'Kaynak', - title: 'Kaynak' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/tt.js b/public/ckeditor-plugins/sourcedialog/lang/tt.js deleted file mode 100644 index 00ea3a07b..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/tt.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'tt', { - toolbar: 'Чыганак', - title: 'Чыганак' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/ug.js b/public/ckeditor-plugins/sourcedialog/lang/ug.js deleted file mode 100644 index e80bed741..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/ug.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'ug', { - toolbar: 'مەنبە', - title: 'مەنبە' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/uk.js b/public/ckeditor-plugins/sourcedialog/lang/uk.js deleted file mode 100644 index 2127104a8..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/uk.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'uk', { - toolbar: 'Джерело', - title: 'Джерело' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/vi.js b/public/ckeditor-plugins/sourcedialog/lang/vi.js deleted file mode 100644 index fa7d52445..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/vi.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'vi', { - toolbar: 'Mã HTML', - title: 'Mã HTML' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/zh-cn.js b/public/ckeditor-plugins/sourcedialog/lang/zh-cn.js deleted file mode 100644 index 7aa384ab2..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/zh-cn.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'zh-cn', { - toolbar: '源码', - title: '源码' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/lang/zh.js b/public/ckeditor-plugins/sourcedialog/lang/zh.js deleted file mode 100644 index fc201c8bc..000000000 --- a/public/ckeditor-plugins/sourcedialog/lang/zh.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.setLang( 'sourcedialog', 'zh', { - toolbar: '原始碼', - title: '原始碼' -} ); diff --git a/public/ckeditor-plugins/sourcedialog/plugin.js b/public/ckeditor-plugins/sourcedialog/plugin.js deleted file mode 100644 index 009e22207..000000000 --- a/public/ckeditor-plugins/sourcedialog/plugin.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or http://ckeditor.com/license - */ - -CKEDITOR.plugins.add( 'sourcedialog', { - // jscs:disable maximumLineLength - lang: 'af,ar,bg,bn,bs,ca,cs,cy,da,de,el,en,en-au,en-ca,en-gb,eo,es,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mn,ms,nb,nl,no,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE% - // jscs:enable maximumLineLength - icons: 'sourcedialog,sourcedialog-rtl', // %REMOVE_LINE_CORE% - hidpi: true, // %REMOVE_LINE_CORE% - - init: function( editor ) { - // Register the "source" command, which simply opens the "source" dialog. - editor.addCommand( 'sourcedialog', new CKEDITOR.dialogCommand( 'sourcedialog' ) ); - - // Register the "source" dialog. - CKEDITOR.dialog.add( 'sourcedialog', this.path + 'dialogs/sourcedialog.js' ); - - // If the toolbar is available, create the "Source" button. - if ( editor.ui.addButton ) { - editor.ui.addButton( 'Sourcedialog', { - label: editor.lang.sourcedialog.toolbar, - command: 'sourcedialog', - toolbar: 'mode,10' - } ); - } - } -} ); diff --git a/public/ckeditor-plugins/sourcedialog/samples/sourcedialog.html b/public/ckeditor-plugins/sourcedialog/samples/sourcedialog.html deleted file mode 100644 index 738a98bae..000000000 --- a/public/ckeditor-plugins/sourcedialog/samples/sourcedialog.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - Editing source code in a dialog — CKEditor Sample - - - - - - - - - -

- CKEditor Samples » Editing source code in a dialog -

-
- This sample is not maintained anymore. Check out its brand new version in CKEditor SDK. -
-
-

- Sourcedialog plugin provides an easy way to edit raw HTML content - of an editor, similarly to what is possible with Sourcearea - plugin for classic (iframe-based) instances but using dialogs. Thanks to that, it's also possible - to manipulate raw content of inline editor instances. -

-

- This plugin extends the toolbar with a button, - which opens a dialog window with a source code editor. It works with both classic - and inline instances. To enable this - plugin, basically add extraPlugins: 'sourcedialog' to editor's - config: -

-
-// Inline editor.
-CKEDITOR.inline( 'editable', {
-	extraPlugins: 'sourcedialog'
-});
-
-// Classic (iframe-based) editor.
-CKEDITOR.replace( 'textarea_id', {
-	extraPlugins: 'sourcedialog',
-	removePlugins: 'sourcearea'
-});
-
-

- Note that you may want to include removePlugins: 'sourcearea' - in your config when using Sourcedialog in classic editor instances. - This prevents feature redundancy. -

-

- Note that editable in the code above is the id - attribute of the <div> element to be converted into an inline instance. -

-

- Note that textarea_id in the code above is the id attribute of - the <textarea> element to be replaced with CKEditor. -

-
-
- -
-

This is some sample text. You are using CKEditor.

-
-
-
-
- - -
- - - - diff --git a/public/content-snippets-edit b/public/content-snippets-edit new file mode 120000 index 000000000..dbb37c714 --- /dev/null +++ b/public/content-snippets-edit @@ -0,0 +1 @@ +/home/atharp/Repos/content-snippets-edit \ No newline at end of file diff --git a/public/youtubes/.keep b/public/youtubes/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/semaphore_ci/setup.sh b/semaphore_ci/setup.sh index 9676e380b..9df6bdf09 100755 --- a/semaphore_ci/setup.sh +++ b/semaphore_ci/setup.sh @@ -4,6 +4,9 @@ gem update --system echo "gem update bundler" gem update bundler +echo "npm install" +npm install + echo "bundle config build.nokogiri --use-system-libraries" bundle config build.nokogiri --use-system-libraries @@ -13,14 +16,14 @@ bundle install --without production staging development tasks echo "bundle exec rake bower:install:development" bundle exec rake bower:install:development -echo "bundle exec rake webpack:ensure_assets_compiled" -bundle exec rake webpack:ensure_assets_compiled +echo "bundle exec rake cortex:assets:webpack:ensure_all_assets_compiled" +bundle exec rake cortex:assets:webpack:ensure_all_assets_compiled echo "bundle exec rake db:setup" bundle exec rake db:setup -echo "bundle exec rake cortex:create_categories cortex:onet:fetch_and_provision cortex:core:db:reseed" -bundle exec rake cortex:create_categories cortex:onet:fetch_and_provision cortex:core:db:reseed +echo "bundle exec rake cortex:core:db:reseed" +bundle exec rake cortex:core:db:reseed echo "bundle exec rake cortex:rebuild_indexes" bundle exec rake cortex:rebuild_indexes diff --git a/spec/api/v1/resources/applications_spec.rb b/spec/api/v1/resources/applications_spec.rb deleted file mode 100644 index 636638413..000000000 --- a/spec/api/v1/resources/applications_spec.rb +++ /dev/null @@ -1,123 +0,0 @@ -describe SPEC_API::Resources::Applications, :type => :request do - - let(:user) { create(:user, :admin) } - - before do - login_as user - end - - describe 'GET /applications/:id' do - - let(:application) { create(:application) } - - it 'should be a success' do - get "/api/v1/applications/#{application.id}" - expect(response).to be_success - - end - - it 'should return the correct application' do - get "/api/v1/applications/#{application.id}" - expect(response.body).to represent(SPEC_API::Entities::Application, application) - end - end - - describe 'POST /applications' do - - context 'with valid attributes' do - - it 'should be a success' do - post '/api/v1/applications', attributes_for(:application) - expect{ post '/api/v1/applications', attributes_for(:application) }.to change(Application, :count).by(1) - expect(response).to be_success - end - - it 'should create a new application' do - post '/api/v1/applications', attributes_for(:application) - expect(response.body).to represent(SPEC_API::Entities::Application, Application.last) - end - - it 'should change the application count by 1' do - expect{ post '/api/v1/applications', attributes_for(:application) }.to change(Application, :count).by(1) - end - end - - context 'with invalid attributes' do - it 'should NOT create a new application' do - expect{ post '/api/v1/applications', attributes_for(:application, name: nil) }.to_not change(Application, :count) - end - it 'should not be a success' do - post '/api/v1/applications', attributes_for(:application, name: nil) - expect(response).not_to be_success - end - end - end - - describe 'PUT /applications/:id' do - - context 'with valid attributes' do - let(:application) { create(:application) } - - it 'should update the application' do - application.name += ' updated' - put "/api/v1/applications/#{application.id}", application.to_json, application_json - expect(response.body).to represent(SPEC_API::Entities::Application, application) - end - it 'should be a success' do - application.name += ' updated' - put "/api/v1/applications/#{application.id}", application.to_json, application_json - expect(response).to be_success - end - it 'should not create a new application' do - application.name += ' updated' - expect{ put "/api/v1/applications/#{application.id}", application.to_json, application_json }.to_not change(Application, :count) - end - end - - context 'with invalid attributes' do - let(:application) { create(:application) } - - it 'should NOT update the application' do - application - expect{ put "/api/v1/applications/#{application.id}", {name: nil}.to_json, application_json }.to_not change(Application, :count) - end - - it 'should not be a success' do - put "/api/v1/applications/#{application.id}", {name: nil}.to_json, application_json - expect(response).not_to be_success - end - end - end - - describe 'DELETE /applications/:id' do - - context 'with an existing application' do - let(:application) { create(:application) } - - it 'should be a success' do - delete "/api/v1/applications/#{application.id}" - expect(response).to be_success - end - - it 'should delete the application' do - application - expect{ delete "/api/v1/applications/#{application.id}" }.to change(Application, :count).by(-1) - end - end - - context 'with a nonexistent application' do - let(:application) { create(:application) } - - it 'should not be a success' do - application - delete "/api/v1/applications/#{application.id+1}" - expect(response).not_to be_success - end - - it 'should not change the application count' do - application - expect{ delete "/api/v1/applications/#{application.id+1}" }.to_not change(Application, :count) - end - end - end -end diff --git a/spec/api/v1/resources/content_items_spec.rb b/spec/api/v1/resources/content_items_spec.rb deleted file mode 100644 index 85756d5ca..000000000 --- a/spec/api/v1/resources/content_items_spec.rb +++ /dev/null @@ -1,43 +0,0 @@ -describe SPEC_API::Resources::ContentItems, type: :request do - - let(:user) { create(:user, :admin) } - let(:field) { create(:field) } - let(:content_type) { field.content_type } - - before(:each) do - login_as user - end - - context 'with valid attributes' do - let(:valid_content_item) { - { - publish_state: "draft", - author_id: user.id, - creator_id: user.id, - content_type_id: content_type.id, - field_items_attributes: [ - { - field_id: field.id, - text: "abc123" - } - ] - } - } - - xit 'should create a new content item' do - expect{ post '/api/v1/content_items', valid_content_item }.to change(ContentItem, :count).by(1) - expect(response).to be_success - expect(response.body).to represent(SPEC_API::Entities::ContentItem, ContentItem.last, { full: true }) - content_item = ContentItem.last - expect(content_item.content_type.name).to eq content_type.name - expect(content_item.field_items.first.field_id).to eq field.id - end - end - - context 'with invalid attributes' do - it 'should NOT create a new content item' do - expect{ post '/api/v1/content_items', attributes_for(:content_item, creator: nil) }.to_not change(ContentItem, :count) - expect(response).not_to be_success - end - end -end diff --git a/spec/api/v1/resources/content_types_spec.rb b/spec/api/v1/resources/content_types_spec.rb deleted file mode 100644 index 2e9866400..000000000 --- a/spec/api/v1/resources/content_types_spec.rb +++ /dev/null @@ -1,54 +0,0 @@ -describe SPEC_API::Resources::ContentTypes, type: :request do - let(:user) { create(:user, :admin) } - - before(:each) do - login_as user - end - - describe 'GET /content_types' do - before(:each) do - 3.times { |i| create(:content_type, name: "Bloggy #{i}") } - end - - it "returns all content types" do - get '/api/v1/content_types' - expect(response).to be_success - expect(JSON.parse(response.body).map { |content_type| content_type['name'] }).to match_array(["Bloggy 0", "Bloggy 1", "Bloggy 2"]) - end - end - - describe 'GET /content_types/:content_type_id' do - let(:content_type) { create(:content_type, name: "Blog post") } - let!(:last_name_field) { create(:field, content_type: content_type, name: "Last Name", validations: { length: 20}) } - let!(:first_name_field) { build(:field, name: "First Name") } - let(:content_type_response) do - { - id: content_type.id, - name: content_type.name, - fields: [ - { - required: first_name_field.required, - field_type: first_name_field.field_type, - name: first_name_field.name, - validations: first_name_field.validations - }, - { - required: last_name_field.required, - field_type: last_name_field.field_type, - name: last_name_field.name, - validations: last_name_field.validations - } - ] - } - end - - before do - first_name_field.update(content_type: content_type) - end - - xit "returns the fields for the specified content type" do - get "/api/v1/content_types/#{content_type.id}" - expect(JSON.parse(response.body, symbolize_names: true)).to eq content_type_response - end - end -end diff --git a/spec/api/v1/resources/credentials_spec.rb b/spec/api/v1/resources/credentials_spec.rb deleted file mode 100644 index 16dca7ff4..000000000 --- a/spec/api/v1/resources/credentials_spec.rb +++ /dev/null @@ -1,108 +0,0 @@ -describe SPEC_API::Resources::Credentials, :type => :request do - - let(:user) { create(:user, :admin) } - - before do - login_as user - end - - describe 'GET /applications/:application_id/credentials/:id' do - - let(:credentials) { create(:credentials) } - - it 'should be a success' do - get "/api/v1/applications/#{credentials.owner.id}/credentials" - expect(response).to be_success - end - - it 'should return the correct credentials' do - get "/api/v1/applications/#{credentials.owner.id}/credentials/#{credentials.id}" - expect(response.body).to represent(SPEC_API::Entities::Credential, credentials) - end - end - - describe 'POST /applications/:application_id/credentials/:id' do - - let(:application) { create(:application) } - - context 'with valid attributes' do - - it 'should be a success' do - post "/api/v1/applications/#{application.id}/credentials", attributes_for(:credentials) - expect(response).to be_success - end - - it 'should increase the number of credentials by 1' do - expect{ post "/api/v1/applications/#{application.id}/credentials", attributes_for(:credentials) }.to change{application.credentials.count}.by(1) - end - - it 'should create a new credential' do - post "/api/v1/applications/#{application.id}/credentials", attributes_for(:credentials) - expect(response.body).to represent(SPEC_API::Entities::Credential, application.credentials.last) - end - end - - context 'with invalid attributes' do - it 'should NOT create a new application' do - expect{ post "/api/v1/applications/#{application.id}/credentials", attributes_for(:credentials, name: nil) }.to_not change{application.credentials.count} - end - it 'should not be a success' do - post "/api/v1/applications/#{application.id}/credentials", attributes_for(:credentials, name: nil) - expect(response).not_to be_success - end - end - end - - describe 'PUT /applications/:application_id/credentials/:id' do - - context 'with valid attributes' do - let(:credentials) { create(:credentials) } - - it 'should update the credential' do - credentials.name += ' updated' - put "/api/v1/applications/#{credentials.owner.id}/credentials/#{credentials.id}", credentials.to_json, application_json - expect(response.body).to represent(SPEC_API::Entities::Credential, credentials) - end - it 'should be a success' do - credentials.name += ' updated' - put "/api/v1/applications/#{credentials.owner.id}/credentials/#{credentials.id}", credentials.to_json, application_json - expect(response).to be_success - end - it 'should not create a new credential' do - credentials.name += ' updated' - expect{ put "/api/v1/applications/#{credentials.owner.id}/credentials/#{credentials.id}", credentials.to_json, application_json }.to_not change{credentials.owner.credentials.count} - end - end - - context 'with invalid attributes' do - let(:credentials) { create(:credentials) } - - it 'should NOT update the credential' do - credentials - expect{ put "/api/v1/applications/#{credentials.owner.id}/credentials/#{credentials.id}", {name: nil}.to_json, application_json }.to_not change{credentials.owner.credentials.count} - end - - it 'should not be a success' do - put "/api/v1/applications/#{credentials.owner.id}/credentials/#{credentials.id}", {name: nil}.to_json, application_json - expect(response).not_to be_success - end - end - end - - describe 'DELETE /applications/:application_id/credentials/:id' do - - context 'with an existing credential' do - let(:credentials) { create(:credentials) } - - it 'should be a success' do - delete "/api/v1/applications/#{credentials.owner.id}/credentials/#{credentials.id}" - expect(response).to be_success - end - - it 'should delete the credential' do - credentials - expect{ delete "/api/v1/applications/#{credentials.owner.id}/credentials/#{credentials.id}" }.to change{credentials.owner.credentials.count}.by(-1) - end - end - end -end diff --git a/spec/api/v1/resources/documents_spec.rb b/spec/api/v1/resources/documents_spec.rb deleted file mode 100644 index 71b56e238..000000000 --- a/spec/api/v1/resources/documents_spec.rb +++ /dev/null @@ -1,91 +0,0 @@ -describe SPEC_API::Resources::Documents, type: :request do - - let(:user) { create(:user, :admin) } - - describe 'GET /documents' do - - it 'returns an empty array if there are no documents' do - get '/api/v1/documents' - expect(response).to be_success - expect(JSON.parse(response.body)).to eq([]) - end - - it 'should return two documents' do - 2.times { create(:document, user: user) } - get '/api/v1/documents' - expect(response).to be_success - expect(JSON.parse(response.body).count).to eq(2) - end - - it 'should return paginated results' do - 5.times { create(:document, user: user) } - get '/api/v1/documents?per_page=2' - expect(response).to be_success - expect(JSON.parse(response.body).count).to eq(2) - expect(response.headers['X-Total']).to eq('5') - end - end - - describe 'GET /documents/:id' do - - let(:document) { create(:document, user: user) } - - it 'should return the correct document' do - get "/api/v1/documents/#{document.id}" - expect(response).to be_success - expect(response.body).to represent(SPEC_API::Entities::Document, document) - end - end - - describe 'POST /documents' do - - context 'with valid attributes' do - it 'should create new document' do - pending 'Broken!' - expect{ post '/api/v1/documents', document: attributes_for(:document) }.to change(Document, :count).by(1) - expect(response).to be_success - expect(response.body).to represent(SPEC_API::Entities::Document, Document.last) - end - end - end - - describe 'PUT /documents/:id' do - - context 'with valid attributes' do - it 'should update document' do - document = create(:document, user: user) - document.name += ' updated' - expect{ put "/api/v1/documents/#{document.id}", document.to_json, application_json }.to_not change(Document, :count) - expect(response).to be_success - expect(response.body).to represent(SPEC_API::Entities::Document, document) - end - end - end - - describe 'DELETE /documents/:id' do - - it 'should delete document' do - document = create(:document, user: user) - expect{ delete "/api/v1/documents/#{document.id}" }.to change(Document, :count).by(-1) - expect(response).to be_success - end - - it 'should NOT delete non-existent document' do - document = create(:document, user: user) - expect{ delete "/api/v1/documents/#{document.id+1}" }.to_not change(Document, :count) - expect(response).not_to be_success - end - - it 'should not delete consumed document' do - pending 'Switch to Snippet relation rather than direct to Document' - document = create(:document, user: user) - snippet = create(:snippet) - webpage = create(:webpage, user: user) - webpage.documents << snippet - webpage.save - expect { delete "/api/v1/documents/#{document.id}" }.to_not change(Document, :count) - expect(Document.exists? document.id).to be_truthy - expect(response.status).to eq(409) - end - end -end diff --git a/spec/api/v1/resources/media_spec.rb b/spec/api/v1/resources/media_spec.rb deleted file mode 100644 index 429e65b9e..000000000 --- a/spec/api/v1/resources/media_spec.rb +++ /dev/null @@ -1,147 +0,0 @@ -describe SPEC_API::Resources::Media, type: :request, elasticsearch: true do - - let(:user) { create(:user, :admin) } - - before do - login_as user - Media.__elasticsearch__.create_index! index: Media.index_name - end - - describe 'GET /media' do - - context 'Media does not exist' do - xit 'returns an empty array' do - get '/api/v1/media' - expect(response).to be_success - expect(JSON.parse(response.body)).to eq([]) - end - end - - context 'Media does exist' do - before(:each) do - 5.times { create(:media, user: user) } - media_2 = create(:media, name: "RANDOM", user: user) - Media.import({refresh: true}) - end - - xit 'should return all media items' do - get '/api/v1/media' - expect(response).to be_success - expect(JSON.parse(response.body).count).to eq(Media.all.count) - end - - xit 'should return paginated results' do - get '/api/v1/media?per_page=2' - expect(response).to be_success - expect(JSON.parse(response.body).count).to eq(2) - expect(response.headers['X-Total']).to eq(Media.all.count.to_s) - end - - xit 'should allow search on q' do - get '/api/v1/media?q=RANDOM' - expect(response).to be_success - expect(JSON.parse(response.body).count).to eq(1) - end - end - end - - describe 'GET /media/tags' do - - xit 'returns an empty array if there are no tags' do - get '/api/v1/media/tags' - expect(response).to be_success - expect(JSON.parse(response.body)).to eq([]) - end - - xit 'should return the correct number of tags' do - 5.times { |i| create(:media, tag_list: ["tag_#{i}"], user: user) } - get '/api/v1/media/tags' - expect(response).to be_success - result = JSON.parse(response.body) - expect(result.count).to eq(5) - end - - xit 'should return popular tags in order' do - 5.times { |i| create(:media, tag_list: ['popular_tag', "tag_#{i}"], user: user) } - get '/api/v1/media/tags?popular=true' - expect(response).to be_success - result = JSON.parse(response.body) - expect(result.count).to eq(6) - expect(result[0]).to include('name' => 'popular_tag', 'count' => 5) - end - end - - describe 'GET /media/:id' do - - let(:media) { create(:media, user: user) } - - xit 'should return the correct media' do - get "/api/v1/media/#{media.id}" - expect(response).to be_success - expect(response.body).to represent(SPEC_API::Entities::Media, media, { full: true }) - end - end - - describe 'POST /media' do - - context 'with valid attributes' do - xit 'should create new media' do - expect{ post '/api/v1/media', media: attributes_for(:media) }.to change(Media, :count).by(1) - expect(response).to be_success - expect(response.body).to represent(SPEC_API::Entities::Media, Media.last, { full: true }) - end - end - end - - describe 'PUT /media/:id' do - - context 'with valid attributes' do - xit 'should update media' do - media = create(:media, user: user) - media.name += ' updated' - expect{ put "/api/v1/media/#{media.id}", media.to_json, application_json }.to_not change(Media, :count) - expect(response).to be_success - expect(response.body).to represent(SPEC_API::Entities::Media, media, { full: true }) - end - - xit 'should only update allowed parameters' do - media = create(:media, user: user) - media.name += ' updated' - media.taxon = 'BreakingTaxon' - expect { put "/api/v1/media/#{media.id}", media.to_json, application_json }.to_not change(Media, :count) - expect(response).to be_success - response_obj = JSON.parse(response.body) - expect(response_obj["name"]).to eq "#{media.name}" - expect(response_obj["taxon"]).not_to eq "BreakingTaxon" - end - end - end - - describe 'DELETE /media/:id' do - - xit 'should delete media' do - media = create(:media, user: user) - expect{ delete "/api/v1/media/#{media.id}" }.to change(Media, :count).by(-1) - expect(response).to be_success - end - - xit 'should NOT delete non-existent media' do - media = create(:media, user: user) - expect{ delete "/api/v1/media/#{media.id+1}" }.to_not change(Media, :count) - expect(response).not_to be_success - end - - xit 'should not delete consumed media' do - media = create(:media, user: user) - post = create(:post, user: user) - post.featured_media = media - post.save - expect { delete "/api/v1/media/#{media.id}" }.to_not change(Media, :count) - expect(Media.exists? media.id).to be_truthy - expect(response.status).to eq(409) - end - end - after do - Media.__elasticsearch__.client.indices.delete index: Media.index_name - end -end diff --git a/spec/api/v1/resources/posts_spec.rb b/spec/api/v1/resources/posts_spec.rb deleted file mode 100644 index 0e450f753..000000000 --- a/spec/api/v1/resources/posts_spec.rb +++ /dev/null @@ -1,282 +0,0 @@ -describe SPEC_API::Resources::Posts, type: :request do - - let(:user) { create(:user, :admin) } - let(:author) { create(:author) } - - before(:each) do - login_as user - Post.__elasticsearch__.create_index! index: Post.index_name - end - - describe 'GET /posts' do - - before(:each) do - 5.times { create(:post, user: user) } - create(:post, title: "Test Post for testing queries.", user: user) - Post.import({refresh: true}) - end - - it 'should return all posts' do - get '/api/v1/posts' - expect(response).to be_success - expect(JSON.parse(response.body).count).to eq ::Post.find_by_tenant_id(user.tenant.id).count - end - - it 'should return paginated results' do - get '/api/v1/posts?per_page=2' - expect(response).to be_success - expect(JSON.parse(response.body).count).to eq(2) - expect(response.headers['X-Total'].to_i).to eq ::Post.find_by_tenant_id(user.tenant.id).count - end - - it 'should allow search on q' do - get '/api/v1/posts?q=queries' - expect(response).to be_success - expect(JSON.parse(response.body).count).to eq(1) - end - end - - describe 'GET /posts/feed' do - - before(:each) do - Post.connection - Post.__elasticsearch__.create_index! index: Post.index_name, force: true - @industry_1 = create(:onet_occupation, soc: '12-0000') - @industry_2 = create(:onet_occupation, soc: '13-0000') - @industry_3 = create(:onet_occupation) - @category_1 = create(:category) - @category_2 = create(:category) - @post_1 = create(:post, type: "VideoPost", job_phase: "Get the Job", user: user) - @post_1.industries << @industry_1 - @post_1.categories << @category_1 - @post_2 = create(:post, job_phase: "On the Job", user: user) - @post_2.industries << @industry_2 - @post_2.categories << @category_2 - @post_3 = create(:post, type: "PromoPost", user: user) - @post_3.industries << @industry_1 - @post_4 = create(:post, type: "VideoPost", job_phase: "Get the Job", user: user) - @post_4.industries << @industry_3 - Post.import({refresh: true}) - end - - context 'filtering test' do - it 'should filter on industry and include results for All Industries' do - get '/api/v1/posts/feed?industries=13-0000,12-0000' - expect(response).to be_success - expect(JSON.parse(response.body).count).to eq(3) - end - - it 'should filter on category' do - get "/api/v1/posts/feed?categories=#{@category_1.name},#{@category_2.name}" - expect(response).to be_success - expect(JSON.parse(response.body).count).to eq(2) - end - - it 'should filter on post types' do - get "/api/v1/posts/feed?post_type=VideoPost,PromoPost" - expect(response).to be_success - expect(JSON.parse(response.body).count).to eq(3) - end - - it 'should filter on job phase' do - get "/api/v1/posts/feed?job_phase=Get%20the%20Job,On%20the%20Job" - expect(response).to be_success - expect(JSON.parse(response.body).count).to eq(3) - end - - it 'should filter on multiple criteria' do - get "/api/v1/posts/feed?industries=13-0000,12-0000&post_type=VideoPost&job_phase=Get%20the%20Job&categories=#{@category_1.name},#{@category_2.name}" - expect(response).to be_success - expect(JSON.parse(response.body).count).to eq(1) - end - end - end - - describe 'GET /posts/feed/:id' do - - it 'should return the correct post' do - post = create(:post, user: user) - get "/api/v1/posts/feed/#{post.id}" - expect(response).to be_success - expect(response.body).to represent(SPEC_API::Entities::Post, post, { full: true }) - end - - it 'should not show unpublished posts' do - post = create(:post, draft: true) - get "/api/v1/posts/feed/#{post.id}" - expect(response.status.to_i).to eq(404) - end - end - - describe 'GET /posts/:id' do - - it 'should return the correct post' do - post = create(:post, user: user) - get "/api/v1/posts/#{post.id}" - expect(response).to be_success - expect(response.body).to represent(SPEC_API::Entities::Post, post, { full: true }) - end - - it 'should return unpublished posts' do - post = create(:post, draft: true, user: user) - get "/api/v1/posts/#{post.id}" - expect(response).to be_success - expect(response.body).to represent(SPEC_API::Entities::Post, post, { full: true }) - end - end - - describe 'POST /posts' do - - context 'with valid attributes' do - it 'should create a new post' do - valid_post = attributes_for(:post, author_id: author.id) - expect{ post '/api/v1/posts', valid_post }.to change(Post, :count).by(1) - expect(response).to be_success - expect(response.body).to represent(SPEC_API::Entities::Post, Post.last, { full: true }) - end - end - - context 'with invalid attributes' do - it 'should NOT create a new post' do - expect{ post '/api/v1/posts', attributes_for(:post, title: nil) }.to_not change(Post, :count) - expect(response).not_to be_success - end - end - - context 'with featured media' do - xit 'should create a new post' do - with_media_post = build(:post, :with_featured_media, author_id: author.id).to_json - expect{ post '/api/v1/posts', with_media_post, application_json }.to change(Post, :count).by(1) - expect(response).to be_success - expect(response.body).to represent(SPEC_API::Entities::Post, Post.last, { full: true }) - end - - # This is broken because the post.to_json does not generate valid JSON for the API to consume - xit 'should include the featured media in associated media' do - post = build(:post, :with_featured_media, author_id: author.id) - post '/api/v1/posts', post.to_json, application_json - expect(Post.last.media).to include(post.featured_media) - end - end - - context 'for a promo post' do - it 'should create a new promo' do - promo_post = attributes_for(:post, type: 'PromoPost', destination_url: "Not null", - call_to_action: "Defined", author_id: author.id) - - expect{ post '/api/v1/posts', promo_post }.to change(Post, :count).by(1) - expect(response).to be_success - expect(response.body).to represent(SPEC_API::Entities::Post, Post.last, { full: true }) - end - it 'should require featured_url and call_to_action' do - promo_post = attributes_for(:post, type: 'PromoPost', author_id: author.id) - expect{ post '/api/v1/posts', promo_post }.to_not change(Post, :count) - expect(response).not_to be_success - end - end - end - - describe 'PUT /posts/:id' do - - context 'with valid attributes' do - it 'should update the post', skip: true do - post = create(:post, user: user) - post.title += ' updated' - expect{ put "/api/v1/posts/#{post.id}", post.to_json, application_json }.to_not change(Post, :count) - expect(response).to be_success - expect(response.body).to represent(SPEC_API::Entities::Post, post, { full: true }) - end - end - - context 'with invalid attributes' do - it 'should NOT update the post', skip: true do - post = create(:post, user: user) - expect{ put "/api/v1/posts/#{post.id}", {title: nil}.to_json, application_json }.to_not change(Post, :count) - expect(response).not_to be_success - end - end - - context 'for a promo post' do - it 'should update the post with valid attributes', skip: true do - post = create(:promo, user: user) - post.destination_url = "http://www.example.com" - expect{ put "/api/v1/posts/#{post.id}", {destination_url: "http://www.example.com"}.to_json, application_json }.to_not change(Post, :count) - expect(response).to be_success - expect(response.body).to represent(SPEC_API::Entities::Post, post, { full: true }) - end - - it 'should not update the post with invalid attributes' do - post = create(:promo, user: user) - expect{ put "/api/v1/posts/#{post.id}", {destination_url: nil}.to_json, application_json }.to_not change(Post, :count) - expect(response).not_to be_success - end - - it 'should support updating from article to promo' do - post = create(:post, user: user) - expect{ put "/api/v1/posts/#{post.id}", {type: 'PromoPost', destination_url: "Example.com", call_to_action: "Click here"}.to_json, application_json}.to_not change(Post, :count) - expect(response).to be_success - end - end - - context 'with featured media' do - xit 'should update the post' do - post = create(:post, :with_featured_media, user: user) - post.title += ' updated' - expect{ put "/api/v1/posts/#{post.id}", post.to_json, application_json }.to_not change(Post, :count) - expect(response).to be_success - expect(response.body).to represent(SPEC_API::Entities::Post, post, { full: true }) - end - - # This is broken because the post.to_json does not generate valid JSON for the API to consume - xit 'should include the featured media in associated media' do - post = create(:post, :with_featured_media, user: user) - post.featured_media = build(:post, :with_featured_media).featured_media - expect{ put "/api/v1/posts/#{post.id}", post.to_json, application_json }.to_not change(Post, :count) - expect(Post.find(post.id).media).to include(post.featured_media) - end - end - end - - describe 'DELETE /posts/:id' do - - it 'should delete the post' do - post = create(:post, user: user) - expect{ delete "/api/v1/posts/#{post.id}" }.to change(Post, :count).by(-1) - expect(response).to be_success - end - - it 'should NOT delete a non-existent post' do - post = create(:post, user: user) - expect{ delete "/api/v1/posts/#{post.id+1}" }.to_not change(Post, :count) - expect(response).not_to be_success - end - end - - describe 'GET /posts/filter' do - - before do - category_1 = create(:category) - category_2 = create(:category, parent: category_1) - end - - it 'should default to only categories with a depth of 1 or higher' do - categories = Array(Category.where('depth >= 1')) - get '/api/v1/posts/filters' - expect(response).to be_success - json = JSON.parse(response.body) - expect(Array(json['categories']).count).to eq(categories.count) - end - - it 'should allow depth selection' do - categories = Category.all - get '/api/v1/posts/filters?depth=0' - expect(response).to be_success - json = JSON.parse(response.body) - expect(Array(json['categories']).count).to eq(categories.count) - end - end - - after do - Post.__elasticsearch__.client.indices.delete index: Post.index_name - end -end diff --git a/spec/api/v1/resources/tenants_spec.rb b/spec/api/v1/resources/tenants_spec.rb deleted file mode 100644 index dcfc51ec3..000000000 --- a/spec/api/v1/resources/tenants_spec.rb +++ /dev/null @@ -1,73 +0,0 @@ -describe SPEC_API::Resources::Tenants, :type => :request do - - let(:user) { create(:user, :admin) } - - before do - login_as user - end - - describe 'GET /tenants/:id' do - - let(:tenant) { create(:tenant) } - - it 'should return the correct tenant' do - get "/api/v1/tenants/#{tenant.id}" - expect(response).to be_success - expect(response.body).to represent(SPEC_API::Entities::Tenant, tenant) - end - end - - describe 'POST /tenants' do - - context 'with valid attributes' do - it 'should create a new tenant' do - expect{ post '/api/v1/tenants', attributes_for(:tenant) }.to change(Tenant, :count).by(1) - expect(response).to be_success - expect(response.body).to represent(SPEC_API::Entities::Tenant, Tenant.last) - end - end - - context 'with invalid attributes' do - it 'should NOT create a new tenant' do - expect{ post '/api/v1/tenants', attributes_for(:tenant, name: nil) }.to_not change(Tenant, :count) - expect(response).not_to be_success - end - end - end - - describe 'PUT /tenants/:id' do - - context 'with valid attributes' do - it 'should update the tenant' do - tenant = create(:tenant) - tenant.name += ' updated' - expect{ put "/api/v1/tenants/#{tenant.id}", tenant.to_json, application_json }.to_not change(Tenant, :count) - expect(response).to be_success - expect(response.body).to represent(SPEC_API::Entities::Tenant, tenant) - end - end - - context 'with invalid attributes' do - it 'should NOT update the tenant' do - tenant = create(:tenant) - expect{ put "/api/v1/tenants/#{tenant.id}", {name: nil}.to_json, application_json }.to_not change(Tenant, :count) - expect(response).not_to be_success - end - end - end - - describe 'DELETE /tenants/:id' do - - it 'should delete the tenant' do - tenant = create(:tenant) - expect{ delete "/api/v1/tenants/#{tenant.id}" }.to change(Tenant, :count).by(-1) - expect(response).to be_success - end - - it 'should NOT delete a non-existent tenant' do - tenant = create(:tenant) - expect{ delete "/api/v1/tenants/#{tenant.id+1}" }.to_not change(Tenant, :count) - expect(response).not_to be_success - end - end -end diff --git a/spec/api/v1/resources/users_spec.rb b/spec/api/v1/resources/users_spec.rb deleted file mode 100644 index fdbfdba1c..000000000 --- a/spec/api/v1/resources/users_spec.rb +++ /dev/null @@ -1,66 +0,0 @@ -describe SPEC_API::Resources::Users, :type => :request do - describe 'GET /users/me' do - let(:user) { create(:user) } - - it 'should get the current user if authorized' do - login_as user - get '/api/v1/users/me' - expect(response).to be_success - expect(response.body).to represent(SPEC_API::Entities::User, user, { full: true }) - end - - it 'should NOT get the current user if unauthorized' do - get '/api/v1/users/me' - expect(response.status).to eq(401) - end - end - - describe 'PUT /users/:user_id' do - let(:user) { create(:user, password: 'TestPassword') } - let(:admin_user) { create(:user, :admin) } - let(:other_user) { create(:user) } - - context 'as the target user' do - before :each do - login_as user - end - - it 'should reject if the current password is incorrect' do - put "/api/v1/users/#{user.id}", {current_password: 'WrongPassword', password: 'NewPassword', password_confirmation: 'NewPassword'} - expect(response.status).to eq(403) - end - - it 'should reject if the passwords don\'t match' do - put "/api/v1/users/#{user.id}", {current_password: 'TestPassword', password: 'NewPassword', password_confirmation: 'Different Password'} - expect(response.status).to eq(422) - end - - it 'should change the password when all is correct' do - put "/api/v1/users/#{user.id}", {current_password: 'TestPassword', password: 'NewPassword', password_confirmation: 'NewPassword'} - expect(response).to be_success - end - end - - context 'as a different user' do - before :each do - login_as other_user - end - - it 'should reject in all cases' do - put "/api/v1/users/#{user.id}", {current_password: 'TestPassword', password: 'NewPassword', password_confirmation: 'NewPassword'} - expect(response.status).to eq(403) - end - end - - context 'as an admin' do - before :each do - login_as admin_user - end - - it 'should succeed but not change password of other user' do - put "/api/v1/users/#{user.id}", {current_password: 'TestPassword', password: 'NewPassword', password_confirmation: 'NewPassword'} - expect(response).to be_success - end - end - end -end diff --git a/spec/api_v1_helper.rb b/spec/api_v1_helper.rb deleted file mode 100644 index 1cb1de891..000000000 --- a/spec/api_v1_helper.rb +++ /dev/null @@ -1,10 +0,0 @@ -SPEC_API = ::V1 - -def represent(entity, obj, opts = {}) - obj_json = obj.kind_of?(Array) ? obj.map{ |v| entity.new(v, opts).to_json }.to_json : entity.new(obj, opts).to_json - be_json_eql(obj_json) -end - -def application_json - {:CONTENT_TYPE => 'application/json'} -end diff --git a/spec/factories/author.rb b/spec/factories/author.rb deleted file mode 100644 index 1a5f429c8..000000000 --- a/spec/factories/author.rb +++ /dev/null @@ -1,6 +0,0 @@ -FactoryGirl.define do - factory :author do - firstname 'author' - sequence(:lastname) { |n| "#{n}" } - end -end diff --git a/spec/factories/bulk_job.rb b/spec/factories/bulk_job.rb deleted file mode 100644 index a6674b080..000000000 --- a/spec/factories/bulk_job.rb +++ /dev/null @@ -1,7 +0,0 @@ -FactoryGirl.define do - factory :bulk_job do - content_type "Test" - metadata_file_name "File name" - metadata_updated_at DateTime.now - end -end diff --git a/spec/factories/category.rb b/spec/factories/category.rb deleted file mode 100644 index 0ac7cdf92..000000000 --- a/spec/factories/category.rb +++ /dev/null @@ -1,6 +0,0 @@ -FactoryGirl.define do - factory :category do - sequence(:name) { |n| "category#{n}" } - user - end -end \ No newline at end of file diff --git a/spec/factories/document.rb b/spec/factories/document.rb deleted file mode 100644 index 39768fe13..000000000 --- a/spec/factories/document.rb +++ /dev/null @@ -1,7 +0,0 @@ -FactoryGirl.define do - factory :document do - user - sequence(:name) { |n| "Document#{n}" } - body 'I am to cool for my socks' - end -end diff --git a/spec/factories/media.rb b/spec/factories/media.rb deleted file mode 100644 index 9d926ddc7..000000000 --- a/spec/factories/media.rb +++ /dev/null @@ -1,22 +0,0 @@ -include ActionDispatch::TestProcess - -FactoryGirl.define do - factory :media do - user - tag_list [] - sequence(:name) { |n| "Media#{n}" } - attachment { fixture_file_upload("#{Rails.root}/spec/support/media/test.txt", 'text/plain') } - - trait :document do - attachment { fixture_file_upload("#{Rails.root}/spec/support/media/test.pdf", 'application/pdf') } - end - - trait :movie do - attachment { fixture_file_upload("#{Rails.root}/spec/support/media/test.mp4", 'video/mp4') } - end - - trait :image do - attachment { fixture_file_upload("#{Rails.root}/spec/support/media/test.jpg", 'image/jpeg') } - end - end -end diff --git a/spec/factories/onet_occupation.rb b/spec/factories/onet_occupation.rb deleted file mode 100644 index d6e360594..000000000 --- a/spec/factories/onet_occupation.rb +++ /dev/null @@ -1,21 +0,0 @@ -# == Schema Information -# -# Table name: onet_occupations -# -# id :integer not null, primary key -# soc :string(255) -# title :string(255) -# description :text -# created_at :datetime -# updated_at :datetime -# - -# Read about factories at https://github.com/thoughtbot/factory_girl - -FactoryGirl.define do - factory :onet_occupation, :class => 'Onet::Occupation' do - soc '11-1011.00' - title 'Chief Executives' - description 'Determine and formulate policies and provide overall direction of companies or private and public sector organizations within guidelines set up by a board of directors or similar governing body. Plan, direct, or coordinate operational activities at the highest level of management with the help of subordinate executives and staff managers.' - end -end diff --git a/spec/factories/post.rb b/spec/factories/post.rb deleted file mode 100644 index 26c9e9f55..000000000 --- a/spec/factories/post.rb +++ /dev/null @@ -1,44 +0,0 @@ -FactoryGirl.define do - factory :post, class: 'ArticlePost' do - sequence(:title) { |n| "post#{n}" } - sequence(:slug) { |n| "post-#{n}" } - short_description 'This is a short description of the post that is long enough' - body '

Test paragraph text

' - copyright_owner :'CareerBuilder, LLC' - job_phase :Discovery - display :large - type 'ArticlePost' - draft false - published_at DateTime.now - industries [] - primary_industry_id 1 - categories [] - primary_category_id 1 - author - user - - trait :with_featured_media do - association :featured_media, factory: [:media, :image] - end - end - - factory :promo, class: 'PromoPost' do - sequence(:title) { |n| "post#{n}" } - sequence(:slug) { |n| "post-#{n}" } - short_description 'This is a short description of the post that is long enough' - copyright_owner :'CareerBuilder, LLC' - job_phase :Discovery - display :large - type 'PromoPost' - draft false - published_at DateTime.now - industries [] - primary_industry_id 1 - categories [] - primary_category_id 1 - destination_url 'Example.com' - call_to_action 'Click me' - author - user - end -end diff --git a/spec/factories/snippet.rb b/spec/factories/snippet.rb deleted file mode 100644 index 53d27a9bb..000000000 --- a/spec/factories/snippet.rb +++ /dev/null @@ -1,8 +0,0 @@ -FactoryGirl.define do - factory :snippet do - webpage - document - user - end - -end diff --git a/spec/factories/webpage.rb b/spec/factories/webpage.rb deleted file mode 100644 index 145601b50..000000000 --- a/spec/factories/webpage.rb +++ /dev/null @@ -1,6 +0,0 @@ -FactoryGirl.define do - factory :webpage do - user_id 1 - end - -end diff --git a/spec/javascripts/controllers/media/edit_spec.js b/spec/javascripts/controllers/media/edit_spec.js deleted file mode 100644 index 24c8acc0d..000000000 --- a/spec/javascripts/controllers/media/edit_spec.js +++ /dev/null @@ -1,86 +0,0 @@ -//= require spec_helper - -(function() { - 'use strict'; - - describe('Media Edit Module', function() { - - beforeEach(function() { - debaser() - .module('cortex.controllers.media.edit') - .object('settings', {}) - .object('$state').withFunc('go').returnsArg(0) - .withFunc('cortex').returns(sinon.stub()) - .object('$upload').withFunc('upload').fulfills(true) - .debase(); - }); - - describe('MediaEditCtrl', function() { - var constructController; - - beforeEach(inject(function($controller) { - constructController = function() { - return $controller('MediaEditCtrl', { }); - }; - })); - - it('should construct', function() { - var controller = constructController(); - expect(controller).toBeTruthy(); - }); - - it('should provide data.media', function() { - var controller = constructController(); - expect(controller.data.media).toBeDefined(); - }); - - it('should allow the tab to be selected', function() { - var controller = constructController(); - expect(controller.selectTab).toBeDefined(); - expect(controller.selectTab).toEqual(jasmine.any(Function)); - controller.selectTab('file'); - expect(controller.currentTab).toBe('file'); - }); - - it('should provide a cancel function', inject(function($state) { - var controller = constructController(); - expect(controller.cancel).toBeDefined(); - expect(controller.cancel).toEqual(jasmine.any(Function)); - controller.cancel(); - expect($state.go.calledWith('^.manage.components')).toBeTruthy(); - })); - - it('should provide a saveMedia function', function() { - var controller = constructController(); - expect(controller.saveMedia).toBeDefined(); - expect(controller.saveMedia).toEqual(jasmine.any(Function)); - }); - - it('should save youtube', function() { - var controller = constructController(); - sinon.stub(controller.data.media, '$save').fulfills({}); - angular.extend(controller.data.media, {$youtube: '1234', name: 'Youtube video'}); - controller.selectTab('youtube'); - controller.saveMedia(); - expect(controller.data.media.$save.called).toBeTruthy(); - }); - - it('should upload files', inject(function($upload) { - var controller = constructController(); - controller.selectTab('file'); - controller.data.media.$file = {name: 'file'}; - angular.extend(controller.data.media, {name: 'File', attachment: true}); - controller.saveMedia(); - expect($upload.upload.called).toBeTruthy(); - })); - - it('should add a tag', inject(function(cortex) { - var controller = constructController(); - var tag = {name: "Test Tag", id: 1}; - controller.addTag(tag); - expect(controller.data.media.tag_list).toContain(tag); - })); - - }); - }); -})(); diff --git a/spec/javascripts/controllers/media/grid_spec.js b/spec/javascripts/controllers/media/grid_spec.js deleted file mode 100644 index ad7128245..000000000 --- a/spec/javascripts/controllers/media/grid_spec.js +++ /dev/null @@ -1,107 +0,0 @@ -//= require spec_helper - -(function() { - 'use strict'; - - describe('Media Grid Module', function() { - - beforeEach(function() { - var media = [{id: 1}, {id: 2}]; - var searchPaged = function(args, successFn) { - var paging = {per_page: 10, page: 1}; - if (args) { - paging = angular.extend(paging, args); - } - - if (successFn) { - successFn(media, {}, paging); - } - - return media; - }; - debaser() - .module('cortex.controllers.media.grid') - .object('settings', { paging: { defaultPerPage: 10 } } ) - .object('$stateParams', { query: '', page: 1 } ) - .object('$state').withFunc('go').returns(true) - .object('media', media) - .object('mediaSelectType', {}) - .object('$window').withFunc('confirm').returns(true) - .object('cortex', { media: { delete: function(a, s) { s() }, searchPaged: searchPaged } } ) - .object('PostsPopupService', { popupOpen: false } ) - .object('mediaSelectType', { }) - .object('PostBodyEditorService', { }) - .debase(); - }); - - describe('MediaGridCtrl', function() { - var constructController; - - beforeEach(inject(function($controller) { - - constructController = function() { - return $controller('MediaGridCtrl', {}); - }; - })); - - it('should construct', function() { - var controller = constructController(); - expect(controller).toBeTruthy(); - }); - - describe('$scope.page', function() { - - it('should provide query', inject(function($stateParams) { - $stateParams.query = 'query'; - var controller = constructController(); - expect(controller.page.query).toEqual('query'); - })); - - it('should use $stateParams.page if available', inject(function($stateParams) { - $stateParams.page = 2; - var controller = constructController(); - expect(controller.page.page).toEqual(2); - })); - - it('should provide default page', function() { - var controller = constructController(); - expect(controller.page.page).toEqual(1); - }); - - it('should provide default perPage', function() { - var controller = constructController(); - expect(controller.page.perPage).toEqual(10); - }); - - it('should use $stateParams.perPage if available', inject(function($stateParams) { - $stateParams.perPage = 23; - var controller = constructController(); - expect(controller.page.perPage).toEqual(23); - })); - - it('should provide next()', function() { - var controller = constructController(); - controller.page.next(); - expect(controller.page.page).toEqual(2); - }); - - it('should provide previous()', function() { - var controller = constructController(); - controller.page.previous(); - expect(controller.page.page).toEqual(0); - }); - }); - - it('should provide data.media', function() { - var controller = constructController(); - expect(controller.data.media.length).toEqual(2); - }); - - it('should provide deleteMedia()', function() { - var controller = constructController(); - controller.deleteMedia({id: 1}); - expect(controller.data.media).not.toContain({id: 1}); - }); - }); - }); -})(); diff --git a/spec/javascripts/controllers/posts/edit_spec.js b/spec/javascripts/controllers/posts/edit_spec.js deleted file mode 100644 index 462fec20d..000000000 --- a/spec/javascripts/controllers/posts/edit_spec.js +++ /dev/null @@ -1,69 +0,0 @@ -//= require spec_helper - -(function() { - 'use strict'; - - describe('Post Editor Module', function() { - beforeEach(function() { - debaser() - .module('cortex.controllers.posts.edit') - .object('AddMediaService').withFunc('initRedactorMediaPlugin').returns({ }) - .object('ImageFitService').withFunc('initRedactorImageFitPlugin').returns({ }) - .object('currentUserAuthor', { full_name: "Test User"}) - .object('filters', { job_phases: [], industries: [] }) - .object('$state', { go: function() { return { } }, includes: function() { return true } } ) - .object('mediaSelectType', { }) - .object('post', { }) - .object('categoriesHierarchy', { }) - .debase() - }); - - describe('PostsEditCtrl', function() { - var constructController; - beforeEach(inject(function($controller) { - constructController = function() { - return $controller('PostsEditCtrl', {}); - }; - })); - - it('should construct', function() { - var controller = constructController(); - expect(controller).toBeTruthy(); - }); - - it('should provide data.industries on scope', function() { - var controller = constructController(); - expect(controller.data.industries).toBeDefined(); - }); - - it('should provide data.post on scope', function() { - var controller = constructController(); - expect(controller.data.post).toBeDefined(); - }); - - it('should provide data.categoriesHierarchy on scope', function() { - var controller = constructController(); - expect(controller.data.categoriesHierarchy).toBeDefined(); - }); - - it('should set data.authorIsUser to true if creating a new post', function() { - var controller = constructController(); - expect(controller.data.authorIsUser).toBeTruthy(); - }); - - it('should set data.authorIsUser to true if editing a post that has an author', function() { - var controller = constructController(); - controller.data.post.author = { id: 1, first_name: "Calvin" }; - controller.data.post.id = 1; - expect(controller.isAuthorUser(controller.data.post)).toBeTruthy(); - }); - - it('should not set data.authorIsUser if editing a post that has a custom author', function() { - var controller = constructController(); - controller.data.post.custom_author = "Hobbes"; - controller.data.post.id = 1; - expect(controller.isAuthorUser(controller.data.post)).toBeFalsy(); - }); - }); - }); -})(); diff --git a/spec/javascripts/controllers/posts/grid_spec.js b/spec/javascripts/controllers/posts/grid_spec.js deleted file mode 100644 index dd45c1d42..000000000 --- a/spec/javascripts/controllers/posts/grid_spec.js +++ /dev/null @@ -1,29 +0,0 @@ -//= require spec_helper - -(function() { - 'use strict'; - - describe("Post Grid Module", function() { - beforeEach(function() { - debaser() - .module('cortex.controllers.posts.grid') - .object('cortex', {}) - .func('ngTableParams').returns({}) - .debase() - }); - - describe('PostsGridCtrl', function() { - var constructController; - beforeEach(inject(function($controller) { - constructController = function() { - return $controller('PostsGridCtrl'); - }; - })); - - it('should construct', function() { - var controller = constructController(); - expect(controller).toBeTruthy(); - }); - }); - }); -})(); \ No newline at end of file diff --git a/spec/javascripts/controllers/users/edit_spec.js b/spec/javascripts/controllers/users/edit_spec.js deleted file mode 100644 index a82fa9fc4..000000000 --- a/spec/javascripts/controllers/users/edit_spec.js +++ /dev/null @@ -1,40 +0,0 @@ -//= require spec_helper - -(function() { - 'use strict'; - - describe('User Profile Module', function() { - beforeEach(function() { - debaser() - .module('cortex.controllers.users.profile') - .object('$scope', {}) - .object('user', {}) - .object('author').withFunc('$save').fulfills({}) - .debase(); - }); - - describe('UsersProfileCtrl', function() { - var constructController; - - beforeEach(inject(function($controller) { - constructController = function() { - return $controller('UsersProfileCtrl', {}); - }; - })); - - it('should construct', function() { - var controller = constructController(); - expect(controller).toBeTruthy(); - }); - - it('should save an author', function() { - var controller = constructController(); - controller.saveAuthor(); - expect(controller.data.author.$save.called).toBeTruthy(); - }); - - }); - - }); - -})(); diff --git a/spec/javascripts/cortex_spec.js b/spec/javascripts/cortex_spec.js deleted file mode 100644 index 3af3e5d8b..000000000 --- a/spec/javascripts/cortex_spec.js +++ /dev/null @@ -1,47 +0,0 @@ -//= require spec_helper - -(function() { - 'use strict'; - - describe('Cortex Module', function() { - - beforeEach(function() { - angular.mock.module('cortex'); - }); - - describe('CortexCtrl', function() { - var controller, $rootScope, $state, $stateParams, moment, currentUser; - - beforeEach(inject(function(_$rootScope_, _$state_, $controller, _$stateParams_, $http, - $window, _currentUser_, _moment_) { - $rootScope = _$rootScope_; - $state = _$state_; - $stateParams = _$stateParams_; - moment = _moment_; - currentUser = _currentUser_; - - controller = $controller('CortexCtrl', { - $rootScope: $rootScope, - $scope: $rootScope.$new(), - $state: $state, - $stateParams: $stateParams, - $http: $http, - $window: $window, - currentUser: currentUser, - moment: moment - }); - })); - - it('should construct', function() { - expect(controller).toBeTruthy(); - }); - - it('should add necessary properties to $rootScope', function() { - expect($rootScope.$state).toEqual($state); - expect($rootScope.$stateParams).toEqual($stateParams); - expect($rootScope.currentUser).toEqual(currentUser); - expect($rootScope.moment).toEqual(moment); - }); - }); - }); -})(); diff --git a/spec/javascripts/directives/file-selector_spec.js b/spec/javascripts/directives/file-selector_spec.js deleted file mode 100644 index 4f2c30c1b..000000000 --- a/spec/javascripts/directives/file-selector_spec.js +++ /dev/null @@ -1,79 +0,0 @@ -(function() { - 'use strict'; - - describe('file-selector directive', function() { - var $scope, createDirective; - - beforeEach(function() { - module('cortex.directives.fileSelector'); - module('cortex.templates'); - }); - - beforeEach(inject(function($compile, $rootScope) { - $scope = $rootScope.$new(); - - createDirective = function(multiple) { - if (multiple === undefined) { - multiple = false; - } - $scope.multiple = multiple; - var elem = angular.element(''); - $compile(elem)($scope); - $scope.$digest(); - return elem; - }; - })); - - it('should browse for files when the dropzone is clicked', function() { - var elem = createDirective(false); - var dropzone = elem.find('.dropzone'); - var openFileDialogOpened = false; - - dropzone.scope().browseForFiles = function() { - openFileDialogOpened = true; - }; - elem.find('.dropzone').trigger('click'); - - expect(openFileDialogOpened).toBe(true); - }); - - describe('when multiple=false', function() { - var elem; - - beforeEach(function() { - elem = createDirective(false); - }); - - it('should NOT allow multiple files to be selected', function() { - var multiple = elem.find('input[type="file"][multiple]'); - expect(multiple.size()).toBe(0); - }); - }); - - describe('when multiple=true', function() { - var elem; - - beforeEach(function() { - elem = createDirective(true); - }); - - it('should allow multiple files to be selected', function() { - var multiple = elem.find('input[type="file"][multiple]'); - expect(multiple.size()).toBe(1); - }); - }); - - it('should remove files when they are clicked', function() { - var file = {name: 'hilarious_meme.jpg'}; - var elem = createDirective(); - // Grab a random child element to fetch the isolate scope - var directiveScope = elem.find('div').scope(); - directiveScope.files = [file, {name: 'foo.png'}]; - - directiveScope.remove(file); - expect(directiveScope.files).not.toContain(file); - }); - - it('should add a file dropped into the dropzone'); - }); -})(); diff --git a/spec/javascripts/directives/youtube-selector_spec.js b/spec/javascripts/directives/youtube-selector_spec.js deleted file mode 100644 index c060a243b..000000000 --- a/spec/javascripts/directives/youtube-selector_spec.js +++ /dev/null @@ -1,55 +0,0 @@ -(function() { - 'use strict'; - - describe('youtube-selector directive', function() { - var elem, $scope; - - beforeEach(function() { - module('cortex.directives.youtubeSelector'); - module('cortex.templates'); - }); - - beforeEach(inject(function($compile, $rootScope) { - $scope = $rootScope.$new(); - elem = angular.element(''); - $compile(elem)($scope); - $scope.$digest(); - })); - - describe('with a valid YouTube URL', function() { - var VALID_CODE = 'aBOzOVLxbCE'; - - beforeEach(function() { - var input = elem.find('input'); - input.val('http://www.youtube.com/watch?v=' + VALID_CODE); - input.trigger('input'); - }); - - it('should update ng-model', function() { - expect($scope.youtube).toBe(VALID_CODE); - }); - - it('should embed the video', function() { - expect(elem.find('iframe').attr('src')).toBe('http://www.youtube.com/embed/' + VALID_CODE); - }); - }); - - describe('with an invalid YouTube URL', function() { - var INVALID_CODE = 'xyz'; - - beforeEach(function() { - var input = elem.find('input'); - input.val('http://www.youtube.com/watch?v=' + INVALID_CODE); - input.trigger('input'); - }); - - it('should NOT update ng-model', function() { - expect($scope.youtube).toBe(null); - }); - - it('should NOT embed the video', function() { - expect(elem.find('iframe').size()).toBe(0); - }); - }); - }); -})(); diff --git a/spec/javascripts/helpers/mock.js b/spec/javascripts/helpers/mock.js deleted file mode 100644 index 14753a525..000000000 --- a/spec/javascripts/helpers/mock.js +++ /dev/null @@ -1,54 +0,0 @@ -mock = (function() { - 'use strict'; - - // A primitive mock factory, returns a function that accepts an object to override properties - // - // Example mock construction: - // var userMock = factory({name: 'Fred', id: 1}); - // - // Example mock use: - // var fred = userMock(); // returns {name: 'Fred', id: 1} - // var jackie = userMock({name: 'Jackie', id: 2}); // returns {name: 'Jackie', id: 2} - var factory = function(defaultMock) { - return function(properties) { - var mock = angular.copy(defaultMock); - if (typeof(properties) === 'Object') { - for (var k in properties) { - defaultMock[k] = properties[k]; - } - } - return mock; - } - }; - - var basicGon = { - current_user: null, - settings: { - cortex_base_url: '', - paging: { - defaultPerPage: 10 - } - } - }; - - var basicMedia = { - id: 1, - name: 'Media', - alt: 'Media', - dimensions: [800, 600], - type: 'Media', - thumbs: { - default: "default.jpg", - large: "large.jpg", - micro: "micro.jpg", - mini: "mini.jpg" - }, - tag_list: [] - }; - - return { - gon: factory(basicGon), - media: factory(basicMedia) - }; - -})(); diff --git a/spec/javascripts/helpers/window_helper.js b/spec/javascripts/helpers/window_helper.js deleted file mode 100644 index 4199d41de..000000000 --- a/spec/javascripts/helpers/window_helper.js +++ /dev/null @@ -1,5 +0,0 @@ -(function() { - beforeEach(function() { - window.gon = mock.gon(); - }); -})(); diff --git a/spec/javascripts/services/cortex_spec.js b/spec/javascripts/services/cortex_spec.js deleted file mode 100644 index c6eb02808..000000000 --- a/spec/javascripts/services/cortex_spec.js +++ /dev/null @@ -1,60 +0,0 @@ -//= require helpers/window_helper - -(function () { - 'use strict'; - - describe("Cortex Service", function () { - beforeEach(function () { - angular.mock.module('cortex.services.cortex'); - }); - - describe("Cortex factory", function () { - var $httpBackend, cortexResource; - beforeEach(function () { - - inject(function ($injector) { - $httpBackend = $injector.get('$httpBackend'); - cortexResource = $injector.get('cortex'); - }); - - }); - - it("should have a posts object.", function () { - expect(cortexResource.posts).toBeDefined(); - }); - - it("should recognize paginated responses.", function () { - $httpBackend.expectGET('/posts/feed?page=1').respond([], {'X-Total': '84'}); - cortexResource.posts.feedPaged({'page': 1}); - $httpBackend.flush(); - }); - - it("should have a filters request.", function () { - $httpBackend.expectGET('/posts/filters').respond({}); - cortexResource.posts.filters(); - $httpBackend.flush(); - }); - - xit("should have a related request.", function () { - $httpBackend.expectGET('/posts/feed/1/related').respond([ - {} - ]); - cortexResource.posts.related({id: 1}); - $httpBackend.flush(); - }); - - it("should have a users object.", function () { - expect(cortexResource.users).toBeDefined(); - }); - - it("should be able to make a request to user.me.", function () { - $httpBackend.expectGET('/users/me').respond({}); - cortexResource.users.me(); - $httpBackend.flush(); - }); - - }); - - }); - -})(); diff --git a/spec/javascripts/services/media-constraints_spec.js b/spec/javascripts/services/media-constraints_spec.js deleted file mode 100644 index c33cef632..000000000 --- a/spec/javascripts/services/media-constraints_spec.js +++ /dev/null @@ -1,95 +0,0 @@ -(function () { - 'use strict'; - - describe("Media-Constraints service", function() { - var media, service; - beforeEach(module("cortex.services.mediaConstraints")); - - beforeEach(inject(function($injector) { - media = { - dimensions: [800, 600] - }; - service = $injector.get("mediaConstraintsService"); - })); - - it("should check width constraints", function() { - expect(service.width(media, 500, 1000)).toBeTruthy(); - expect(service.width(media, 500, -1)).toBeTruthy(); - expect(service.width(media, 1000, 1100)).toBeFalsy(); - expect(service.width(media, 1000, -1)).toBeFalsy(); - }); - - it("should check height constraints", function() { - expect(service.height(media, 500, 1000)).toBeTruthy(); - expect(service.height(media, 500, -1)).toBeTruthy(); - expect(service.height(media, 1000, 1100)).toBeFalsy(); - expect(service.height(media, 1000, -1)).toBeFalsy(); - }); - - it("should check aspect ratio constraints", function() { - expect(service.aspectratio(media, 1.3)).toBeTruthy(); - expect(service.aspectratio(media, [1.2, 1.3])).toBeTruthy(); - expect(service.aspectratio(media, 1.7)).toBeFalsy(); - expect(service.aspectratio(media, [1.7])).toBeFalsy(); - }); - - it("should check total size", function() { - expect(service.totalSize(media, 480000,.9)).toBeTruthy(); - expect(service.totalSize(media, 48000000,.9)).toBeFalsy(); - }); - - describe("featuredMediaConstraintsService", function() { - var failMedia; - beforeEach(inject(function($injector) { - failMedia = { - dimensions: [1, 1] - }; - media = { - dimensions: [1920, 1080] - }; - service = $injector.get("featuredMediaConstraintsService"); - })); - - it("should check width constraints", function() { - expect(service.width(media)).toBeTruthy(); - expect(service.width(failMedia)).toBeFalsy(); - }); - - it("should check aspect ratio constraints", function() { - expect(service.aspectratio(media)).toBeTruthy(); - expect(service.aspectratio(failMedia)).toBeFalsy(); - }); - - it("should check total size", function() { - expect(service.totalSize(media)).toBeTruthy(); - expect(service.totalSize(failMedia)).toBeFalsy(); - }); - }); - - describe("tileMediaConstraintsService", function() { - var failMedia; - beforeEach(inject(function($injector) { - failMedia = { - dimensions: [1, 5] - }; - media = { - dimensions: [400, 400] - }; - service = $injector.get("tileMediaConstraintsService"); - })); - - it("should check width constraints", function() { - expect(service.width(media)).toBeTruthy(); - expect(service.width(failMedia)).toBeFalsy(); - }); - - it("should check aspect ratio constraints", function() { - expect(service.aspectratio(media)).toBeTruthy(); - expect(service.aspectratio(failMedia)).toBeFalsy(); - }); - - - }); - }); - -})(); \ No newline at end of file diff --git a/spec/javascripts/spec_helper.js b/spec/javascripts/spec_helper.js deleted file mode 100644 index 3549fc692..000000000 --- a/spec/javascripts/spec_helper.js +++ /dev/null @@ -1,6 +0,0 @@ -// = require application -// = require angular-mocks -// = require sinonjs -// = require sinon-ng -// = require angular-debaser -// = require_tree ./helpers diff --git a/spec/javascripts/support/jasmine.yml b/spec/javascripts/support/jasmine.yml index 9c6fa3192..b5a346dea 100644 --- a/spec/javascripts/support/jasmine.yml +++ b/spec/javascripts/support/jasmine.yml @@ -1,3 +1,50 @@ -# minimalist jasmine.yml configuration when leveraging asset pipeline +# path to parent directory of src_files +# relative path from Rails.root +# defaults to app/assets/javascripts +src_dir: "app/assets/javascripts" + +# path to additional directory of source file that are not part of assets pipeline and need to be included +# relative path from Rails.root +# defaults to [] +# include_dir: +# - ../mobile_app/public/js + +# path to parent directory of css_files +# relative path from Rails.root +# defaults to app/assets/stylesheets +css_dir: "app/assets/stylesheets" + +# list of file expressions to include as source files +# relative path from src_dir +src_files: + - "application.{js.coffee,js,coffee}" + +# list of file expressions to include as css files +# relative path from css_dir +css_files: + +# path to parent directory of spec_files +# relative path from Rails.root +# +# Alternatively accept an array of directory to include external spec files +# spec_dir: +# - spec/javascripts +# - ../engine/spec/javascripts +# +# defaults to spec/javascripts +spec_dir: spec/javascripts + +# list of file expressions to include as helpers into spec runner +# relative path from spec_dir +helpers: + - "helpers/**/*.{js.coffee,js,coffee}" + +# list of file expressions to include as specs into spec runner +# relative path from spec_dir spec_files: - - "**/*[Ss]pec.{js,coffee}" + - "**/*[Ss]pec.{js.coffee,js,coffee}" + +# path to directory of temporary files +# (spec runner and asset cache) +# defaults to tmp/jasmine +tmp_dir: "tmp/jasmine" diff --git a/spec/models/abilities/ability_spec.rb b/spec/models/abilities/ability_spec.rb index d7c2165f5..8463303ca 100644 --- a/spec/models/abilities/ability_spec.rb +++ b/spec/models/abilities/ability_spec.rb @@ -15,12 +15,6 @@ abilities = Abilities::Ability.allowed(user, Tenant) expect(abilities).to eq([]) end - - it 'should NOT have the ability to create webpages' do - user = create(:user) - abilities = Abilities::Ability.allowed(user, Webpage) - expect(abilities).to eq([:view]) - end end context 'Application' do @@ -30,14 +24,5 @@ expect(abilities).to eq([:view, :create, :update, :delete]) end end - - context 'Anything Else' do - it 'should have no abilities' do - post = create(:post) - abilities = Abilities::Ability.allowed(post, post) - expect(abilities).to eq([]) - end - end end - end diff --git a/spec/models/abilities/user_ability_spec.rb b/spec/models/abilities/user_ability_spec.rb index c0d6f7384..046863efe 100644 --- a/spec/models/abilities/user_ability_spec.rb +++ b/spec/models/abilities/user_ability_spec.rb @@ -44,36 +44,6 @@ end end - context 'Subject is a Post' do - let (:subject) { Post } - - it 'should be able to view and create' do - user = build(:user) - abilities = Abilities::UserAbility.allowed(user, subject) - expect(abilities).to eq([:view, :create]) - end - end - - context 'Subject is a Media' do - let (:subject) { Media } - - it 'should be able to view and create' do - user = build(:user) - abilities = Abilities::UserAbility.allowed(user, subject) - expect(abilities).to eq([:view, :create]) - end - end - - context 'Subject is a Category' do - let (:subject) { Category } - - it 'should be able to view' do - user = build(:user) - abilities = Abilities::UserAbility.allowed(user, subject) - expect(abilities).to eq([:view]) - end - end - context 'Subject is a Localization' do let (:subject) { Localization } @@ -114,56 +84,6 @@ end end - context 'Subject is a BulkJob' do - let (:subject) { BulkJob } - - it 'should be able to view and create' do - user = build(:user) - abilities = Abilities::UserAbility.allowed(user, subject) - expect(abilities).to eq([:view, :create]) - end - end - - context 'Subject is a Document' do - let (:subject) { Document } - - it 'should be able to view and create' do - user = build(:user) - abilities = Abilities::UserAbility.allowed(user, subject) - expect(abilities).to eq([:view, :create]) - end - end - - context 'Subject is a Webpage' do - let (:subject) { Webpage } - - context 'User is an Admin' do - it 'should be able to view and create' do - admin = build(:user, :admin) - abilities = Abilities::UserAbility.allowed(admin, subject) - expect(abilities).to eq([:view, :create]) - end - end - - context 'User is not an Admin' do - it 'should be able to view' do - user = build(:user) - abilities = Abilities::UserAbility.allowed(user, subject) - expect(abilities).to eq([:view]) - end - end - end - - context 'Subject is a Snippet' do - let (:subject) { Snippet } - - it 'should be able to view and create' do - user = build(:user) - abilities = Abilities::UserAbility.allowed(user, subject) - expect(abilities).to eq([:view, :create]) - end - end - context 'Subject is a ContentItem' do let (:subject) { ContentItem } @@ -234,26 +154,6 @@ end end - context 'Subject is a Post' do - let (:subject) { build(:post) } - - it 'should be able to view, update, and delete' do - user = build(:user) - abilities = Abilities::UserAbility.allowed(user, subject) - expect(abilities).to eq([:view, :update, :delete]) - end - end - - context 'Subject is a Media' do - let (:subject) { build(:media) } - - it 'should be able to view, update, and delete' do - user = build(:user) - abilities = Abilities::UserAbility.allowed(user, subject) - expect(abilities).to eq([:view, :update, :delete]) - end - end - context 'Subject is a Localization' do let (:subject) { build(:localization) } @@ -306,57 +206,6 @@ end end - context 'Subject is a BulkJob' do - let (:subject) { build(:bulk_job) } - - it 'should be able to view, update, and delete' do - user = build(:user) - abilities = Abilities::UserAbility.allowed(user, subject) - expect(abilities).to eq([:view, :update, :delete]) - end - end - - context 'Subject is a Document' do - let (:subject) { build(:document) } - - it 'should be able to view, update, and delete' do - user = build(:user) - abilities = Abilities::UserAbility.allowed(user, subject) - expect(abilities).to eq([:view, :update, :delete]) - end - end - - context 'Subject is a Webpage' do - let (:subject) { build(:webpage) } - - context 'User is an Admin' do - it 'should be able to view, update, and delete' do - admin = build(:user, :admin) - abilities = Abilities::UserAbility.allowed(admin, subject) - expect(abilities).to eq([:view, :update, :delete]) - end - end - - context 'User is not an Admin' do - it 'should be able to view' do - user = build(:user) - abilities = Abilities::UserAbility.allowed(user, subject) - expect(abilities).to eq([:view]) - end - end - end - - # Mysteriously broken.. it's trying to persist the snippet, which is breaking ES - xcontext 'Subject is a Snippet' do - let (:user) { build(:user) } - let (:subject) { build(:snippet, user: user) } - - it 'should be able to view, update, and delete' do - abilities = Abilities::UserAbility.allowed(user, subject) - expect(abilities).to eq([:view, :update, :delete]) - end - end - context 'Subject is a ContentType' do let (:subject) { build(:content_type) } @@ -378,5 +227,4 @@ end end end - end diff --git a/spec/models/concerns/has_gravatar_spec.rb b/spec/models/concerns/has_gravatar_spec.rb deleted file mode 100644 index 63666ea9b..000000000 --- a/spec/models/concerns/has_gravatar_spec.rb +++ /dev/null @@ -1,10 +0,0 @@ -require 'spec_helper' - -describe HasGravatar, :type => :model do - context 'author model' do - it 'should provide Gravatar icon URLs' do - author = build(:author, email: 'talentsolutionstechnology@careerbuilder.com') - expect(author.avatars[:default]).to include('211d03ded8ca5767c12c5f80f9cb6ad2') - end - end -end diff --git a/spec/models/media_spec.rb b/spec/models/media_spec.rb deleted file mode 100644 index baaf502fe..000000000 --- a/spec/models/media_spec.rb +++ /dev/null @@ -1,41 +0,0 @@ -require 'spec_helper' - -RSpec.describe Media, type: :model do - - xit "should create media with valid parameters" do - media = create(:media, :image) - expect(media.attachment_content_type).to eq('image/jpeg') - end - - xit "should allow deletion of unconsumed media" do - media = create(:media) - expect(media.destroy).to be_truthy - end - - xit "should not allow deletion of consumed media" do - media = create(:media) - post = create(:post) - post.featured_media = media - post.save - expect {media.destroy}.to raise_error - end - - xdescribe 'find_by_tenant_id' do - let (:user) { create(:user) } - let (:other_user) { create(:user) } - let (:media) { create(:media, user: user) } - let (:other_media) { create(:media, user: other_user) } - - it 'should return the post from the first tenant' do - this_media = Media.find media.id - that_media = Media.find other_media.id - expect(Media.find_by_tenant_id(user.tenant.id)).to include(this_media) - end - - it 'should not return the post from the other tenant' do - this_media = Media.find media.id - that_media = Media.find other_media.id - expect(Media.find_by_tenant_id(user.tenant.id)).not_to include(that_media) - end - end -end diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb deleted file mode 100644 index 4acb7ec59..000000000 --- a/spec/models/post_spec.rb +++ /dev/null @@ -1,141 +0,0 @@ -require 'spec_helper' - -RSpec.describe Post, type: :model do - - describe "find_by_id_or_slug" do - it "should find by ID" do - post = create(:post) - expect(Post.find_by_id_or_slug(post.id).id).to eq(post.id) - end - - it "should find by slug" do - post = create(:post) - post2 = create(:post, slug: "#{post.id}-slug") - expect(Post.find_by_id_or_slug(post2.slug).id).to eq(post2.id) - end - end - - describe 'find_by_tenant_id' do - let (:user) { create(:user) } - let (:other_user) { create(:user) } - let (:post) { create(:post, user: user) } - let (:other_post) { create(:post, user: other_user) } - - it 'should return the post from the first tenant' do - this_post = Post.find post.id - that_post = Post.find other_post.id - expect(Post.find_by_tenant_id(user.tenant.id)).to include(this_post) - end - - it 'should not return the post from the other tenant' do - this_post = Post.find post.id - that_post = Post.find other_post.id - expect(Post.find_by_tenant_id(user.tenant.id)).not_to include(that_post) - end - end - - describe '#published?' do - let (:user) { create(:user) } - let (:post) { create(:post) } - - context 'Post is Expired' do - let (:expired_post) { create(:post, user: user, expired_at: Time.now - 2.days) } - - it 'should return false' do - expect(expired_post.published?).to be_falsey - end - end - - context 'Post is a Draft' do - let (:draft_post) { create(:post, user: user, draft: true) } - - it 'should return false' do - expect(draft_post.published?).to be_falsey - end - end - - context 'Post will be published in the future' do - let (:future_post) { create(:post, user: user, published_at: Time.now + 2.days) } - - it 'should return false' do - expect(future_post.published?).to be_falsey - end - end - - context 'Post is Active' do - it 'should return true' do - expect(post.published?).to be_truthy - end - end - end - - describe '#expired?' do - let (:user) { create(:user) } - let (:post) { create(:post, user: user, expired_at: Time.now + 2.days) } - let (:expired_post) { create(:post, user: user, expired_at: Time.now - 2.days) } - - context 'expired_at is nil' do - context 'Post is expired' do - it 'should return true' do - expect(expired_post.expired?).to be_truthy - end - end - - context 'Post is not expired' do - it 'should return false' do - expect(post.expired?).to be_falsey - end - end - end - - context 'expired_at is not nil' do - let (:other_post) { create(:post, user: user, expired_at: nil) } - - it 'should return false' do - expect(other_post.expired?).to be_falsey - end - end - end - - describe '#pending?' do - let (:user) { create(:user) } - let (:post) { create(:post, user: user, published_at: Time.now - 2.days) } - let (:future_post) { create(:post, user: user, published_at: Time.now + 2.days) } - - context 'published_at is not nil' do - context 'Post is pending publish' do - it 'should return true' do - expect(future_post.pending?).to be_truthy - end - end - - context 'Post is not pending publish' do - it 'should return false' do - expect(post.pending?).to be_falsey - end - end - end - - context 'published_at is nil' do - let (:other_post) { create(:post, user: user, published_at: nil) } - - it 'should return false' do - expect(other_post.pending?).to be_falsey - end - end - end - - describe Post.published do - before :all do - user = create(:user) - @unpublished_post = create(:post, user: user, draft: true) - @future_post = create(:post, user: user, published_at: Time.now + 2.days) - @expired_post = create(:post, user: user, expired_at: Time.now - 2.days) - @post = create(:post) - end - - it { is_expected.not_to include(@unpublished_post, @future_post, @expired_post) } - it { is_expected.to include(@post) } - end - -end diff --git a/spec/models/webpage_spec.rb b/spec/models/webpage_spec.rb deleted file mode 100644 index 70fd750dd..000000000 --- a/spec/models/webpage_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe Webpage, type: :model do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index c0a82718c..dbd93064f 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -4,8 +4,6 @@ abort('The Rails environment is running in production mode!') if Rails.env.production? require 'rspec/rails' -require 'api_v1_helper' - require 'mocha/api' require 'net/http' require 'email_spec'