From 7653cebb8156b7cf737f229932b64a2e2d4cd04b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Bol=C3=ADvar?= Date: Tue, 9 Jan 2024 16:23:05 +0100 Subject: [PATCH] Configure linters and add CI workflows --- .erb-lint.yml | 30 +++++++++ .eslintignore | 15 +++++ .eslintrc.json | 3 + .github/workflows/lint.yml | 44 ++++++++++++ .github/workflows/test.yml | 62 +++++++++++++++++ .gitignore | 1 + .mdl_style.rb | 15 +++++ .mdlrc | 1 + .rubocop.yml | 21 ++++++ Gemfile | 67 ++++++++++--------- Gemfile.lock | 4 ++ README.md | 4 +- Rakefile | 4 +- app/channels/application_cable/channel.rb | 2 + app/channels/application_cable/connection.rb | 2 + app/controllers/application_controller.rb | 2 + app/controllers/decidim_controller.rb | 2 + app/helpers/application_helper.rb | 2 + app/jobs/application_job.rb | 2 + app/mailers/application_mailer.rb | 6 +- app/models/application_record.rb | 2 + app/models/employee.rb | 2 + app/packs/stylesheets/.keep | 0 app/views/layouts/mailer.html.erb | 2 +- config.ru | 4 +- config/application.rb | 21 +++--- config/boot.rb | 6 +- config/deploy.rb | 30 +++++---- config/deploy/production.rb | 12 ++-- config/deploy/staging.rb | 12 ++-- config/environment.rb | 4 +- config/environments/development.rb | 6 +- config/environments/production.rb | 32 ++++----- config/environments/test.rb | 6 +- .../application_controller_renderer.rb | 1 + config/initializers/backtrace_silencers.rb | 1 + .../initializers/content_security_policy.rb | 1 + config/initializers/cookies_serializer.rb | 2 + config/initializers/decidim.rb | 8 +-- .../extend_proposal_title_size.rb | 2 + .../initializers/filter_parameter_logging.rb | 2 + config/initializers/inflections.rb | 1 + config/initializers/mime_types.rb | 1 + config/initializers/omniauth.rb | 8 +-- config/initializers/wrap_parameters.rb | 2 + config/puma.rb | 8 ++- config/routes.rb | 12 ++-- config/schedule.rb | 8 ++- config/spring.rb | 6 +- db/seeds.rb | 2 + lib/capistrano/tasks/stage_files.rake | 8 ++- lib/imipre_strategy.rb | 17 +++-- lib/tasks/chamber.rake | 48 ++++++------- lib/tasks/load_employees.rake | 26 +++---- package.json | 12 ++++ public/decidim-packs/js/decidim_core.js | 1 + public/decidim-packs/js/decidim_core.js.map | 2 +- spec/factories.rb | 1 + spec/features/feder_footer_spec.rb | 14 ++-- spec/lib/overrides_spec.rb | 2 +- spec/rails_helper.rb | 12 ++-- spec/spec_helper.rb | 64 +++++++++--------- 62 files changed, 492 insertions(+), 208 deletions(-) create mode 100644 .erb-lint.yml create mode 100644 .eslintignore create mode 100644 .eslintrc.json create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/test.yml create mode 100644 .mdl_style.rb create mode 100644 .mdlrc create mode 100644 .rubocop.yml delete mode 100644 app/packs/stylesheets/.keep diff --git a/.erb-lint.yml b/.erb-lint.yml new file mode 100644 index 0000000..3321add --- /dev/null +++ b/.erb-lint.yml @@ -0,0 +1,30 @@ +--- + +linters: + ExtraNewline: + enabled: true + + FinalNewline: + enabled: true + + SpaceAroundErbTag: + enabled: true + + AllowedScriptType: + enabled: true + allowed_types: + - text/javascript + - text/template + + Rubocop: + enabled: true + + rubocop_config: + AllCops: + DisabledByDefault: true + + Style/StringLiterals: + EnforcedStyle: double_quotes + + Layout/SpaceInsideHashLiteralBraces: + Enabled: true diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..748844c --- /dev/null +++ b/.eslintignore @@ -0,0 +1,15 @@ +**/*{.,-}min.js +decidim-*/vendor/**/*.js +spec/decidim_dummy_app/**/*.js +development_app +**/node_modules/** +bundle.js +karma.conf.js +webpack.config.js +webpack.config.babel.js +entry.test.js +entry.js +*_manifest.js +coverage +decidim-dev/**/*/test/**/*.js +vendor/bundle diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..08de8c7 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "@decidim" +} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..98bc1e6 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,44 @@ +name: Lint + +on: + push: + branches: + - main + pull_request: + +env: + RUBY_VERSION: 2.7.3 + NODE_VERSION: 16.9.1 + +jobs: + lint: + name: Lint code + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2.0.0 + with: + fetch-depth: 1 + + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ env.RUBY_VERSION }} + bundler-cache: true + + - uses: actions/setup-node@master + with: + node-version: ${{ env.NODE_VERSION }} + + - run: bundle exec rubocop -P + name: Lint Ruby files + + - run: bundle exec mdl *.md + name: Lint Markdown files + + - run: bundle exec erblint app/{overrides,views}/**/*.{erb,deface} + name: Lint ERB files + + - run: npm run stylelint + name: Lint SCSS files + + - run: npm run lint + name: Lint JS files diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..8ac5747 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,62 @@ +name: Test + +on: + push: + branches: + - main + pull_request: + +env: + RUBY_VERSION: 2.7.3 + NODE_VERSION: 16.9.1 + +jobs: + test: + name: Test + runs-on: ubuntu-20.04 + services: + postgres: + image: postgres:11 + ports: + - 5432:5432 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_HOST_AUTH_METHOD: trust + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 1 + + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ env.RUBY_VERSION }} + bundler-cache: true + + - name: Bundle Install + run: bundle install + + - name: Setup & create Database + run: bundle exec rake db:test:prepare + env: + RAILS_ENV: test + DATABASE_USERNAME: postgres + DATABASE_PASSWORD: postgres + + - name: Precompile assets + run: | + npm install + bundle exec rake assets:precompile + env: + RAILS_ENV: test + DATABASE_USERNAME: postgres + DATABASE_PASSWORD: postgres + + - name: Run RSpec + run: SIMPLECOV=1 CODECOV=1 bundle exec rspec + env: + RAILS_ENV: test + DATABASE_USERNAME: postgres + DATABASE_PASSWORD: postgres diff --git a/.gitignore b/.gitignore index 4d6d0cf..ebe5caf 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,4 @@ config/*-development.yml /public/packs-test yarn-debug.log* .yarn-integrity +.rubocop-https* diff --git a/.mdl_style.rb b/.mdl_style.rb new file mode 100644 index 0000000..6830ce3 --- /dev/null +++ b/.mdl_style.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +all + +exclude_rule "first-line-h1" + +exclude_rule "line-length" + +exclude_rule "no-bare-urls" + +exclude_rule "no-inline-html" + +exclude_rule "ol-prefix" + +rule "no-trailing-punctuation", punctuation: ".,;:!" diff --git a/.mdlrc b/.mdlrc new file mode 100644 index 0000000..27f3882 --- /dev/null +++ b/.mdlrc @@ -0,0 +1 @@ +style ".mdl_style.rb" diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..87b2b0d --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,21 @@ +inherit_from: https://raw.githubusercontent.com/decidim/decidim/release/0.25-stable/.rubocop.yml + +AllCops: + Include: + - "**/*.rb" + - "**/*.rake" + - "**/*.ru" + - "**/Gemfile" + - "**/Rakefile" + Exclude: + - "development_app/**/*" + - "**/development_app/**/*" + - "spec/decidim_dummy_app/**/*" + - "**/spec/decidim_dummy_app/**/*" + - "bin/**/*" + - "node_modules/**/*" + - "**/node_modules/**/*" + - "db/schema.rb" + - "db/migrate/*" + - "vendor/**/*" + - "**/vendor/**/*" diff --git a/Gemfile b/Gemfile index 9bb5e68..0d0b078 100644 --- a/Gemfile +++ b/Gemfile @@ -1,54 +1,55 @@ # frozen_string_literal: true -source 'https://rubygems.org' +source "https://rubygems.org" ruby RUBY_VERSION -DECIDIM_VERSION = { git: 'https://github.com/decidim/decidim.git', branch: 'release/0.25-stable' } +DECIDIM_VERSION = { git: "https://github.com/decidim/decidim.git", branch: "release/0.25-stable" }.freeze -gem 'activerecord-session_store' -gem 'chamber', '~> 2.12.1' +gem "activerecord-session_store" +gem "chamber", "~> 2.12.1" # Change term_customizer dependency to ruby-gems' when term-customizer is compatible with DECIDIM_bVERSION -gem 'decidim-term_customizer', git: 'https://github.com/mainio/decidim-module-term_customizer', branch: 'release/0.25-stable' +gem "decidim-term_customizer", git: "https://github.com/mainio/decidim-module-term_customizer", branch: "release/0.25-stable" -gem 'decidim', DECIDIM_VERSION -gem 'decidim-consultations', DECIDIM_VERSION -gem 'decidim-direct_verifications', '~> 1.2.0' -gem 'omniauth-saml', '~> 2.0' +gem "decidim", DECIDIM_VERSION +gem "decidim-consultations", DECIDIM_VERSION +gem "decidim-direct_verifications", "~> 1.2.0" +gem "omniauth-saml", "~> 2.0" # Metrics require a queue system and a daily cron -gem 'delayed_job_active_record' +gem "delayed_job_active_record" # daemons: required to manage the delayed_job background process -gem 'daemons' -gem 'whenever', require: false +gem "daemons" +gem "whenever", require: false -gem 'bootsnap', '~> 1.3' +gem "bootsnap", "~> 1.3" -gem 'puma', '~> 5.0' -gem 'uglifier', '~> 4.1' +gem "puma", "~> 5.0" +gem "uglifier", "~> 4.1" -gem 'httplog' gem "deface" +gem "httplog" group :development, :test do - gem 'byebug', platform: :mri - gem 'rspec-rails' - gem 'decidim-dev', DECIDIM_VERSION - gem 'faker', "~> 2.14" + gem "byebug", platform: :mri + gem "decidim-dev", DECIDIM_VERSION + gem "faker", "~> 2.14" + gem "rspec-rails" end group :development do - gem 'airbrussh', require: false - gem 'capistrano', '3.3.5' - gem 'capistrano-bundler', '~> 1.2' - gem 'capistrano-db-tasks', require: false - gem 'capistrano-faster-assets', '~> 1.0' - gem 'capistrano-passenger' - gem 'capistrano-rails' - gem 'capistrano3-delayed-job', '~> 1.0' - gem 'letter_opener_web', '~> 1.3' - gem 'listen', '~> 3.1' - gem 'spring', '~> 2.0' - gem 'spring-watcher-listen', '~> 2.0' - gem 'web-console', '~> 3.5' + gem "airbrussh", require: false + gem "capistrano", "3.3.5" + gem "capistrano3-delayed-job", "~> 1.0" + gem "capistrano-bundler", "~> 1.2" + gem "capistrano-db-tasks", require: false + gem "capistrano-faster-assets", "~> 1.0" + gem "capistrano-passenger" + gem "capistrano-rails" + gem "letter_opener_web", "~> 1.3" + gem "listen", "~> 3.1" + gem "rubocop-faker" + gem "spring", "~> 2.0" + gem "spring-watcher-listen", "~> 2.0" + gem "web-console", "~> 3.5" end diff --git a/Gemfile.lock b/Gemfile.lock index 34b8268..8d8d662 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -752,6 +752,9 @@ GEM unicode-display_width (>= 1.4.0, < 2.0) rubocop-ast (1.30.0) parser (>= 3.2.1.0) + rubocop-faker (1.1.0) + faker (>= 2.12.0) + rubocop (>= 0.82.0) rubocop-rails (2.9.1) activesupport (>= 4.2.0) rack (>= 1.1) @@ -899,6 +902,7 @@ DEPENDENCIES omniauth-saml (~> 2.0) puma (~> 5.0) rspec-rails + rubocop-faker spring (~> 2.0) spring-watcher-listen (~> 2.0) uglifier (~> 4.1) diff --git a/README.md b/README.md index 9c0f1c3..95caa9d 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ Al autenticar con OAUTH comprueba que los campos del csv tengan el estado activo Ejemplo de csv: -``` +```csv Matricula;Cognoms;Nom;mail;Estat;Tipus d'Empleat DXXXXXX;Sanchez Inclan ;Manuel;msinclan@bcn.cat;ACTIVE;T1 ``` @@ -170,4 +170,4 @@ finalmente se borran las respuestas: ```ruby a.destroy_all -``` \ No newline at end of file +``` diff --git a/Rakefile b/Rakefile index e85f913..d2a78aa 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,8 @@ +# frozen_string_literal: true + # Add your own tasks in files placed in lib/tasks ending in .rake, # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. -require_relative 'config/application' +require_relative "config/application" Rails.application.load_tasks diff --git a/app/channels/application_cable/channel.rb b/app/channels/application_cable/channel.rb index d672697..9aec230 100644 --- a/app/channels/application_cable/channel.rb +++ b/app/channels/application_cable/channel.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ApplicationCable class Channel < ActionCable::Channel::Base end diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb index 0ff5442..8d6c2a1 100644 --- a/app/channels/application_cable/connection.rb +++ b/app/channels/application_cable/connection.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ApplicationCable class Connection < ActionCable::Connection::Base end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 09705d1..7944f9f 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + class ApplicationController < ActionController::Base end diff --git a/app/controllers/decidim_controller.rb b/app/controllers/decidim_controller.rb index d61ffd0..85919c0 100644 --- a/app/controllers/decidim_controller.rb +++ b/app/controllers/decidim_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Entry point for Decidim. It will use the `DecidimController` as # entry point, but you can change what controller it inherits from # so you can customize some methods. diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index de6be79..15b06f0 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + module ApplicationHelper end diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb index a009ace..d92ffdd 100644 --- a/app/jobs/application_job.rb +++ b/app/jobs/application_job.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + class ApplicationJob < ActiveJob::Base end diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb index 286b223..5cc63a0 100644 --- a/app/mailers/application_mailer.rb +++ b/app/mailers/application_mailer.rb @@ -1,4 +1,6 @@ +# frozen_string_literal: true + class ApplicationMailer < ActionMailer::Base - default from: 'from@example.com' - layout 'mailer' + default from: "from@example.com" + layout "mailer" end diff --git a/app/models/application_record.rb b/app/models/application_record.rb index 10a4cba..71fbba5 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class ApplicationRecord < ActiveRecord::Base self.abstract_class = true end diff --git a/app/models/employee.rb b/app/models/employee.rb index d5e0233..49ad79c 100644 --- a/app/models/employee.rb +++ b/app/models/employee.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + class Employee < ApplicationRecord end diff --git a/app/packs/stylesheets/.keep b/app/packs/stylesheets/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/app/views/layouts/mailer.html.erb b/app/views/layouts/mailer.html.erb index cbd34d2..3aac900 100644 --- a/app/views/layouts/mailer.html.erb +++ b/app/views/layouts/mailer.html.erb @@ -1,7 +1,7 @@ - + diff --git a/config.ru b/config.ru index f7ba0b5..bff88d6 100644 --- a/config.ru +++ b/config.ru @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # This file is used by Rack-based servers to start the application. -require_relative 'config/environment' +require_relative "config/environment" run Rails.application diff --git a/config/application.rb b/config/application.rb index 4d46d84..c0b52bc 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,4 +1,6 @@ -require_relative 'boot' +# frozen_string_literal: true + +require_relative "boot" require "decidim/rails" # Add the frameworks used by your app that are not loaded by Decidim. @@ -21,20 +23,21 @@ class Application < Rails::Application # the framework and any gems in your application. # Load chamber settings because we use it in this file - Chamber.load files: [Rails.root + 'config/settings.yml', Rails.root + 'config/settings/**/*.{yml,yml.erb}'], - decryption_key: Rails.root + 'config/chamber.pem', + Chamber.load files: [Rails.root.join("config/settings.yml"), Rails.root.join("config/settings/**/*.{yml,yml.erb}")], + decryption_key: Rails.root.join("config/chamber.pem"), namespaces: { environment: -> { ::Rails.env }, - hostname: -> { Socket.gethostname } } + hostname: -> { Socket.gethostname } + } # We need to initialize before load_environment_config because railties initialize it before config with default # parameters. - initializer 'internos.chamber.load', before: :load_environment_config do - Chamber.load files: [Rails.root + 'config/settings.yml', Rails.root + 'config/settings/**/*.{yml,yml.erb}'], - decryption_key: Rails.root + 'config/chamber.pem', + initializer "internos.chamber.load", before: :load_environment_config do + Chamber.load files: [Rails.root.join("config/settings.yml"), Rails.root.join("config/settings/**/*.{yml,yml.erb}")], + decryption_key: Rails.root.join("config/chamber.pem"), namespaces: { environment: -> { ::Rails.env }, - hostname: -> { Socket.gethostname } } + hostname: -> { Socket.gethostname } + } end - end end diff --git a/config/boot.rb b/config/boot.rb index 6d556ea..4ab87a7 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,6 +1,8 @@ -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +# frozen_string_literal: true -require 'bundler/setup' # Set up gems listed in the Gemfile. +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +require "bundler/setup" # Set up gems listed in the Gemfile. require "bootsnap" env = ENV["RAILS_ENV"] || "development" diff --git a/config/deploy.rb b/config/deploy.rb index b791224..212db3f 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -1,29 +1,31 @@ +# frozen_string_literal: true + # config valid only for current version of Capistrano -lock '3.3.5' +lock "3.3.5" -set :application, 'internos' -set :user, 'aytobarcelonadecidim' +set :application, "internos" +set :user, "aytobarcelonadecidim" set :repo_url, "https://github.com/AjuntamentdeBarcelona/aytobarcelona-internos.git" set :deploy_to, -> { "/home/#{fetch(:user)}/app" } set :keep_releases, 5 -set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/chamber.pem') -set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads', - 'storage', 'tmp/webpacker-cache', 'node_modules', 'public/decidim-packs') +set :linked_files, fetch(:linked_files, []).push("config/database.yml", "config/chamber.pem") +set :linked_dirs, fetch(:linked_dirs, []).push("log", "tmp/pids", "tmp/cache", "tmp/sockets", "vendor/bundle", "public/system", "public/uploads", + "storage", "tmp/webpacker-cache", "node_modules", "public/decidim-packs") # Files that won't be copied from script/deploy/{branch}/ into the root directory set :exclude_deployment_files, [] -set :ssh_options, -> { +set :ssh_options, lambda { { - user: fetch(:user), - forward_agent: true, - compression: 'none' + user: fetch(:user), + forward_agent: true, + compression: "none" } } -set :rails_env, 'production' +set :rails_env, "production" set :scm, :git set :log_level, :info @@ -34,12 +36,12 @@ # This directory must be in your shared directory on the server set :assets_dir, %w(public/assets) # if you want to work on a specific local environment (default = ENV['RAILS_ENV'] || 'development') -set :locals_rails_env, 'development' +set :locals_rails_env, "development" set :passenger_restart_with_touch, true namespace :deploy do - desc 'Create chamber.pem symlink' + desc "Create chamber.pem symlink" task :create_symlink do on roles(:app) do # Asegurar que shared path y latest release tienen valor/existen @@ -59,4 +61,4 @@ before "deploy:assets:precompile", "deploy:decidim_webpacker_install" end -after 'bundler:install', 'deploy:create_symlink' +after "bundler:install", "deploy:create_symlink" diff --git a/config/deploy/production.rb b/config/deploy/production.rb index 7e74497..5b1e5e7 100644 --- a/config/deploy/production.rb +++ b/config/deploy/production.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Simple Role Syntax # ================== # Supports bulk-adding hosts to roles, the primary @@ -6,12 +8,12 @@ # Don't declare `role :all`, it's a meta role role :app, %w(decidim-intern.ajbcn.coditramuntana.cat) role :web, %w(decidim-intern.ajbcn.coditramuntana.cat) -role :db, %w(decidim-intern.ajbcn.coditramuntana.cat) +role :db, %w(decidim-intern.ajbcn.coditramuntana.cat) -set :app_env, 'master' # Name used in rollbar/hipchat, etc -set :branch, fetch(:app_env) # Git branch deployed -set :instance, 'production' # Deploy extra files from script/deploy/ -set :bundle_without, %w{development test}.join(' ') +set :app_env, "master" # Name used in rollbar/hipchat, etc +set :branch, fetch(:app_env) # Git branch deployed +set :instance, "production" # Deploy extra files from script/deploy/ +set :bundle_without, %w(development test).join(" ") # Extended Server Syntax # ====================== diff --git a/config/deploy/staging.rb b/config/deploy/staging.rb index 2f7e25c..7061a5d 100644 --- a/config/deploy/staging.rb +++ b/config/deploy/staging.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Simple Role Syntax # ================== # Supports bulk-adding hosts to roles, the primary @@ -6,12 +8,12 @@ # Don't declare `role :all`, it's a meta role role :app, %w(decidim-intern-pre.ajbcn.coditramuntana.cat) role :web, %w(decidim-intern-pre.ajbcn.coditramuntana.cat) -role :db, %w(decidim-intern-pre.ajbcn.coditramuntana.cat) +role :db, %w(decidim-intern-pre.ajbcn.coditramuntana.cat) -set :app_env, 'master' # Name used in rollbar/hipchat, etc -set :branch, fetch(:app_env) # Git branch deployed -set :instance, 'staging' # Deploy extra files from script/deploy/ -set :bundle_without, %w{development test}.join(' ') +set :app_env, "master" # Name used in rollbar/hipchat, etc +set :branch, fetch(:app_env) # Git branch deployed +set :instance, "staging" # Deploy extra files from script/deploy/ +set :bundle_without, %w(development test).join(" ") # Extended Server Syntax # ====================== diff --git a/config/environment.rb b/config/environment.rb index 426333b..7df99e8 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Load the Rails application. -require_relative 'application' +require_relative "application" # Initialize the Rails application. Rails.application.initialize! diff --git a/config/environments/development.rb b/config/environments/development.rb index 64a43b0..a2b0456 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -14,12 +16,12 @@ # Enable/disable caching. By default caching is disabled. # Run rails dev:cache to toggle caching. - if Rails.root.join('tmp', 'caching-dev.txt').exist? + if Rails.root.join("tmp/caching-dev.txt").exist? config.action_controller.perform_caching = true config.cache_store = :memory_store config.public_file_server.headers = { - 'Cache-Control' => "public, max-age=#{2.days.to_i}" + "Cache-Control" => "public, max-age=#{2.days.to_i}" } else config.action_controller.perform_caching = false diff --git a/config/environments/production.rb b/config/environments/production.rb index cc00061..312853d 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -11,7 +13,7 @@ config.eager_load = false # Full error reports are disabled and caching is turned on. - config.consider_all_requests_local = false + config.consider_all_requests_local = false config.action_controller.perform_caching = true # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] @@ -20,7 +22,7 @@ # Disable serving static files from the `/public` folder by default since # Apache or NGINX already handles this. - config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? + config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? # Enable serving of images, stylesheets, and JavaScripts from an asset server. # config.action_controller.asset_host = 'http://assets.example.com' @@ -45,13 +47,13 @@ config.log_level = :info # Prepend all log lines with the following tags. - config.log_tags = [ :request_id ] + config.log_tags = [:request_id] # Use a different cache store in production. # config.cache_store = :mem_cache_store # Use a real queuing backend for Active Job (and separate queues per environment) - config.active_job.queue_adapter = :delayed_job + config.active_job.queue_adapter = :delayed_job # config.active_job.queue_name_prefix = "borrame_#{Rails.env}" config.action_mailer.perform_caching = false @@ -70,14 +72,14 @@ # Use default logging formatter so that PID and timestamp are not suppressed. config.log_formatter = ::Logger::Formatter.new config.action_mailer.smtp_settings = { - :address => Rails.application.secrets.smtp_address, - :port => Rails.application.secrets.smtp_port, - :authentication => Rails.application.secrets.smtp_authentication, - :user_name => Rails.application.secrets.smtp_username, - :password => Rails.application.secrets.smtp_password, - :domain => Rails.application.secrets.smtp_domain, - :enable_starttls_auto => Rails.application.secrets.smtp_starttls_auto, - :openssl_verify_mode => 'none' + address: Rails.application.secrets.smtp_address, + port: Rails.application.secrets.smtp_port, + authentication: Rails.application.secrets.smtp_authentication, + user_name: Rails.application.secrets.smtp_username, + password: Rails.application.secrets.smtp_password, + domain: Rails.application.secrets.smtp_domain, + enable_starttls_auto: Rails.application.secrets.smtp_starttls_auto, + openssl_verify_mode: "none" } # Use a different logger for distributed setups. @@ -85,13 +87,13 @@ # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') if ENV["RAILS_LOG_TO_STDOUT"].present? - logger = ActiveSupport::Logger.new(STDOUT) + logger = ActiveSupport::Logger.new($stdout) logger.formatter = config.log_formatter - config.logger = ActiveSupport::TaggedLogging.new(logger) + config.logger = ActiveSupport::TaggedLogging.new(logger) end # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false - Rails.application.routes.default_url_options[:protocol] = 'https' + Rails.application.routes.default_url_options[:protocol] = "https" end diff --git a/config/environments/test.rb b/config/environments/test.rb index 0a38fd3..5169dda 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -15,11 +17,11 @@ # Configure public file server for tests with Cache-Control for performance. config.public_file_server.enabled = true config.public_file_server.headers = { - 'Cache-Control' => "public, max-age=#{1.hour.to_i}" + "Cache-Control" => "public, max-age=#{1.hour.to_i}" } # Show full error reports and disable caching. - config.consider_all_requests_local = true + config.consider_all_requests_local = true config.action_controller.perform_caching = false # Raise exceptions instead of rendering exception templates. diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb index 89d2efa..f4556db 100644 --- a/config/initializers/application_controller_renderer.rb +++ b/config/initializers/application_controller_renderer.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # ActiveSupport::Reloader.to_prepare do diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb index 59385cd..d0f0d3b 100644 --- a/config/initializers/backtrace_silencers.rb +++ b/config/initializers/backtrace_silencers.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb index d3bcaa5..497f566 100644 --- a/config/initializers/content_security_policy.rb +++ b/config/initializers/content_security_policy.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Define an application-wide content security policy diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb index 5a6a32d..ee8dff9 100644 --- a/config/initializers/cookies_serializer.rb +++ b/config/initializers/cookies_serializer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Specify a serializer for the signed and encrypted cookie jars. diff --git a/config/initializers/decidim.rb b/config/initializers/decidim.rb index 3207415..21899b5 100644 --- a/config/initializers/decidim.rb +++ b/config/initializers/decidim.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true Decidim.configure do |config| - config.application_name = 'Decidim Ajuntament de Barcelona' - config.mailer_sender = 'svc_decidim@bcn.cat' + config.application_name = "Decidim Ajuntament de Barcelona" + config.mailer_sender = "svc_decidim@bcn.cat" # Change these lines to set your preferred locales config.default_locale = :ca - config.available_locales = %i[ca] + config.available_locales = [:ca] # Geocoder configuration if Rails.application.secrets.maps @@ -28,7 +28,7 @@ # end # Currency unit - config.currency_unit = '€' + config.currency_unit = "€" # The number of reports which an object can receive before hiding it # config.max_reports_before_hiding = 3 diff --git a/config/initializers/extend_proposal_title_size.rb b/config/initializers/extend_proposal_title_size.rb index b8fb7ad..1a74c13 100644 --- a/config/initializers/extend_proposal_title_size.rb +++ b/config/initializers/extend_proposal_title_size.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # extends the title size to 250 characters Rails.application.configure do config.after_initialize do diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb index 4a994e1..7a4f47b 100644 --- a/config/initializers/filter_parameter_logging.rb +++ b/config/initializers/filter_parameter_logging.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Configure sensitive parameters which will be filtered from the log file. diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index ac033bf..aa7435f 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Add new inflection rules using the following format. Inflections diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb index dc18996..6e1d16f 100644 --- a/config/initializers/mime_types.rb +++ b/config/initializers/mime_types.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Add new mime types for use in respond_to blocks: diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb index d2010dd..104a74f 100644 --- a/config/initializers/omniauth.rb +++ b/config/initializers/omniauth.rb @@ -4,7 +4,7 @@ module OmniAuth module Strategies # tell OmniAuth to load our strategy - autoload :Imipre, Rails.root.join('lib', 'imipre_strategy') + autoload :Imipre, Rails.root.join("lib/imipre_strategy") end end end @@ -18,8 +18,8 @@ module Strategies sp_entity_id: Chamber.env.saml.sp_entity_id, strategy_class: ::OmniAuth::Strategies::SAML, attribute_statements: { - email: ['mail'], - name: ['givenName', 'nom'] + email: ["mail"], + name: %w(givenName nom) }, certificate: Chamber.env.saml.certificate, private_key: Chamber.env.saml.private_key, @@ -35,7 +35,7 @@ module Strategies before_action :verify_user_type, only: :saml def verify_user_type - saml_response = OneLogin::RubySaml::Response.new(params['SAMLResponse']) + saml_response = OneLogin::RubySaml::Response.new(params["SAMLResponse"]) unless valid_user?(saml_response) flash[:error] = I18n.t("devise.failure.invalid_user_type") redirect_to root_path diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb index bbfc396..2f3c0db 100644 --- a/config/initializers/wrap_parameters.rb +++ b/config/initializers/wrap_parameters.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # This file contains settings for ActionController::ParamsWrapper which diff --git a/config/puma.rb b/config/puma.rb index a5eccf8..a8adec5 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -1,19 +1,21 @@ +# frozen_string_literal: true + # Puma can serve each request in a thread from an internal thread pool. # The `threads` method setting takes two numbers: a minimum and maximum. # Any libraries that use thread pools should be configured to match # the maximum value specified for Puma. Default is set to 5 threads for minimum # and maximum; this matches the default thread size of Active Record. # -threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } +threads_count = ENV.fetch("RAILS_MAX_THREADS", 5) threads threads_count, threads_count # Specifies the `port` that Puma will listen on to receive requests; default is 3000. # -port ENV.fetch("PORT") { 3000 } +port ENV.fetch("PORT", 3000) # Specifies the `environment` that Puma will run in. # -environment ENV.fetch("RAILS_ENV") { "development" } +environment ENV.fetch("RAILS_ENV", "development") # Specifies the number of `workers` to boot in clustered mode. # Workers are forked webserver processes. If using threads and workers together diff --git a/config/routes.rb b/config/routes.rb index 49b4775..fef1a40 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,13 +1,13 @@ +# frozen_string_literal: true + Rails.application.routes.draw do - if Rails.env.development? - mount LetterOpenerWeb::Engine, at: "/letter_opener" - end + mount LetterOpenerWeb::Engine, at: "/letter_opener" if Rails.env.development? if Rails.application.secrets.dig(:omniauth, :saml, :enabled) - get '/users/sign_in', to: redirect { |path_params, req| "/users/auth/saml?#{req.params.to_query}" }, as: :new_user_session - get '/users/sign_up', to: redirect { |path_params, req| "/users/auth/saml?#{req.params.to_query}" }, as: :new_user_registration + get "/users/sign_in", to: redirect { |_path_params, req| "/users/auth/saml?#{req.params.to_query}" }, as: :new_user_session + get "/users/sign_up", to: redirect { |_path_params, req| "/users/auth/saml?#{req.params.to_query}" }, as: :new_user_registration end - mount Decidim::Core::Engine => '/' + mount Decidim::Core::Engine => "/" # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end diff --git a/config/schedule.rb b/config/schedule.rb index a6d5045..7888dc8 100644 --- a/config/schedule.rb +++ b/config/schedule.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Use this file to easily define all of your cron jobs. # # It's helpful, but not entirely necessary to understand cron before proceeding. @@ -19,14 +21,14 @@ # Learn more: http://github.com/javan/whenever -every :sunday, at: '4:00 am' do +every :sunday, at: "4:00 am" do rake "decidim:delete_data_portability_files" end -every 1.day, at: '2:00 am' do +every 1.day, at: "2:00 am" do rake "decidim:metrics:all" end -every 1.day, at: '4:00 am' do +every 1.day, at: "4:00 am" do rake "decidim:open_data:export" end diff --git a/config/spring.rb b/config/spring.rb index 9fa7863..ff5ba06 100644 --- a/config/spring.rb +++ b/config/spring.rb @@ -1,6 +1,8 @@ -%w[ +# frozen_string_literal: true + +%w( .ruby-version .rbenv-vars tmp/restart.txt tmp/caching-dev.txt -].each { |path| Spring.watch(path) } +).each { |path| Spring.watch(path) } diff --git a/db/seeds.rb b/db/seeds.rb index 4d3602e..a60983d 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This file should contain all the record creation needed to seed the database with its default values. # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). # diff --git a/lib/capistrano/tasks/stage_files.rake b/lib/capistrano/tasks/stage_files.rake index dec0c6f..cdda0ab 100644 --- a/lib/capistrano/tasks/stage_files.rake +++ b/lib/capistrano/tasks/stage_files.rake @@ -1,10 +1,12 @@ +# frozen_string_literal: true + namespace :deploy do - desc 'Copy files used per stage to main application dir' + desc "Copy files used per stage to main application dir" task :copy_stage_files do on roles(:app), in: :parallel do files_path = release_path.join("script/deploy/#{fetch(:instance)}/") - excludes = fetch(:exclude_deployment_files, []).map{|f| "--exclude=#{f}" }.join(' ') - execute :rsync, '-avcC', excludes, files_path, release_path + excludes = fetch(:exclude_deployment_files, []).map { |f| "--exclude=#{f}" }.join(" ") + execute :rsync, "-avcC", excludes, files_path, release_path end end diff --git a/lib/imipre_strategy.rb b/lib/imipre_strategy.rb index b1be733..6bf6f6b 100644 --- a/lib/imipre_strategy.rb +++ b/lib/imipre_strategy.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -require 'omniauth-oauth2' -require 'open-uri' +require "omniauth-oauth2" +require "open-uri" module OmniAuth module Strategies @@ -26,13 +26,13 @@ def build_access_token end uid do - employee = Employee.find_by!(code: raw_info['sub']) - raw_info['sub'] + Employee.find_by!(code: raw_info["sub"]) + raw_info["sub"] end # TODO: Check raw info content for user type info do - employee = Employee.find_by!(code: raw_info['sub']) + employee = Employee.find_by!(code: raw_info["sub"]) if employee.present? { email: employee.email, @@ -51,9 +51,8 @@ def client end def raw_info - access_token.options[:mode]= :query - @raw_info ||= access_token.get(Chamber.env.imipre.info_url, {headers: { 'X-OAUTH-IDENTITY-DOMAIN-NAME': Chamber.env.imipre.domain }} - ).parsed + access_token.options[:mode] = :query + @raw_info ||= access_token.get(Chamber.env.imipre.info_url, { headers: { 'X-OAUTH-IDENTITY-DOMAIN-NAME': Chamber.env.imipre.domain } }).parsed end # https://github.com/intridea/omniauth-oauth2/issues/81 @@ -66,7 +65,7 @@ def callback_url def authorize_url @authorize_url ||= URI.join( options.site, - '/oauth2/rest/authz?response_type=code'\ + "/oauth2/rest/authz?response_type=code"\ "&client_id=#{options.client_id}"\ "&domain=#{Chamber.env.imipre.domain}"\ "&scope=#{Chamber.env.imipre.scope}"\ diff --git a/lib/tasks/chamber.rake b/lib/tasks/chamber.rake index 9190542..cb3f1a2 100644 --- a/lib/tasks/chamber.rake +++ b/lib/tasks/chamber.rake @@ -1,40 +1,42 @@ -require 'chamber/commands/securable' -require 'chamber/commands/secure' -require 'pathname' +# frozen_string_literal: true -namespace :chamber do +require "chamber/commands/securable" +require "chamber/commands/secure" +require "pathname" - desc 'Secure all keys from every environment' +namespace :chamber do + desc "Secure all keys from every environment" task :secure_all do - environments = Pathname.new(File.join(Rails.root, 'script', 'deploy')).children.select { |c| c.directory? }.map{|c| c.basename.to_s} << 'development' #nil for development configuration + environments = Pathname.new(Rails.root.join("script/deploy")).children.select(&:directory?).map { |c| c.basename.to_s } << "development" # nil for development configuration environments.each do |environment| - puts "Securing #{environment || 'development'} environment" - Rake::Task['chamber:secure'].execute(environment: environment) + puts "Securing #{environment || "development"} environment" + Rake::Task["chamber:secure"].execute(environment: environment) end end - desc 'Secure keys' - task :secure, [:environment] do |t, args| - environment = args[:environment] || 'development' + desc "Secure keys" + task :secure, [:environment] do |_t, args| + environment = args[:environment] || "development" - basepath = environment != 'development' ? File.join(Rails.root, "script", "deploy", "#{environment}", "config") : File.join(Rails.root, "config") - encryption_key = File.join("#{basepath}", "chamber.pem.pub") + basepath = environment != "development" ? Rails.root.join("script/deploy/#{environment}/config") : Rails.root.join("config") + encryption_key = File.join(basepath.to_s, "chamber.pem.pub") files = [ - File.join("#{basepath}", "settings.yml"), - File.join("#{basepath}", "settings", "*.{yml,yml.erb}") + File.join(basepath.to_s, "settings.yml"), + File.join(basepath.to_s, "settings", "*.{yml,yml.erb}") ] puts "Basepath : #{basepath}" puts "Encryption_key : #{encryption_key}" puts "Files path : #{files}" - if File.exists? encryption_key + if File.exist? encryption_key puts "Encrypting #{environment} environment" options = { - rootpath: Rails.root, - basepath: basepath, - encryption_key: encryption_key, - files: files } + rootpath: Rails.root, + basepath: basepath, + encryption_key: encryption_key, + files: files + } # system "bundle exec chamber secure --basepath=#{basepath} --encryption-key=#{encryption_key} --files=#{files}" chamber_instance = Chamber::Instance.new(options) @@ -44,14 +46,14 @@ namespace :chamber do end puts "\n\n" - end def prepare_params(args) args.each do |arg| - task arg.to_sym do ; end + # rubocop:disable Style/BlockDelimiters + task arg.to_sym do; end + # rubocop:enable Style/BlockDelimiters end args end - end diff --git a/lib/tasks/load_employees.rake b/lib/tasks/load_employees.rake index c6d7aab..aa5528c 100644 --- a/lib/tasks/load_employees.rake +++ b/lib/tasks/load_employees.rake @@ -1,18 +1,20 @@ -require 'csv' +# frozen_string_literal: true + +require "csv" namespace :employees do - desc 'Load employees from csv' - task :load => :environment do - csv_text = File.read('tmp/employees.csv') - csv = CSV.parse(csv_text, headers: true, col_sep: ';'); + desc "Load employees from csv" + task load: :environment do + csv_text = File.read("tmp/employees.csv") + csv = CSV.parse(csv_text, headers: true, col_sep: ";") csv.each do |row| hash = row.to_hash - employee = Employee.find_or_create_by!(code: hash['Matricula']) - employee.tap do |employee| - employee.name = hash['Nom'] - employee.surnames = hash['Cognoms'] - employee.email = hash['mail'] - employee.status = hash['Estat'] - employee.employee_type = hash["Tipus d'Empleat"] + employee = Employee.find_or_create_by!(code: hash["Matricula"]) + employee.tap do |e| + e.name = hash["Nom"] + e.surnames = hash["Cognoms"] + e.email = hash["mail"] + e.status = hash["Estat"] + e.employee_type = hash["Tipus d'Empleat"] end.save! user = Decidim::User.where(email: employee.email).first if user diff --git a/package.json b/package.json index 441560a..9d8559e 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,18 @@ "browserslist": [ "extends @decidim/browserslist-config" ], + "scripts": { + "lint": "eslint -c .eslintrc.json --ext .js app/packs/src", + "lint-fix": "eslint -c .eslintrc.json --ext .js app/packs/src --fix", + "stylelint": "stylelint app/packs/stylesheets/**/*.scss", + "stylelint-fix": "stylelint app/packs/stylesheets/**/*.scss --fix" + }, + "stylelint": { + "extends": "@decidim/stylelint-config", + "rules": { + "block-opening-brace-space-before": "always" + } + }, "devDependencies": { "@decidim/dev": "file:packages/dev", "@decidim/eslint-config": "file:packages/eslint-config", diff --git a/public/decidim-packs/js/decidim_core.js b/public/decidim-packs/js/decidim_core.js index 24d9596..c666024 100644 --- a/public/decidim-packs/js/decidim_core.js +++ b/public/decidim-packs/js/decidim_core.js @@ -2299,6 +2299,7 @@ function _typeof(o) { // Load images __webpack_require__("./app/packs/images sync recursive ^\\.\\/.*$"); +var a = 1; /***/ }), diff --git a/public/decidim-packs/js/decidim_core.js.map b/public/decidim-packs/js/decidim_core.js.map index eeaec2b..b22ccfa 100644 --- a/public/decidim-packs/js/decidim_core.js.map +++ b/public/decidim-packs/js/decidim_core.js.map @@ -1 +1 @@ -{"version":3,"file":"js/decidim_core.js","mappings":";;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACvBA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AAEA;AACA;AACA;AAAA;AAGA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAJA;AAAA;AAAA;AAKA;AACA;AACA;AACA;AAEA;AAAA;AAAA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAJA;AAAA;AAAA;AAKA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA;AAAA;AAAA;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AATA;AAAA;AAAA;AAUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAJA;AAAA;AAAA;AAMA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AALA;AAAA;AAAA;AAMA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AAEA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA;AAAA;AAAA;AASA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AARA;AAAA;AAAA;AAUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAJA;AAAA;AAAA;AAKA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAJA;AAAA;AAAA;AAMA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAJA;AAAA;AAAA;AAMA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAJA;AAAA;AAAA;AAMA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AALA;AAAA;AAAA;AAOA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AALA;AAAA;AAAA;AAOA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AE1SA;AACA;;AAEA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;;;;;;;;;ACnEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;AC1BA;AAEA;AACA;AACA;AACA;;;;;;;;;;ACLA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;;AAEA;AACA;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAMA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;;;;;;;;;;AClFA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;ACfA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;ACtHA;;AAEA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;;;;;;;;;;AChBA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;AChDA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;AC5BA;;AAEA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AChCA;AAEA;AAKA;AAEA;AACA;AACA;AACA;AAAA;AAOA;AAAA;AACA;AAEA;AACA;AAAA;AAAA;AAAA;AAEA;AACA;AAAA;AAAA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AAGA;AAEA;AACA;AAAA;AAAA;AAAA;AAGA;AACA;AAAA;AAAA;AAAA;AAGA;AACA;AAAA;AAAA;AAAA;AA3CA;AACA;AAAA;AAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACjBA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AAIA;AACA;AAEA;AAEA;AACA;AAEA;AAIA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC9CA;AACA;AACA;AACA;AAAA;AAOA;AAAA;AAAA;AACA;AAEA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AAGA;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA;AAAA;AAAA;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AAtCA;AACA;AAAA;AAAA;AAAA;AAAA;AAwCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;ACvDA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;;;;;;;;;;AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;AC3DA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;ACtBA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AAEA;AAEA;;AAEA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AAEA;AACA;;;;;;;;;;ACpEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;ACrCA;;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AAAA;AAAA;AAEA;AAAA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAAA;;;;;;;;;;;;;;AChCA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAAA;AAAA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AASA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;;;;;;;;;ACnMA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;;;;;;;;;;AClCA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;ACjBA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;ACXA;AAEA;AACA;AACA;AAEA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;ACxCA;;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;;;;;;;;;;ACfA;AACA;AACA;;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;;;;;;;;;;ACZA;;AAEA;AAEA;AACA;AAEA;AAEA;AAEA;AACA;AAEA;AACA;AACA;AACA;;;;;;;;;;ACjBA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;AC5CA;;AAEA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;;;;;ACJA;AACA;;AAEA;AACA;;;;;;;;;;;;ACJA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC7BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AC7BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACPA;;;;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACNA;AACA;AACA;AACA;AACA;;;;;ACJA;;;;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AElDA;AACA;AACA;AACA;AACA","sources":["webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/ sync ^\\.\\/.*$","webpack://app/./app/packs/images/ sync ^\\.\\/.*$","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-comments/app/packs/src/decidim/comments/comments.component.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-comments/app/packs/src/decidim/comments/comments.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/entrypoints/decidim_core.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/account_form.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/append_elements.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/append_redirect_url_to_modals.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/callout.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/clipboard.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/conferences.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/conversations.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/diff_mode_dropdown.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/dropdowns_menus.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/external_domain_warning.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/external_link.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/floating_help.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/form_validator.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/icon.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/identity_selector_dialog.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/impersonation.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/index.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/input_autojump.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/input_emoji.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/input_multiple_mentions.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/notifications.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/represent_user_group.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/responsive_horizontal_tabs.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/results_listing.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/security/selfxss_warning.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/start_conversation_dialog.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/tooltip_keep_on_hover.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/user_registrations.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/vendor/modernizr.js","webpack://app/./app/packs/src/decidim/decidim_application.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/entrypoints/decidim_core.scss?2b5b","webpack://app/webpack/bootstrap","webpack://app/webpack/runtime/chunk loaded","webpack://app/webpack/runtime/compat get default export","webpack://app/webpack/runtime/define property getters","webpack://app/webpack/runtime/global","webpack://app/webpack/runtime/hasOwnProperty shorthand","webpack://app/webpack/runtime/make namespace object","webpack://app/webpack/runtime/node module decorator","webpack://app/webpack/runtime/publicPath","webpack://app/webpack/runtime/jsonp chunk loading","webpack://app/webpack/before-startup","webpack://app/webpack/startup","webpack://app/webpack/after-startup"],"sourcesContent":["var map = {\n\t\"./decidim/avatar-multiuser.png\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/avatar-multiuser.png\",\n\t\"./decidim/brands/google.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/brands/google.svg\",\n\t\"./decidim/cc-badge.png\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/cc-badge.png\",\n\t\"./decidim/decidim-logo.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/decidim-logo.svg\",\n\t\"./decidim/default-avatar.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/default-avatar.svg\",\n\t\"./decidim/gamification/badges/decidim_gamification_badges_followers.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/gamification/badges/decidim_gamification_badges_followers.svg\",\n\t\"./decidim/gamification/badges/decidim_gamification_badges_invitations.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/gamification/badges/decidim_gamification_badges_invitations.svg\",\n\t\"./decidim/icons.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/icons.svg\",\n\t\"./decidim/pattern.png\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/pattern.png\",\n\t\"./decidim/placeholder.jpg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/placeholder.jpg\",\n\t\"./decidim/vendor/leaflet/layers-2x.png\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/leaflet/layers-2x.png\",\n\t\"./decidim/vendor/leaflet/layers.png\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/leaflet/layers.png\",\n\t\"./decidim/vendor/leaflet/marker-icon-2x.png\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/leaflet/marker-icon-2x.png\",\n\t\"./decidim/vendor/leaflet/marker-icon.png\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/leaflet/marker-icon.png\",\n\t\"./decidim/vendor/leaflet/marker-shadow.png\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/leaflet/marker-shadow.png\",\n\t\"./decidim/vendor/social-share-button/delicious.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/delicious.svg\",\n\t\"./decidim/vendor/social-share-button/douban.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/douban.svg\",\n\t\"./decidim/vendor/social-share-button/email.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/email.svg\",\n\t\"./decidim/vendor/social-share-button/facebook.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/facebook.svg\",\n\t\"./decidim/vendor/social-share-button/google_bookmark.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/google_bookmark.svg\",\n\t\"./decidim/vendor/social-share-button/google_plus.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/google_plus.svg\",\n\t\"./decidim/vendor/social-share-button/hacker_news.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/hacker_news.svg\",\n\t\"./decidim/vendor/social-share-button/linkedin.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/linkedin.svg\",\n\t\"./decidim/vendor/social-share-button/odnoklassniki.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/odnoklassniki.svg\",\n\t\"./decidim/vendor/social-share-button/pinterest.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/pinterest.svg\",\n\t\"./decidim/vendor/social-share-button/qq.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/qq.svg\",\n\t\"./decidim/vendor/social-share-button/reddit.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/reddit.svg\",\n\t\"./decidim/vendor/social-share-button/telegram.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/telegram.svg\",\n\t\"./decidim/vendor/social-share-button/tumblr.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/tumblr.svg\",\n\t\"./decidim/vendor/social-share-button/twitter.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/twitter.svg\",\n\t\"./decidim/vendor/social-share-button/vkontakte.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/vkontakte.svg\",\n\t\"./decidim/vendor/social-share-button/wechat.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/wechat.svg\",\n\t\"./decidim/vendor/social-share-button/weibo.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/weibo.svg\",\n\t\"./decidim/vendor/social-share-button/whatsapp.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/whatsapp.svg\",\n\t\"./decidim/vendor/social-share-button/xing.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/xing.svg\"\n};\n\n\nfunction webpackContext(req) {\n\tvar id = webpackContextResolve(req);\n\treturn __webpack_require__(id);\n}\nfunction webpackContextResolve(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\treturn map[req];\n}\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images sync recursive ^\\\\.\\\\/.*$\";","var map = {\n\t\"./Oauth_logo.svg\": \"./app/packs/images/Oauth_logo.svg\",\n\t\"./feder-logo.png\": \"./app/packs/images/feder-logo.png\"\n};\n\n\nfunction webpackContext(req) {\n\tvar id = webpackContextResolve(req);\n\treturn __webpack_require__(id);\n}\nfunction webpackContextResolve(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\treturn map[req];\n}\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = \"./app/packs/images sync recursive ^\\\\.\\\\/.*$\";","/* eslint id-length: [\"error\", { \"exceptions\": [\"$\"] }] */\n\n/**\n * A plain Javascript component that handles the comments.\n *\n * @class\n * @augments Component\n */\n\n// This is necessary for testing purposes\nconst $ = window.$;\n\nimport { createCharacterCounter } from \"src/decidim/input_character_counter\"\nimport ExternalLink from \"src/decidim/external_link\"\nimport updateExternalDomainLinks from \"src/decidim/external_domain_warning\"\n\nexport default class CommentsComponent {\n constructor($element, config) {\n this.$element = $element;\n this.commentableGid = config.commentableGid;\n this.commentsUrl = config.commentsUrl;\n this.rootDepth = config.rootDepth;\n this.order = config.order;\n this.lastCommentId = config.lastCommentId;\n this.pollingInterval = config.pollingInterval || 15000;\n this.id = this.$element.attr(\"id\") || this._getUID();\n this.mounted = false;\n }\n\n /**\n * Handles the logic for mounting the component\n * @public\n * @returns {Void} - Returns nothing\n */\n mountComponent() {\n if (this.$element.length > 0 && !this.mounted) {\n this.mounted = true;\n this._initializeComments(this.$element);\n\n $(\".order-by__dropdown .is-submenu-item a\", this.$element).on(\"click.decidim-comments\", () => this._onInitOrder());\n }\n }\n\n /**\n * Handles the logic for unmounting the component\n * @public\n * @returns {Void} - Returns nothing\n */\n unmountComponent() {\n if (this.mounted) {\n this.mounted = false;\n this._stopPolling();\n\n $(\".add-comment .opinion-toggle .button\", this.$element).off(\"click.decidim-comments\");\n $(\".add-comment textarea\", this.$element).off(\"input.decidim-comments\");\n $(\".order-by__dropdown .is-submenu-item a\", this.$element).off(\"click.decidim-comments\");\n $(\".add-comment form\", this.$element).off(\"submit.decidim-comments\");\n $(\".add-comment textarea\", this.$element).each((_i, el) => el.removeEventListener(\"emoji.added\", this._onTextInput));\n }\n }\n\n /**\n * Adds a new thread to the comments section.\n * @public\n * @param {String} threadHtml - The HTML content for the thread.\n * @param {Boolean} fromCurrentUser - A boolean indicating whether the user\n * herself was the author of the new thread. Defaults to false.\n * @returns {Void} - Returns nothing\n */\n addThread(threadHtml, fromCurrentUser = false) {\n const $parent = $(\".comments:first\", this.$element);\n const $comment = $(threadHtml);\n const $threads = $(\".comment-threads\", this.$element);\n this._addComment($threads, $comment);\n this._finalizeCommentCreation($parent, fromCurrentUser);\n }\n\n /**\n * Adds a new reply to an existing comment.\n * @public\n * @param {Number} commentId - The ID of the comment for which to add the\n * reply to.\n * @param {String} replyHtml - The HTML content for the reply.\n * @param {Boolean} fromCurrentUser - A boolean indicating whether the user\n * herself was the author of the new reply. Defaults to false.\n * @returns {Void} - Returns nothing\n */\n addReply(commentId, replyHtml, fromCurrentUser = false) {\n const $parent = $(`#comment_${commentId}`);\n const $comment = $(replyHtml);\n const $replies = $(`#comment-${commentId}-replies`);\n this._addComment($replies, $comment);\n $replies.siblings(\".comment__additionalreply\").removeClass(\"hide\");\n this._finalizeCommentCreation($parent, fromCurrentUser);\n }\n\n /**\n * Generates a unique identifier for the form.\n * @private\n * @returns {String} - Returns a unique identifier\n */\n _getUID() {\n return `comments-${new Date().setUTCMilliseconds()}-${Math.floor(Math.random() * 10000000)}`;\n }\n\n /**\n * Initializes the comments for the given parent element.\n * @private\n * @param {jQuery} $parent The parent element to initialize.\n * @returns {Void} - Returns nothing\n */\n _initializeComments($parent) {\n $(\".add-comment\", $parent).each((_i, el) => {\n const $add = $(el);\n const $form = $(\"form\", $add);\n const $opinionButtons = $(\".opinion-toggle .button\", $add);\n const $text = $(\"textarea\", $form);\n\n $opinionButtons.on(\"click.decidim-comments\", this._onToggleOpinion);\n $text.on(\"input.decidim-comments\", this._onTextInput);\n\n $(document).trigger(\"attach-mentions-element\", [$text.get(0)]);\n\n $form.on(\"submit.decidim-comments\", () => {\n const $submit = $(\"button[type='submit']\", $form);\n\n $submit.attr(\"disabled\", \"disabled\");\n this._stopPolling();\n });\n\n if ($text.length && $text.get(0) !== null) {\n // Attach event to the DOM node, instead of the jQuery object\n $text.get(0).addEventListener(\"emoji.added\", this._onTextInput);\n }\n });\n\n this._pollComments();\n }\n\n /**\n * Adds the given comment element to the given target element and\n * initializes it.\n * @private\n * @param {jQuery} $target - The target element to add the comment to.\n * @param {jQuery} $container - The comment container element to add.\n * @returns {Void} - Returns nothing\n */\n _addComment($target, $container) {\n let $comment = $(\".comment\", $container);\n if ($comment.length < 1) {\n // In case of a reply\n $comment = $container;\n }\n this.lastCommentId = parseInt($comment.data(\"comment-id\"), 10);\n\n $target.append($container);\n $container.foundation();\n this._initializeComments($container);\n createCharacterCounter($(\".add-comment textarea\", $container));\n $container.find('a[target=\"_blank\"]').each((_i, elem) => {\n const $link = $(elem);\n $link.data(\"external-link\", new ExternalLink($link));\n });\n updateExternalDomainLinks($container)\n }\n\n /**\n * Finalizes the new comment creation after the comment adding finishes\n * successfully.\n * @private\n * @param {jQuery} $parent - The parent comment element to finalize.\n * @param {Boolean} fromCurrentUser - A boolean indicating whether the user\n * herself was the author of the new comment.\n * @returns {Void} - Returns nothing\n */\n _finalizeCommentCreation($parent, fromCurrentUser) {\n if (fromCurrentUser) {\n const $add = $(\"> .add-comment\", $parent);\n const $text = $(\"textarea\", $add);\n const characterCounter = $text.data(\"remaining-characters-counter\");\n $text.val(\"\");\n if (characterCounter) {\n characterCounter.updateStatus();\n }\n if (!$add.parent().is(\".comments\")) {\n $add.addClass(\"hide\");\n }\n }\n\n // Restart the polling\n this._pollComments();\n }\n\n /**\n * Sets a timeout to poll new comments.\n * @private\n * @returns {Void} - Returns nothing\n */\n _pollComments() {\n this._stopPolling();\n\n this.pollTimeout = setTimeout(() => {\n $.ajax({\n url: this.commentsUrl,\n method: \"GET\",\n contentType: \"application/javascript\",\n data: {\n \"commentable_gid\": this.commentableGid,\n \"root_depth\": this.rootDepth,\n order: this.order,\n after: this.lastCommentId\n }\n }).done(() => this._pollComments());\n }, this.pollingInterval);\n }\n\n /**\n * Stops polling for new comments.\n * @private\n * @returns {Void} - Returns nothing\n */\n _stopPolling() {\n if (this.pollTimeout) {\n clearTimeout(this.pollTimeout);\n }\n }\n\n /**\n * Sets the loading comments element visible in the view.\n * @private\n * @returns {Void} - Returns nothing\n */\n _setLoading() {\n const $container = $(\"> .comments-container\", this.$element);\n $(\"> .comments\", $container).addClass(\"hide\");\n $(\"> .loading-comments\", $container).removeClass(\"hide\");\n }\n\n /**\n * Event listener for the ordering links.\n * @private\n * @returns {Void} - Returns nothing\n */\n _onInitOrder() {\n this._stopPolling();\n this._setLoading();\n }\n\n /**\n * Event listener for the opinion toggle buttons.\n * @private\n * @param {Event} ev - The event object.\n * @returns {Void} - Returns nothing\n */\n _onToggleOpinion(ev) {\n let $btn = $(ev.target);\n if (!$btn.is(\".button\")) {\n $btn = $btn.parents(\".button\");\n }\n\n const $add = $btn.closest(\".add-comment\");\n const $form = $(\"form\", $add);\n const $opinionButtons = $(\".opinion-toggle .button\", $add);\n const $selectedState = $(\".opinion-toggle .selected-state\", $add);\n const $alignment = $(\".alignment-input\", $form);\n\n $opinionButtons.removeClass(\"is-active\").attr(\"aria-pressed\", \"false\");\n $btn.addClass(\"is-active\").attr(\"aria-pressed\", \"true\");\n\n if ($btn.is(\".opinion-toggle--ok\")) {\n $alignment.val(1);\n } else if ($btn.is(\".opinion-toggle--meh\")) {\n $alignment.val(0);\n } else if ($btn.is(\".opinion-toggle--ko\")) {\n $alignment.val(-1);\n }\n\n // Announce the selected state for the screen reader\n $selectedState.text($btn.data(\"selected-label\"));\n }\n\n /**\n * Event listener for the comment field text input.\n * @private\n * @param {Event} ev - The event object.\n * @returns {Void} - Returns nothing\n */\n _onTextInput(ev) {\n const $text = $(ev.target);\n const $add = $text.closest(\".add-comment\");\n const $form = $(\"form\", $add);\n const $submit = $(\"button[type='submit']\", $form);\n\n if ($text.val().length > 0) {\n $submit.removeAttr(\"disabled\");\n } else {\n $submit.attr(\"disabled\", \"disabled\");\n }\n }\n}\n","import \"src/decidim/comments/comments.component\"\n","/* eslint no-unused-vars: 0 */\n/* eslint id-length: [\"error\", { \"exceptions\": [\"$\"] }] */\n\nimport $ from \"jquery\"\nimport Quill from \"quill\"\nimport Rails from \"@rails/ujs\"\n\nimport \"core-js/stable\";\nimport \"regenerator-runtime/runtime\";\nimport morphdom from \"morphdom\"\n// Export variable to make it available in .js.erb templates\nwindow.morphdom = morphdom\nimport \"src/decidim/vendor/foundation-datepicker\"\nimport \"src/decidim/foundation_datepicker_locales\"\nimport \"src/decidim/vendor/modernizr\"\nimport \"social-share-button\"\n\nimport \"src/decidim/input_tags\"\nimport \"src/decidim/input_hashtags\"\nimport \"src/decidim/input_mentions\"\nimport \"src/decidim/input_multiple_mentions\"\nimport \"src/decidim/input_character_counter\"\nimport \"src/decidim/input_autojump\"\nimport \"src/decidim/index\"\nimport \"src/decidim/history\"\nimport \"src/decidim/callout\"\nimport \"src/decidim/clipboard\"\nimport \"src/decidim/append_elements\"\nimport \"src/decidim/user_registrations\"\nimport \"src/decidim/account_form\"\nimport \"src/decidim/data_picker\"\nimport \"src/decidim/dropdowns_menus\"\nimport \"src/decidim/append_redirect_url_to_modals\"\nimport \"src/decidim/form_validator\"\nimport \"src/decidim/ajax_modals\"\nimport \"src/decidim/conferences\"\nimport \"src/decidim/tooltip_keep_on_hover\"\nimport \"src/decidim/diff_mode_dropdown\"\nimport \"src/decidim/conversations\"\nimport \"src/decidim/delayed\"\nimport \"src/decidim/icon\"\nimport \"src/decidim/vizzs\"\nimport \"src/decidim/responsive_horizontal_tabs\"\nimport \"src/decidim/security/selfxss_warning\"\nimport \"src/decidim/session_timeouter\"\nimport \"src/decidim/configuration\"\nimport \"src/decidim/floating_help\"\nimport \"src/decidim/confirm\"\nimport \"src/decidim/comments/comments\"\nimport \"src/decidim/results_listing\"\nimport \"src/decidim/represent_user_group\"\nimport \"src/decidim/impersonation\"\nimport \"src/decidim/start_conversation_dialog\"\nimport \"src/decidim/notifications\"\nimport \"src/decidim/identity_selector_dialog\"\nimport \"src/decidim/gallery\"\n\n// CSS\nimport \"entrypoints/decidim_core.scss\"\n\n// Import from the Rails instance application\nimport \"src/decidim/decidim_application\"\n\n// Images\nrequire.context(\"../images\", true)\n\n// This needs to be loaded after confirm dialog to bind properly\nRails.start()\n\n","/**\n * Since the delete account has a modal to confirm it we need to copy the content of the\n * reason field to the hidden field in the form inside the modal.\n */\n$(() => {\n const $deleteAccountForm = $(\".delete-account\");\n const $deleteAccountModalForm = $(\".delete-account-modal\");\n\n if ($deleteAccountForm.length > 0) {\n const $openModalButton = $(\".open-modal-button\");\n const $modal = $(\"#deleteConfirm\");\n\n $openModalButton.on(\"click\", (event) => {\n try {\n const reasonValue = $deleteAccountForm.find(\"textarea#delete_account_delete_reason\").val();\n $deleteAccountModalForm.find(\"input#delete_account_delete_reason\").val(reasonValue);\n $modal.foundation(\"open\");\n } catch (error) {\n console.error(error); // eslint-disable-line no-console\n }\n\n event.preventDefault();\n event.stopPropagation();\n return false;\n });\n }\n});\n","import \"@zeitiger/appendaround\"\n\n$(() => {\n let $appendableElements = $(\".js-append\");\n $appendableElements.appendAround();\n})\n","/* eslint-disable multiline-ternary, no-ternary */\n\n/*\n *\n * This is used to make sure users are redirected to\n * the expected URL after sign in.\n *\n * When a button or link trigger a login modal we capture\n * the event and inject the URL where the user should\n * be redirected after sign in (the redirect_url param).\n *\n * The code is injected to any form or link in the modal\n * and when the modal is closed we remove the injected\n * code.\n *\n * In order for this to work the button or link must have\n * a data-open attribute with the ID of the modal to open\n * and a data-redirect-url attribute with the URL to redirect\n * the user. If any of this is missing no code will be\n * injected.\n *\n */\n$(() => {\n const removeUrlParameter = (url, parameter) => {\n const urlParts = url.split(\"?\");\n\n if (urlParts.length >= 2) {\n // Get first part, and remove from array\n const urlBase = urlParts.shift();\n\n // Join it back up\n const queryString = urlParts.join(\"?\");\n\n const prefix = `${encodeURIComponent(parameter)}=`;\n const parts = queryString.split(/[&;]/g);\n\n // Reverse iteration as may be destructive\n for (let index = parts.length - 1; index >= 0; index -= 1) {\n // Idiom for string.startsWith\n if (parts[index].lastIndexOf(prefix, 0) !== -1) {\n parts.splice(index, 1);\n }\n }\n\n if (parts.length === 0) {\n return urlBase;\n }\n\n return `${urlBase}?${parts.join(\"&\")}`;\n }\n\n return url;\n }\n\n $(document).on(\"click.zf.trigger\", (event) => {\n const target = `#${$(event.target).data(\"open\")}`;\n const redirectUrl = $(event.target).data(\"redirectUrl\");\n\n if (target && redirectUrl) {\n $(\"\").\n attr(\"id\", \"redirect_url\").\n attr(\"name\", \"redirect_url\").\n attr(\"value\", redirectUrl).\n appendTo(`${target} form`);\n\n $(`${target} a`).attr(\"href\", (index, href) => {\n const querystring = jQuery.param({\"redirect_url\": redirectUrl});\n return href + (href.match(/\\?/) ? \"&\" : \"?\") + querystring;\n });\n }\n });\n\n $(document).on(\"closed.zf.reveal\", (event) => {\n $(\"#redirect_url\", event.target).remove();\n $(\"a\", event.target).attr(\"href\", (index, href) => {\n if (href && href.indexOf(\"redirect_url\") !== -1) {\n return removeUrlParameter(href, \"redirect_url\");\n }\n\n return href;\n });\n });\n});\n","/**\n * Improves the accessibility of the callout messages for screen readers. Not\n * all screen readers would announce the callout alert contents after the page\n * reload without this.\n */\n\n$(() => {\n const $callout = $('.callout[role=\"alert\"]:first');\n if ($callout.length > 0) {\n setTimeout(() => {\n // The content insertion is to try to hint some of the screen readers\n // that the alert content has changed and needs to be announced.\n $callout.attr(\"tabindex\", \"0\").focus().html(`${$callout.html()} `);\n }, 500);\n }\n});\n","import select from \"select\";\n\n/**\n * This provides functionality to add clipboard copy functionality to buttons\n * on the page. The element to be copied from has to be defined for the button\n * using a `data` attribute and the target element has to be a form input.\n *\n * Usage:\n * 1. Create the button:\n * \n *\n * 2. Make sure the target element exists on the page:\n * \n *\n * Options through data attributes:\n * - `data-clipboard-copy` = The jQuery selector for the target input element\n * where text will be copied from.\n * - `data-clipboard-copy-label` = The label that will be shown in the button\n * after a succesful copy.\n * - `data-clipboard-copy-message` = The text that will be announced to screen\n * readers after a successful copy.\n */\n\n// How long the \"copied\" text is shown in the copy element after successful\n// copy.\nconst CLIPBOARD_COPY_TIMEOUT = 5000;\n\n$(() => {\n $(document).on(\"click\", \"[data-clipboard-copy]\", (ev) => {\n const $el = $(ev.target);\n if (!$el.data(\"clipboard-copy\") || $el.data(\"clipboard-copy\").length < 1) {\n return;\n }\n\n const $input = $($el.data(\"clipboard-copy\"));\n if ($input.length < 1 || !$input.is(\"input, textarea, select\")) {\n return;\n }\n\n // Get the available text to clipboard.\n const selectedText = select($input[0]);\n if (!selectedText || selectedText.length < 1) {\n return;\n }\n\n // Move the selected text to clipboard.\n const $temp = $(``).css({\n width: 1,\n height: 1\n });\n $el.after($temp);\n $temp.select();\n\n const copyDone = () => {\n $temp.remove();\n $el.focus();\n };\n try {\n // document.execCommand is deprecated but the Clipboard API is not\n // supported by IE (which unfortunately is still a thing).\n if (!document.execCommand(\"copy\")) {\n return;\n }\n } catch (err) {\n copyDone();\n return;\n }\n copyDone();\n\n // Change the label to indicate the copying was successful.\n const label = $el.data(\"clipboard-copy-label\");\n if (label) {\n let to = $el.data(\"clipboard-copy-label-timeout\");\n if (to) {\n clearTimeout(to);\n }\n\n if (!$el.data(\"clipboard-copy-label-original\")) {\n $el.data(\"clipboard-copy-label-original\", $el.html());\n }\n\n $el.html(label);\n to = setTimeout(() => {\n $el.html($el.data(\"clipboard-copy-label-original\"));\n $el.removeData(\"clipboard-copy-label-original\");\n $el.removeData(\"clipboard-copy-label-timeout\");\n }, CLIPBOARD_COPY_TIMEOUT);\n $el.data(\"clipboard-copy-label-timeout\", to)\n }\n\n // Alert the screen reader what just happened (the link was copied).\n let message = $el.data(\"clipboard-copy-message\");\n if (message) {\n let $msg = $el.data(\"clipboard-message-element\");\n if ($msg) {\n if ($msg.html() === message) {\n // Try to hint the screen reader to re-read the text in the message\n // element.\n message += \" \";\n }\n } else {\n $msg = $('
');\n $el.after($msg);\n $el.data(\"clipboard-message-element\", $msg);\n }\n\n // Add the non breaking space always to content to try to force the\n // screen reader to reannounce the added text.\n $msg.html(message);\n }\n });\n});\n","/* eslint-disable no-invalid-this */\n\nimport Foundation from \"foundation-sites\"\n\n$(() => {\n // True if small devices\n if (!Foundation.MediaQuery.atLeast(\"medium\")) {\n const $speaker = $(\".js-conference\")\n\n $speaker.hover(function () {\n const top = $(window).scrollTop() + ($(window).height() * 0.1)\n $(this).find(\".js-bio\").css(\"top\", top)\n })\n }\n});\n","/**\n * Scroll smoothly to the last message automatically when the page is fully loaded.\n * To apply this to a page, at least one element must have the class \"scroll-to-last-message\".\n * @returns {void}\n */\nconst scrollToLastMessage = function() {\n if ($(\".scroll-to-last-message\").length > 0) {\n window.scrollTo({\n top: $(\".conversation-chat:last-child\").offset().top,\n behavior: \"smooth\"\n });\n }\n}\n\n$(document).ready(() => {\n scrollToLastMessage();\n});\n","$(() => {\n const $allDiffViews = $(\".row.diff_view\");\n\n $(document).on(\"click\", \".diff-view-by a.diff-view-mode\", (event) => {\n event.preventDefault();\n const $target = $(event.target)\n let type = \"escaped\";\n const $selected = $target.parents(\".is-dropdown-submenu-parent\").find(\"#diff-view-selected\");\n if ($selected.text().trim() === $target.text().trim()) {\n return;\n }\n\n $selected.text($target.text());\n\n if ($target.attr(\"id\") === \"diff-view-unified\") {\n if ($(\".row.diff_view_split_escaped\").hasClass(\"hide\")) {\n type = \"unescaped\";\n }\n\n $allDiffViews.addClass(\"hide\");\n $(`.row.diff_view_unified_${type}`).removeClass(\"hide\");\n }\n if ($target.attr(\"id\") === \"diff-view-split\") {\n if ($(\".row.diff_view_unified_escaped\").hasClass(\"hide\")) {\n type = \"unescaped\";\n }\n\n $allDiffViews.addClass(\"hide\");\n $(`.row.diff_view_split_${type}`).removeClass(\"hide\");\n }\n })\n\n $(document).on(\"click\", \".diff-view-by a.diff-view-html\", (event) => {\n event.preventDefault();\n const $target = $(event.target);\n $target.parents(\".is-dropdown-submenu-parent\").find(\"#diff-view-selected\").text($target.text());\n const $visibleDiffViewsId = $allDiffViews.not(\".hide\").first().attr(\"id\").split(\"_\").slice(1, -1).join(\"_\");\n const $visibleDiffViews = $allDiffViews.filter(`[id*=${$visibleDiffViewsId}]`)\n\n if ($target.attr(\"id\") === \"escaped-html\") {\n $visibleDiffViews.filter(\"[id$=_unescaped]\").addClass(\"hide\");\n $visibleDiffViews.filter(\"[id$=_escaped]\").removeClass(\"hide\");\n }\n if ($target.attr(\"id\") === \"unescaped-html\") {\n $visibleDiffViews.filter(\"[id$=_escaped]\").addClass(\"hide\");\n $visibleDiffViews.filter(\"[id$=_unescaped]\").removeClass(\"hide\");\n }\n })\n});\n","/* eslint-disable require-jsdoc */\n\n// This will apply some fixes for the Foundation dropdown menu element\n// according to W3C instructions at:\n// https://www.w3.org/TR/wai-aria-practices/examples/menu-button/menu-button-links.html\n//\n// NOTE:\n// This needs to run AFTER Foundation has been initialized because those\n// initializers will affect the drop down menu elements.\nexport default function fixDropdownMenus() {\n $(\"[data-dropdown-menu]\").each((_i, element) => {\n // This will break navigation on macOS VoiceOver app since it will let the\n // user to focus on the li element instead of the element where we\n // actually need the focus to be in.\n $(\"li.is-dropdown-submenu-parent\", element).removeAttr(\"aria-haspopup\").removeAttr(\"aria-label\");\n // Foundation marks the wrong role for the submenu elements\n $(\"ul.is-dropdown-submenu\", element).attr(\"role\", \"menu\");\n })\n}\n\n// Ensure the first element is always focused when a dropdown is opened as\n// this would not always happen when using a screen reader. If this is not\n// done, the screen reader will stay quiet when the menu opens which can lead\n// to the blind user not understanding the menu has opened.\n$(() => {\n $(\"[data-dropdown-menu]\").on(\"show.zf.dropdownMenu\", (_i, element) => {\n $(\"li:first > a\", element).focus();\n });\n})\n","/* eslint-disable require-jsdoc */\n\nexport default function updateExternalDomainLinks($target) {\n const whitelist = window.Decidim.config.get(\"external_domain_whitelist\")\n\n if (window.location.pathname === \"/link\") {\n return;\n }\n\n $(\"a\", $target).filter((_i, link) => {\n const $link = $(link);\n if (!$link[0].hasAttribute(\"href\") || $link.parents(\".ql-editor\").length > 0) {\n return false;\n }\n\n const parts = $link.attr(\"href\").match(/^(([a-z]+):)?\\/\\/([^/:]+)(:[0-9]*)?(\\/.*)?$/) || null;\n if (!parts) {\n return false;\n }\n\n const domain = parts[3].replace(/^www\\./, \"\")\n if (whitelist.includes(domain)) {\n return false;\n }\n\n return true;\n }).each((_n, link) => {\n const $link = $(link);\n const externalHref = `/link?external_url=${encodeURIComponent($link.attr(\"href\"))}`;\n $link.attr(\"href\", externalHref)\n $link.attr(\"data-remote\", true)\n });\n}\n","import icon from \"src/decidim/icon\"\n\nconst EXCLUDE_CLASSES = [\n \"card--list__data__icon\",\n \"footer-social__icon\",\n \"logo-cityhall\"\n];\nconst EXCLUDE_REL = [\"license\", \"decidim\"];\n\nconst DEFAULT_MESSAGES = {\n externalLink: \"External link\"\n};\nlet MESSAGES = DEFAULT_MESSAGES;\n\nexport default class ExternalLink {\n static configureMessages(messages) {\n MESSAGES = $.extend(DEFAULT_MESSAGES, messages);\n }\n\n constructor(link) {\n this.$link = link;\n\n this.setup();\n }\n\n setup() {\n if (EXCLUDE_CLASSES.some((cls) => this.$link.hasClass(cls))) {\n return;\n }\n if (\n EXCLUDE_REL.some((rel) => {\n const linkRels = `${this.$link.attr(\"rel\")}`.split(\" \");\n return linkRels.indexOf(rel) > -1;\n })\n ) {\n return;\n }\n\n this.$link.addClass(\"external-link-container\");\n let spacer = \" \";\n if (this.$link.text().trim().length < 1) {\n // Fixes image links extra space\n spacer = \"\";\n }\n this.$link.append(`${spacer}${this.generateElement()}`);\n }\n\n generateElement() {\n let content = `${this.generateIcon()}${this.generateScreenReaderLabel()}`;\n\n return `${content}`;\n }\n\n generateIcon() {\n return icon(\"external-link\");\n }\n\n generateScreenReaderLabel() {\n return `(${MESSAGES.externalLink})`;\n }\n}\n","$(function() {\n if (!window.localStorage) {\n return;\n }\n\n let getDismissedHelpers = () => {\n let serialized = localStorage.getItem(\"dismissedHelpers\");\n if (!serialized) {\n return [];\n }\n\n return serialized.split(\",\");\n };\n\n let addDismissedHelper = (id) => {\n let dismissedHelpers = getDismissedHelpers();\n\n if (!dismissedHelpers.includes(id)) {\n localStorage.setItem(\n \"dismissedHelpers\",\n [...dismissedHelpers, id].join(\",\")\n );\n }\n };\n\n let dismissedHelpers = getDismissedHelpers();\n\n $(\".floating-helper-container\").each((_index, elem) => {\n let id = $(elem).data(\"help-id\");\n\n $(\n \".floating-helper__trigger, .floating-helper__content-close\",\n elem\n ).on(\"click\", (ev) => {\n ev.preventDefault();\n });\n\n if (!dismissedHelpers.includes(id)) {\n $(\".floating-helper\", elem).foundation(\"toggle\");\n $(\".floating-helper__wrapper\", elem).foundation(\"toggle\");\n\n $(\".floating-helper\", elem).on(\"off.zf.toggler\", () => {\n addDismissedHelper(id);\n });\n }\n });\n});\n","const DEFAULT_MESSAGES = {\n correctErrors: \"There are errors on the form, please correct them.\"\n};\nlet MESSAGES = DEFAULT_MESSAGES;\n\nexport default class FormValidator {\n static configureMessages(messages) {\n MESSAGES = $.extend(DEFAULT_MESSAGES, messages);\n }\n\n constructor(form) {\n this.$form = form;\n\n this.$form.on(\"form-error.decidim\", () => {\n this.handleError();\n });\n }\n\n handleError() {\n this.announceFormError();\n\n $(\".is-invalid-input:first\", this.$form).focus();\n }\n\n /**\n * This announces immediately to the screen reader that there are errors on\n * the form that need to be fixed. Does not work on all screen readers but\n * works e.g. in Windows+Firefox+NVDA and macOS+Safari+VoiceOver\n * combinations.\n *\n * @returns {undefined}\n */\n announceFormError() {\n let $announce = $(\".sr-announce\", this.$form);\n if ($announce.length > 0) {\n $announce.remove();\n }\n $announce = $(\"
\");\n $announce.attr(\"class\", \"sr-announce show-for-sr\");\n $announce.attr(\"aria-live\", \"assertive\");\n this.$form.prepend($announce);\n\n setTimeout(() => {\n $announce.text(MESSAGES.correctErrors);\n }, 100);\n }\n}\n\n$(() => {\n $(\"form\").each((_i, el) => {\n $(el).data(\"form-validator\", new FormValidator($(el)));\n });\n $(document).on(\"forminvalid.zf.abide\", function(_ev, form) {\n form.trigger(\"form-error.decidim\");\n })\n});\n","const DEFAULT_ATTRIBUTES = {\n role: \"img\",\n \"aria-hidden\": \"true\"\n};\n\n/**\n * Generates a Decidim icon element and returns it as a string.\n * @param {String} iconKey - the key of the icon to be generated\n * @param {Object} attributes - extra attributes to define for the icon SVG\n * @param {int} wait - number of milliseconds to wait before executing the function.\n * @private\n * @returns {Void} - Returns nothing.\n */\nexport default function icon(iconKey, attributes = {}) {\n const iconAttributes = $.extend(DEFAULT_ATTRIBUTES, attributes);\n const title = iconAttributes.title || iconAttributes.ariaLabel;\n Reflect.deleteProperty(iconAttributes, \"title\");\n\n const htmlAttributes = {\n \"class\": `icon icon--${iconKey}`\n };\n Object.keys(iconAttributes).forEach((key) => {\n // Convert the key to dash-format.\n const newKey = key.replace(/([A-Z])/g, (ucw) => `-${ucw[0].toLowerCase()}`);\n if (typeof htmlAttributes[key] === \"undefined\") {\n htmlAttributes[newKey] = iconAttributes[key];\n } else {\n htmlAttributes[newKey] = `${htmlAttributes[newKey]} ${iconAttributes[key]}`;\n }\n });\n\n const iconsPath = window.Decidim.config.get(\"icons_path\");\n const elHtml = ``;\n const $el = $(elHtml);\n if (title) {\n $el.prepend(`${title}`);\n } else {\n // This keeps accessibility audit tools happy\n $el.prepend(`${iconKey}`);\n // Force hidden if title is not defined\n htmlAttributes[\"aria-hidden\"] = \"true\";\n }\n $el.attr(htmlAttributes);\n\n return $(\"
\").append($el).html();\n}\n","/**\n * Makes the #select-identity-button to open a popup for the user to\n * select with which identity he wants to perform an action.\n *\n */\n$(() => {\n let button = $(\"#select-identity-button\"),\n identitiesUrl = null,\n userIdentitiesDialog = $(\"#user-identities\");\n\n if (userIdentitiesDialog.length) {\n identitiesUrl = userIdentitiesDialog.data(\"reveal-identities-url\");\n\n button.click(function () {\n $.ajax(identitiesUrl).done(function(response) {\n userIdentitiesDialog.html(response).foundation(\"open\");\n button.trigger(\"ajax:success\")\n });\n });\n }\n});\n\n\n/**\n * Manage the identity selector for endorsements.\n *\n */\n$(() => {\n $(\"#select-identity-button\").on(\"ajax:success\", function() {\n // once reveal popup has been rendered register event callbacks\n $(\"#user-identities ul.reveal__list li\").each(function(index, elem) {\n let liTag = $(elem)\n liTag.on(\"click\", function() {\n let method = liTag.data(\"method\"),\n urlDataAttr = null;\n if (method === \"POST\") {\n urlDataAttr = \"create_url\";\n } else {\n urlDataAttr = \"destroy_url\";\n }\n $.ajax({\n url: liTag.data(urlDataAttr),\n method: method,\n dataType: \"script\",\n success: function() {\n if (liTag.hasClass(\"selected\")) {\n liTag.removeClass(\"selected\")\n liTag.find(\".icon--circle-check\").addClass(\"invisible\")\n liTag.data(\"method\", \"POST\")\n } else {\n liTag.addClass(\"selected\")\n liTag.find(\".icon--circle-check\").removeClass(\"invisible\")\n liTag.data(\"method\", \"DELETE\")\n }\n }\n })\n })\n });\n });\n})\n","import moment from \"moment\"\n\n$(() => {\n const $impersonationWarning = $(\".impersonation-warning\");\n if ($impersonationWarning.length) {\n const endsAt = moment($impersonationWarning.data(\"session-ends-at\"));\n const exitInterval = setInterval(() => {\n const diff = (endsAt - moment()) / 60000;\n const diffInMinutes = Math.round(diff);\n $impersonationWarning.find(\".minutes\").html(diffInMinutes);\n\n if (diff <= 0) {\n window.location.reload();\n }\n }, 1000);\n\n // Prevent reload when page is already unloading, otherwise it may cause infinite reloads.\n window.addEventListener(\"beforeunload\", () => {\n clearInterval(exitInterval);\n return;\n });\n }\n});\n","/* eslint-disable no-invalid-this */\n\nimport svg4everybody from \"svg4everybody\"\nimport formDatePicker from \"src/decidim/form_datepicker\"\nimport fixDropdownMenus from \"src/decidim/dropdowns_menus\"\nimport createQuillEditor from \"src/decidim/editor\"\nimport Configuration from \"src/decidim/configuration\"\nimport ExternalLink from \"src/decidim/external_link\"\nimport updateExternalDomainLinks from \"src/decidim/external_domain_warning\"\nimport InputCharacterCounter from \"src/decidim/input_character_counter\"\nimport FormValidator from \"src/decidim/form_validator\"\nimport CommentsComponent from \"src/decidim/comments/comments.component\"\nimport DataPicker from \"src/decidim/data_picker\"\nimport FormFilterComponent from \"src/decidim/form_filter\"\nimport addInputEmoji from \"src/decidim/input_emoji\"\n\nwindow.Decidim = window.Decidim || {};\nwindow.Decidim.config = new Configuration()\nwindow.Decidim.ExternalLink = ExternalLink;\nwindow.Decidim.InputCharacterCounter = InputCharacterCounter;\nwindow.Decidim.FormValidator = FormValidator;\nwindow.Decidim.DataPicker = DataPicker;\nwindow.Decidim.CommentsComponent = CommentsComponent;\nwindow.Decidim.addInputEmoji = addInputEmoji;\n\n$(() => {\n window.theDataPicker = new DataPicker($(\".data-picker\"));\n\n $(document).foundation();\n\n fixDropdownMenus();\n\n svg4everybody();\n\n // Prevent data-open buttons e.g. from submitting the underlying form in\n // authorized action buttons.\n $(\"[data-open]\").on(\"click\", (event) => {\n event.preventDefault();\n });\n\n formDatePicker();\n\n $(\".editor-container\").each((_idx, container) => {\n createQuillEditor(container);\n });\n\n $('a[target=\"_blank\"]').each((_i, elem) => {\n const $link = $(elem);\n $link.data(\"external-link\", new ExternalLink($link));\n });\n\n // Mount comments component\n $(\"[data-decidim-comments]\").each((_i, el) => {\n const $el = $(el);\n const comments = new CommentsComponent($el, $el.data(\"decidim-comments\"));\n comments.mountComponent();\n $(el).data(\"comments\", comments);\n });\n\n $(\"form.new_filter\").each(function () {\n const formFilter = new FormFilterComponent($(this));\n\n formFilter.mountComponent();\n })\n\n updateExternalDomainLinks($(\"body\"))\n\n addInputEmoji()\n});\n","$(() => {\n const $inputs = $(\"input[data-autojump]\");\n const DELETE_KEY_CODE = 8;\n\n // Initialize\n $inputs.on(\"keydown\", (event) => {\n // Don't do anything if there is selected text\n if (event.target.selectionStart !== event.target.selectionEnd) {\n return;\n }\n\n if (event.originalEvent.key.length === 1 && event.target.dataset.jumpNext) {\n if (\n event.target.value.length ===\n parseInt(event.target.dataset.maxLength, 10)\n ) {\n event.preventDefault();\n setTimeout(() => {\n const next = $(event.target.dataset.jumpNext);\n next.val(event.originalEvent.key);\n next.trigger(\"focus\");\n }, 1);\n }\n } else if (\n event.originalEvent.keyCode === DELETE_KEY_CODE &&\n event.target.dataset.jumpPrev\n ) {\n if (event.target.value.length === 0) {\n event.preventDefault();\n setTimeout(() => {\n const prev = $(event.target.dataset.jumpPrev);\n prev.val(prev.val().slice(0, -1));\n prev.trigger(\"focus\");\n }, 1);\n }\n }\n });\n});\n","import { EmojiButton } from \"@joeattardi/emoji-button\";\n\n// eslint-disable-next-line require-jsdoc\nexport default function addInputEmoji() {\n const containers = document.querySelectorAll(\"[data-input-emoji]\");\n\n if (containers.length) {\n containers.forEach((elem) => {\n const picker = new EmojiButton({\n position: \"bottom-end\"\n });\n\n const wrapper = document.createElement(\"div\");\n wrapper.className = \"emoji__container\"\n const btnContainer = document.createElement(\"div\");\n btnContainer.className = \"emoji__trigger\"\n btnContainer.innerHTML = ''\n\n elem.parentNode.insertBefore(wrapper, elem);\n wrapper.appendChild(elem);\n wrapper.appendChild(btnContainer);\n\n btnContainer.addEventListener(\"click\", () => picker.togglePicker(btnContainer))\n\n picker.on(\"emoji\", ({ emoji }) => {\n elem.value += ` ${emoji} `\n\n const event = new Event(\"emoji.added\");\n elem.dispatchEvent(event);\n });\n })\n }\n};\n","/* eslint no-unused-vars: 0 */\nimport Tribute from \"src/decidim/vendor/tribute\"\n\n$(() => {\n const $multipleMentionContainer = $(\".js-multiple-mentions\");\n const $multipleMentionRecipientsContainer = $(\".js-multiple-mentions-recipients\");\n const nodatafound = $multipleMentionContainer.attr(\"data-noresults\");\n const directMessageDisabled = $multipleMentionContainer.attr(\"data-direct-messages-disabled\");\n\n const maxRecipients = 9;\n let mentionsCount = 0;\n\n /* eslint no-unused-vars: 0 */\n let deleteRecipient = function(element) {\n // Remove recipient\n element.remove();\n mentionsCount -= 1;\n // In case mentions container disable, enable again\n if ($multipleMentionContainer.prop(\"disabled\")) {\n $multipleMentionContainer.prop(\"disabled\", false);\n }\n };\n\n let noMatchTemplate = null\n if (nodatafound) {\n noMatchTemplate = () => `
  • ${nodatafound}
  • `;\n }\n\n // Returns a function, that, as long as it continues to be invoked, will not\n // be triggered. The function will be called after it stops being called for\n // N milliseconds\n /* eslint no-invalid-this: 0 */\n /* eslint consistent-this: 0 */\n /* eslint prefer-reflect: 0 */\n const debounce = function(callback, wait) {\n let timeout = null;\n return (...args) => {\n const context = this;\n clearTimeout(timeout);\n timeout = setTimeout(() => callback.apply(context, args), wait);\n };\n }\n\n /* eslint no-use-before-define: [\"error\", { \"variables\": false }]*/\n /* eslint no-unused-expressions: 0 */\n let remoteSearch = function(text, cb) {\n let exclusionIds = [];\n $multipleMentionRecipientsContainer.find(\"input[name^='recipient_id']\").each(function(index) {\n exclusionIds.push($(this).val());\n });\n let query = `{users(filter:{wildcard:\"${text}\",excludeIds:[${exclusionIds}]}){id,nickname,name,avatarUrl,__typename,...on UserGroup{membersCount},...on User{directMessagesEnabled}}}`;\n $.post(\"/api\", {query: query}).\n then((response) => {\n let data = response.data.users || {};\n cb(data)\n }).fail(function() {\n cb([])\n }).always(() => {\n // This function runs Tribute every single time you type something\n // So we must evalute DOM properties after each\n const $parent = $(tribute.current.element).parent();\n $parent.addClass(\"is-active\");\n\n // We need to move the container to the wrapper selected\n const $tribute = $parent.find(\".tribute-container\");\n // Remove the inline styles, relative to absolute positioning\n $tribute.removeAttr(\"style\");\n })\n };\n\n // tribute.js docs - http://github.com/zurb/tribute\n /* global Tribute*/\n /* eslint multiline-ternary: 0 */\n /* eslint no-ternary: 0 */\n let tribute = new Tribute({\n autocompleteMode: true,\n // avoid overloading the API if the user types too fast\n values: debounce(function (text, cb) {\n remoteSearch(text, (users) => cb(users));\n }, 250),\n positionMenu: true,\n menuContainer: null,\n menuItemLimit: 10,\n fillAttr: \"nickname\",\n noMatchTemplate: noMatchTemplate,\n lookup: (item) => item.nickname + item.name,\n selectTemplate: function(item) {\n mentionsCount += 1;\n if (mentionsCount >= maxRecipients) {\n $multipleMentionContainer.prop(\"disabled\", true);\n }\n if (typeof item === \"undefined\") {\n return null;\n }\n // Set recipient profile view\n let recipientLabel = `\n \n `;\n\n // Append new recipient to DOM\n if (item.original.__typename === \"UserGroup\" || item.original.directMessagesEnabled === \"true\") {\n $multipleMentionRecipientsContainer.append($(recipientLabel));\n $multipleMentionContainer.val(\"\");\n }\n\n // In order to add tabindex accessibility control to each recipient in list\n $multipleMentionRecipientsContainer.find(\"label\").each(function(index) {\n $(this).find(\"div\").attr(\"tabIndex\", 0).attr(\"aria-controls\", 0).attr(\"aria-label\", \"Close\").attr(\"role\", \"tab\");\n });\n\n // Clean input\n return \"\";\n },\n menuItemTemplate: function(item) {\n let svg = \"\";\n let enabled = item.original.directMessagesEnabled === \"true\";\n if (window.Decidim && item.original.__typename === \"UserGroup\") {\n enabled = true;\n const iconsPath = window.Decidim.config.get(\"icons_path\");\n svg = `${item.original.membersCount}x `;\n }\n let disabledElementClass = enabled ? \"\" : \"disabled-tribute-element\";\n let disabledElementMessage = enabled ? \"\" : ` ${directMessageDisabled}`;\n return `
    \n \"author-avatar\"\n ${item.original.nickname}\n ${item.original.name}\n ${svg}\n ${disabledElementMessage}\n
    `;\n }\n });\n\n let setupEvents = function($element) {\n // DOM manipulation\n $element.on(\"focusin\", (event) => {\n // Set the parent container relative to the current element\n tribute.menuContainer = event.target.parentNode;\n });\n $element.on(\"focusout\", (event) => {\n let $parent = $(event.target).parent();\n\n if ($parent.hasClass(\"is-active\")) {\n $parent.removeClass(\"is-active\");\n }\n });\n $element.on(\"input\", (event) => {\n let $parent = $(event.target).parent();\n\n if (tribute.isActive) {\n // We need to move the container to the wrapper selected\n let $tribute = $(\".tribute-container\");\n $tribute.appendTo($parent);\n // Remove the inline styles, relative to absolute positioning\n $tribute.removeAttr(\"style\");\n // Parent adaptation\n $parent.addClass(\"is-active\");\n } else {\n $parent.removeClass(\"is-active\");\n }\n });\n };\n\n let setupRecipientEvents = function($element) {\n // Allow delete with click on element in recipients list\n $element.on(\"click\", (event) => {\n let $target = event.target.parentNode;\n if ($target.tagName === \"LABEL\") {\n deleteRecipient($target);\n }\n });\n // Allow delete with keypress on element in recipients list\n $element.on(\"keypress\", (event) => {\n let $target = event.target.parentNode;\n if ($target.tagName === \"LABEL\") {\n deleteRecipient($target);\n }\n });\n };\n\n // Call only if we have containter to bind events to\n if ($multipleMentionContainer.length) {\n setupEvents($multipleMentionContainer);\n tribute.attach($multipleMentionContainer);\n }\n\n // Call only if we have containter to bind events to\n if ($multipleMentionRecipientsContainer.length) {\n setupRecipientEvents($multipleMentionRecipientsContainer);\n }\n});\n","$(() => {\n const $notificationsBellIcon = $(\".title-bar .topbar__notifications\");\n const $wrapper = $(\".wrapper\");\n const $section = $wrapper.find(\"#notifications\");\n const $noNotificationsText = $(\".empty-notifications\");\n const $pagination = $wrapper.find(\"ul.pagination\");\n const FADEOUT_TIME = 500;\n\n const anyNotifications = () => $wrapper.find(\".card--widget\").length > 0;\n const emptyNotifications = () => {\n if (!anyNotifications()) {\n $section.remove();\n $noNotificationsText.removeClass(\"hide\");\n }\n };\n\n $section.on(\"click\", \".mark-as-read-button\", (event) => {\n const $item = $(event.target).parents(\".card--widget\");\n $item.fadeOut(FADEOUT_TIME, () => {\n $item.remove();\n emptyNotifications();\n });\n });\n\n $wrapper.on(\"click\", \".mark-all-as-read-button\", () => {\n $section.fadeOut(FADEOUT_TIME, () => {\n $pagination.remove();\n $notificationsBellIcon.removeClass(\"is-active\");\n $wrapper.find(\".card--widget\").remove();\n emptyNotifications();\n });\n });\n\n emptyNotifications();\n});\n","$(() => {\n const $checkbox = $(\".represent-user-group\").find(\"input#user_group\");\n const $userGroupFields = $(\".user-group-fields\");\n\n $checkbox.click(() => {\n const $select = $userGroupFields.find(\"select\");\n\n if (!$select.val()) {\n $userGroupFields.toggle();\n }\n\n if ($userGroupFields.is(\":visible\")) {\n $checkbox.prop(\"checked\", true);\n } else {\n $checkbox.prop(\"checked\", false);\n }\n });\n});\n","$(() => {\n const $responsiveTabBlock = $(\".responsive-tab-block\");\n\n $responsiveTabBlock.click((event) => {\n if (event.target.closest(\".is-active\") !== null) {\n event.preventDefault();\n if (window.innerWidth <= 639) {\n $responsiveTabBlock.toggleClass(\"expanded\");\n }\n }\n });\n});\n","import { pushState, registerCallback } from \"src/decidim/history\"\n\nconst initializeListingOptionsMenu = (options) => {\n $(document).on(\"click\", `${options.containerSelector} a`, (event) => {\n const $target = $(event.target);\n\n $target.parents(\".menu\").find(\"a:first\").text($target.text());\n\n pushState($target.attr(\"href\"));\n })\n\n registerCallback(options.callbackName, () => {\n const url = window.location.toString();\n const match = url.match(/${options.urlParameter}=([^&]*)/);\n const $targetMenu = $(`${options.containerSelector} .menu`);\n let value = $targetMenu.find(\".menu a:first\").data(options.dataAttribute);\n\n if (match) {\n value = match[1];\n }\n\n const linkText = $targetMenu.find(`.menu a[data-${options.dataAttribute}=\"${value}\"]`).text();\n\n $targetMenu.find(\"a:first\").text(linkText);\n });\n};\n\n$(() => {\n initializeListingOptionsMenu({\n containerSelector: \".order-by\",\n callbackName: \"orders\",\n urlParameter: \"order\",\n dataAttribute: \"order\"\n });\n initializeListingOptionsMenu({\n containerSelector: \".results-per-page\",\n callbackName: \"results_per_page\",\n urlParameter: \"per_page\",\n dataAttribute: \"per-page-option\"\n });\n});\n","/* eslint-disable no-console */\n\n$(() => {\n if (!console) {\n return;\n }\n\n const allMessages = window.Decidim.config.get(\"messages\");\n if (!allMessages) {\n return;\n }\n const messages = allMessages.selfxssWarning;\n\n console.log(`%c${messages.title}`, \"color:#f00;font-weight:bold;font-size:50px;\");\n console.log(`%c${messages.description}`, \"font-size:24px;\");\n});\n","$(() => {\n let addUsersConversationDialog = $(\"#user-conversations-add-modal\"),\n button = $(\"#start-conversation-dialog-button\");\n\n /* eslint no-unused-vars: 0 */\n if (addUsersConversationDialog.length) {\n let refreshUrl = addUsersConversationDialog.data(\"refresh-url\");\n\n button.click(function () {\n addUsersConversationDialog.foundation(\"open\");\n });\n }\n});\n","/* eslint-disable no-invalid-this */\n\n$(() => {\n\n // Foundation requires plugins to be initializated\n setTimeout(function() {\n\n const $tooltips = $(\".tooltip\")\n\n $tooltips.\n on(\"mouseover\", function() {\n $(`[data-keep-on-hover='true'][data-toggle='${this.id}']`).foundation(\"show\");\n }).\n on(\"mouseout\", function() {\n $(`[data-keep-on-hover='true'][data-toggle='${this.id}']`).foundation(\"hide\");\n })\n }, 0);\n});\n","$(() => {\n const $userRegistrationForm = $(\"#register-form\");\n const $userGroupFields = $userRegistrationForm.find(\".user-group-fields\");\n const inputSelector = 'input[name=\"user[sign_up_as]\"]';\n const newsletterSelector = 'input[type=\"checkbox\"][name=\"user[newsletter]\"]';\n const $newsletterModal = $(\"#sign-up-newsletter-modal\");\n\n\n const setGroupFieldsVisibility = (value) => {\n if (value === \"user\") {\n $userGroupFields.hide();\n } else {\n $userGroupFields.show();\n }\n }\n\n const checkNewsletter = (check) => {\n $userRegistrationForm.find(newsletterSelector).prop(\"checked\", check);\n $newsletterModal.data(\"continue\", true);\n $newsletterModal.foundation(\"close\");\n $userRegistrationForm.submit();\n }\n\n setGroupFieldsVisibility($userRegistrationForm.find(`${inputSelector}:checked`).val());\n\n $userRegistrationForm.on(\"change\", inputSelector, (event) => {\n const value = event.target.value;\n\n setGroupFieldsVisibility(value);\n });\n\n $userRegistrationForm.on(\"submit\", (event) => {\n const newsletterChecked = $userRegistrationForm.find(newsletterSelector);\n if (!$newsletterModal.data(\"continue\")) {\n if (!newsletterChecked.prop(\"checked\")) {\n event.preventDefault();\n $newsletterModal.foundation(\"open\");\n }\n }\n });\n\n $newsletterModal.find(\".check-newsletter\").on(\"click\", (event) => {\n checkNewsletter($(event.target).data(\"check\"));\n });\n});\n","/* eslint-disable */\n\n/*! modernizr 3.3.1 (Custom Build) | MIT *\n * https://modernizr.com/download/?-setclasses !*/\n!function(n,e,s){function o(n,e){return typeof n===e}function a(){var n,e,s,a,i,l,r;for(var c in f)if(f.hasOwnProperty(c)){if(n=[],e=f[c],e.name&&(n.push(e.name.toLowerCase()),e.options&&e.options.aliases&&e.options.aliases.length))for(s=0;s 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar chunkIds = deferred[i][0];\n\t\tvar fn = deferred[i][1];\n\t\tvar priority = deferred[i][2];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every(function(key) { return __webpack_require__.O[key](chunkIds[j]); })) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = function(module) {\n\tvar getter = module && module.__esModule ?\n\t\tfunction() { return module['default']; } :\n\t\tfunction() { return module; };\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// define __esModule on exports\n__webpack_require__.r = function(exports) {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.nmd = function(module) {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","__webpack_require__.p = \"/decidim-packs/\";","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t\"decidim_core\": 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = function(chunkId) { return installedChunks[chunkId] === 0; };\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = function(parentChunkLoadingFunction, data) {\n\tvar chunkIds = data[0];\n\tvar moreModules = data[1];\n\tvar runtime = data[2];\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some(function(id) { return installedChunks[id] !== 0; })) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunkapp\"] = self[\"webpackChunkapp\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [\"vendors-node_modules_jquery_dist_jquery-exposed_js\",\"vendors-node_modules_bootstrap-tagsinput_dist_bootstrap-tagsinput_js-node_modules_rails_ujs_l-ee688c\",\"vendors-node_modules_d3_index_js\",\"vendors-node_modules_foundation-datepicker_js_locales_foundation-datepicker_ar_js-node_module-679306\",\"vendors-node_modules_joeattardi_emoji-button_dist_index_js-node_modules_zeitiger_appendaround-3ddad2\",\"_rbenv_versions_2_7_3_lib_ruby_gems_2_7_0_bundler_gems_decidim-04ca5ebdba87_decidim-core_app_-378ce2\",\"_rbenv_versions_2_7_3_lib_ruby_gems_2_7_0_bundler_gems_decidim-04ca5ebdba87_decidim-core_app_-63837c\",\"_rbenv_versions_2_7_3_lib_ruby_gems_2_7_0_bundler_gems_decidim-04ca5ebdba87_decidim-core_app_-5fdcc0\",\"_rbenv_versions_2_7_3_lib_ruby_gems_2_7_0_bundler_gems_decidim-04ca5ebdba87_decidim-core_app_-c47082\"], function() { return __webpack_require__(\"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/entrypoints/decidim_core.js\"); })\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n",""],"names":[],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"js/decidim_core.js","mappings":";;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACvBA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AAEA;AACA;AACA;AAAA;AAGA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAJA;AAAA;AAAA;AAKA;AACA;AACA;AACA;AAEA;AAAA;AAAA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAJA;AAAA;AAAA;AAKA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA;AAAA;AAAA;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AATA;AAAA;AAAA;AAUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAJA;AAAA;AAAA;AAMA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AALA;AAAA;AAAA;AAMA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AAEA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA;AAAA;AAAA;AASA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AARA;AAAA;AAAA;AAUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAJA;AAAA;AAAA;AAKA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAJA;AAAA;AAAA;AAMA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAJA;AAAA;AAAA;AAMA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAJA;AAAA;AAAA;AAMA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AALA;AAAA;AAAA;AAOA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AALA;AAAA;AAAA;AAOA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AE1SA;AACA;;AAEA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;;;;;;;;;ACnEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;AC1BA;AAEA;AACA;AACA;AACA;;;;;;;;;;ACLA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;;AAEA;AACA;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAMA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;;;;;;;;;;AClFA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;ACfA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;ACtHA;;AAEA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;;;;;;;;;;AChBA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;AChDA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;AC5BA;;AAEA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AChCA;AAEA;AAKA;AAEA;AACA;AACA;AACA;AAAA;AAOA;AAAA;AACA;AAEA;AACA;AAAA;AAAA;AAAA;AAEA;AACA;AAAA;AAAA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AAGA;AAEA;AACA;AAAA;AAAA;AAAA;AAGA;AACA;AAAA;AAAA;AAAA;AAGA;AACA;AAAA;AAAA;AAAA;AA3CA;AACA;AAAA;AAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACjBA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AAIA;AACA;AAEA;AAEA;AACA;AAEA;AAIA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC9CA;AACA;AACA;AACA;AAAA;AAOA;AAAA;AAAA;AACA;AAEA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AAGA;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA;AAAA;AAAA;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AAtCA;AACA;AAAA;AAAA;AAAA;AAAA;AAwCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;ACvDA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;;;;;;;;;;AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;AC3DA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;ACtBA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AAEA;AAEA;;AAEA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AAEA;AACA;;;;;;;;;;ACpEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;ACrCA;;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AAAA;AAAA;AAEA;AAAA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAAA;;;;;;;;;;;;;;AChCA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAAA;AAAA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AASA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;;;;;;;;;ACnMA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;;;;;;;;;;AClCA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;ACjBA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;ACXA;AAEA;AACA;AACA;AAEA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;ACxCA;;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;;;;;;;;;;ACfA;AACA;AACA;;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;;;;;;;;;;ACZA;;AAEA;AAEA;AACA;AAEA;AAEA;AAEA;AACA;AAEA;AACA;AACA;AACA;;;;;;;;;;ACjBA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;AC5CA;;AAEA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;;;;;ACJA;AACA;;AAEA;AACA;AAEA;;;;;;;;;;;;ACNA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC7BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AC7BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACPA;;;;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACNA;AACA;AACA;AACA;AACA;;;;;ACJA;;;;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AElDA;AACA;AACA;AACA;AACA","sources":["webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/ sync ^\\.\\/.*$","webpack://app/./app/packs/images/ sync ^\\.\\/.*$","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-comments/app/packs/src/decidim/comments/comments.component.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-comments/app/packs/src/decidim/comments/comments.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/entrypoints/decidim_core.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/account_form.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/append_elements.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/append_redirect_url_to_modals.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/callout.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/clipboard.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/conferences.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/conversations.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/diff_mode_dropdown.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/dropdowns_menus.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/external_domain_warning.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/external_link.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/floating_help.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/form_validator.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/icon.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/identity_selector_dialog.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/impersonation.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/index.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/input_autojump.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/input_emoji.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/input_multiple_mentions.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/notifications.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/represent_user_group.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/responsive_horizontal_tabs.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/results_listing.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/security/selfxss_warning.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/start_conversation_dialog.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/tooltip_keep_on_hover.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/user_registrations.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/src/decidim/vendor/modernizr.js","webpack://app/./app/packs/src/decidim/decidim_application.js","webpack://app/../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/entrypoints/decidim_core.scss?2b5b","webpack://app/webpack/bootstrap","webpack://app/webpack/runtime/chunk loaded","webpack://app/webpack/runtime/compat get default export","webpack://app/webpack/runtime/define property getters","webpack://app/webpack/runtime/global","webpack://app/webpack/runtime/hasOwnProperty shorthand","webpack://app/webpack/runtime/make namespace object","webpack://app/webpack/runtime/node module decorator","webpack://app/webpack/runtime/publicPath","webpack://app/webpack/runtime/jsonp chunk loading","webpack://app/webpack/before-startup","webpack://app/webpack/startup","webpack://app/webpack/after-startup"],"sourcesContent":["var map = {\n\t\"./decidim/avatar-multiuser.png\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/avatar-multiuser.png\",\n\t\"./decidim/brands/google.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/brands/google.svg\",\n\t\"./decidim/cc-badge.png\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/cc-badge.png\",\n\t\"./decidim/decidim-logo.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/decidim-logo.svg\",\n\t\"./decidim/default-avatar.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/default-avatar.svg\",\n\t\"./decidim/gamification/badges/decidim_gamification_badges_followers.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/gamification/badges/decidim_gamification_badges_followers.svg\",\n\t\"./decidim/gamification/badges/decidim_gamification_badges_invitations.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/gamification/badges/decidim_gamification_badges_invitations.svg\",\n\t\"./decidim/icons.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/icons.svg\",\n\t\"./decidim/pattern.png\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/pattern.png\",\n\t\"./decidim/placeholder.jpg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/placeholder.jpg\",\n\t\"./decidim/vendor/leaflet/layers-2x.png\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/leaflet/layers-2x.png\",\n\t\"./decidim/vendor/leaflet/layers.png\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/leaflet/layers.png\",\n\t\"./decidim/vendor/leaflet/marker-icon-2x.png\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/leaflet/marker-icon-2x.png\",\n\t\"./decidim/vendor/leaflet/marker-icon.png\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/leaflet/marker-icon.png\",\n\t\"./decidim/vendor/leaflet/marker-shadow.png\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/leaflet/marker-shadow.png\",\n\t\"./decidim/vendor/social-share-button/delicious.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/delicious.svg\",\n\t\"./decidim/vendor/social-share-button/douban.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/douban.svg\",\n\t\"./decidim/vendor/social-share-button/email.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/email.svg\",\n\t\"./decidim/vendor/social-share-button/facebook.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/facebook.svg\",\n\t\"./decidim/vendor/social-share-button/google_bookmark.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/google_bookmark.svg\",\n\t\"./decidim/vendor/social-share-button/google_plus.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/google_plus.svg\",\n\t\"./decidim/vendor/social-share-button/hacker_news.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/hacker_news.svg\",\n\t\"./decidim/vendor/social-share-button/linkedin.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/linkedin.svg\",\n\t\"./decidim/vendor/social-share-button/odnoklassniki.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/odnoklassniki.svg\",\n\t\"./decidim/vendor/social-share-button/pinterest.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/pinterest.svg\",\n\t\"./decidim/vendor/social-share-button/qq.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/qq.svg\",\n\t\"./decidim/vendor/social-share-button/reddit.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/reddit.svg\",\n\t\"./decidim/vendor/social-share-button/telegram.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/telegram.svg\",\n\t\"./decidim/vendor/social-share-button/tumblr.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/tumblr.svg\",\n\t\"./decidim/vendor/social-share-button/twitter.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/twitter.svg\",\n\t\"./decidim/vendor/social-share-button/vkontakte.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/vkontakte.svg\",\n\t\"./decidim/vendor/social-share-button/wechat.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/wechat.svg\",\n\t\"./decidim/vendor/social-share-button/weibo.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/weibo.svg\",\n\t\"./decidim/vendor/social-share-button/whatsapp.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/whatsapp.svg\",\n\t\"./decidim/vendor/social-share-button/xing.svg\": \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images/decidim/vendor/social-share-button/xing.svg\"\n};\n\n\nfunction webpackContext(req) {\n\tvar id = webpackContextResolve(req);\n\treturn __webpack_require__(id);\n}\nfunction webpackContextResolve(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\treturn map[req];\n}\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = \"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/images sync recursive ^\\\\.\\\\/.*$\";","var map = {\n\t\"./Oauth_logo.svg\": \"./app/packs/images/Oauth_logo.svg\",\n\t\"./feder-logo.png\": \"./app/packs/images/feder-logo.png\"\n};\n\n\nfunction webpackContext(req) {\n\tvar id = webpackContextResolve(req);\n\treturn __webpack_require__(id);\n}\nfunction webpackContextResolve(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\treturn map[req];\n}\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = \"./app/packs/images sync recursive ^\\\\.\\\\/.*$\";","/* eslint id-length: [\"error\", { \"exceptions\": [\"$\"] }] */\n\n/**\n * A plain Javascript component that handles the comments.\n *\n * @class\n * @augments Component\n */\n\n// This is necessary for testing purposes\nconst $ = window.$;\n\nimport { createCharacterCounter } from \"src/decidim/input_character_counter\"\nimport ExternalLink from \"src/decidim/external_link\"\nimport updateExternalDomainLinks from \"src/decidim/external_domain_warning\"\n\nexport default class CommentsComponent {\n constructor($element, config) {\n this.$element = $element;\n this.commentableGid = config.commentableGid;\n this.commentsUrl = config.commentsUrl;\n this.rootDepth = config.rootDepth;\n this.order = config.order;\n this.lastCommentId = config.lastCommentId;\n this.pollingInterval = config.pollingInterval || 15000;\n this.id = this.$element.attr(\"id\") || this._getUID();\n this.mounted = false;\n }\n\n /**\n * Handles the logic for mounting the component\n * @public\n * @returns {Void} - Returns nothing\n */\n mountComponent() {\n if (this.$element.length > 0 && !this.mounted) {\n this.mounted = true;\n this._initializeComments(this.$element);\n\n $(\".order-by__dropdown .is-submenu-item a\", this.$element).on(\"click.decidim-comments\", () => this._onInitOrder());\n }\n }\n\n /**\n * Handles the logic for unmounting the component\n * @public\n * @returns {Void} - Returns nothing\n */\n unmountComponent() {\n if (this.mounted) {\n this.mounted = false;\n this._stopPolling();\n\n $(\".add-comment .opinion-toggle .button\", this.$element).off(\"click.decidim-comments\");\n $(\".add-comment textarea\", this.$element).off(\"input.decidim-comments\");\n $(\".order-by__dropdown .is-submenu-item a\", this.$element).off(\"click.decidim-comments\");\n $(\".add-comment form\", this.$element).off(\"submit.decidim-comments\");\n $(\".add-comment textarea\", this.$element).each((_i, el) => el.removeEventListener(\"emoji.added\", this._onTextInput));\n }\n }\n\n /**\n * Adds a new thread to the comments section.\n * @public\n * @param {String} threadHtml - The HTML content for the thread.\n * @param {Boolean} fromCurrentUser - A boolean indicating whether the user\n * herself was the author of the new thread. Defaults to false.\n * @returns {Void} - Returns nothing\n */\n addThread(threadHtml, fromCurrentUser = false) {\n const $parent = $(\".comments:first\", this.$element);\n const $comment = $(threadHtml);\n const $threads = $(\".comment-threads\", this.$element);\n this._addComment($threads, $comment);\n this._finalizeCommentCreation($parent, fromCurrentUser);\n }\n\n /**\n * Adds a new reply to an existing comment.\n * @public\n * @param {Number} commentId - The ID of the comment for which to add the\n * reply to.\n * @param {String} replyHtml - The HTML content for the reply.\n * @param {Boolean} fromCurrentUser - A boolean indicating whether the user\n * herself was the author of the new reply. Defaults to false.\n * @returns {Void} - Returns nothing\n */\n addReply(commentId, replyHtml, fromCurrentUser = false) {\n const $parent = $(`#comment_${commentId}`);\n const $comment = $(replyHtml);\n const $replies = $(`#comment-${commentId}-replies`);\n this._addComment($replies, $comment);\n $replies.siblings(\".comment__additionalreply\").removeClass(\"hide\");\n this._finalizeCommentCreation($parent, fromCurrentUser);\n }\n\n /**\n * Generates a unique identifier for the form.\n * @private\n * @returns {String} - Returns a unique identifier\n */\n _getUID() {\n return `comments-${new Date().setUTCMilliseconds()}-${Math.floor(Math.random() * 10000000)}`;\n }\n\n /**\n * Initializes the comments for the given parent element.\n * @private\n * @param {jQuery} $parent The parent element to initialize.\n * @returns {Void} - Returns nothing\n */\n _initializeComments($parent) {\n $(\".add-comment\", $parent).each((_i, el) => {\n const $add = $(el);\n const $form = $(\"form\", $add);\n const $opinionButtons = $(\".opinion-toggle .button\", $add);\n const $text = $(\"textarea\", $form);\n\n $opinionButtons.on(\"click.decidim-comments\", this._onToggleOpinion);\n $text.on(\"input.decidim-comments\", this._onTextInput);\n\n $(document).trigger(\"attach-mentions-element\", [$text.get(0)]);\n\n $form.on(\"submit.decidim-comments\", () => {\n const $submit = $(\"button[type='submit']\", $form);\n\n $submit.attr(\"disabled\", \"disabled\");\n this._stopPolling();\n });\n\n if ($text.length && $text.get(0) !== null) {\n // Attach event to the DOM node, instead of the jQuery object\n $text.get(0).addEventListener(\"emoji.added\", this._onTextInput);\n }\n });\n\n this._pollComments();\n }\n\n /**\n * Adds the given comment element to the given target element and\n * initializes it.\n * @private\n * @param {jQuery} $target - The target element to add the comment to.\n * @param {jQuery} $container - The comment container element to add.\n * @returns {Void} - Returns nothing\n */\n _addComment($target, $container) {\n let $comment = $(\".comment\", $container);\n if ($comment.length < 1) {\n // In case of a reply\n $comment = $container;\n }\n this.lastCommentId = parseInt($comment.data(\"comment-id\"), 10);\n\n $target.append($container);\n $container.foundation();\n this._initializeComments($container);\n createCharacterCounter($(\".add-comment textarea\", $container));\n $container.find('a[target=\"_blank\"]').each((_i, elem) => {\n const $link = $(elem);\n $link.data(\"external-link\", new ExternalLink($link));\n });\n updateExternalDomainLinks($container)\n }\n\n /**\n * Finalizes the new comment creation after the comment adding finishes\n * successfully.\n * @private\n * @param {jQuery} $parent - The parent comment element to finalize.\n * @param {Boolean} fromCurrentUser - A boolean indicating whether the user\n * herself was the author of the new comment.\n * @returns {Void} - Returns nothing\n */\n _finalizeCommentCreation($parent, fromCurrentUser) {\n if (fromCurrentUser) {\n const $add = $(\"> .add-comment\", $parent);\n const $text = $(\"textarea\", $add);\n const characterCounter = $text.data(\"remaining-characters-counter\");\n $text.val(\"\");\n if (characterCounter) {\n characterCounter.updateStatus();\n }\n if (!$add.parent().is(\".comments\")) {\n $add.addClass(\"hide\");\n }\n }\n\n // Restart the polling\n this._pollComments();\n }\n\n /**\n * Sets a timeout to poll new comments.\n * @private\n * @returns {Void} - Returns nothing\n */\n _pollComments() {\n this._stopPolling();\n\n this.pollTimeout = setTimeout(() => {\n $.ajax({\n url: this.commentsUrl,\n method: \"GET\",\n contentType: \"application/javascript\",\n data: {\n \"commentable_gid\": this.commentableGid,\n \"root_depth\": this.rootDepth,\n order: this.order,\n after: this.lastCommentId\n }\n }).done(() => this._pollComments());\n }, this.pollingInterval);\n }\n\n /**\n * Stops polling for new comments.\n * @private\n * @returns {Void} - Returns nothing\n */\n _stopPolling() {\n if (this.pollTimeout) {\n clearTimeout(this.pollTimeout);\n }\n }\n\n /**\n * Sets the loading comments element visible in the view.\n * @private\n * @returns {Void} - Returns nothing\n */\n _setLoading() {\n const $container = $(\"> .comments-container\", this.$element);\n $(\"> .comments\", $container).addClass(\"hide\");\n $(\"> .loading-comments\", $container).removeClass(\"hide\");\n }\n\n /**\n * Event listener for the ordering links.\n * @private\n * @returns {Void} - Returns nothing\n */\n _onInitOrder() {\n this._stopPolling();\n this._setLoading();\n }\n\n /**\n * Event listener for the opinion toggle buttons.\n * @private\n * @param {Event} ev - The event object.\n * @returns {Void} - Returns nothing\n */\n _onToggleOpinion(ev) {\n let $btn = $(ev.target);\n if (!$btn.is(\".button\")) {\n $btn = $btn.parents(\".button\");\n }\n\n const $add = $btn.closest(\".add-comment\");\n const $form = $(\"form\", $add);\n const $opinionButtons = $(\".opinion-toggle .button\", $add);\n const $selectedState = $(\".opinion-toggle .selected-state\", $add);\n const $alignment = $(\".alignment-input\", $form);\n\n $opinionButtons.removeClass(\"is-active\").attr(\"aria-pressed\", \"false\");\n $btn.addClass(\"is-active\").attr(\"aria-pressed\", \"true\");\n\n if ($btn.is(\".opinion-toggle--ok\")) {\n $alignment.val(1);\n } else if ($btn.is(\".opinion-toggle--meh\")) {\n $alignment.val(0);\n } else if ($btn.is(\".opinion-toggle--ko\")) {\n $alignment.val(-1);\n }\n\n // Announce the selected state for the screen reader\n $selectedState.text($btn.data(\"selected-label\"));\n }\n\n /**\n * Event listener for the comment field text input.\n * @private\n * @param {Event} ev - The event object.\n * @returns {Void} - Returns nothing\n */\n _onTextInput(ev) {\n const $text = $(ev.target);\n const $add = $text.closest(\".add-comment\");\n const $form = $(\"form\", $add);\n const $submit = $(\"button[type='submit']\", $form);\n\n if ($text.val().length > 0) {\n $submit.removeAttr(\"disabled\");\n } else {\n $submit.attr(\"disabled\", \"disabled\");\n }\n }\n}\n","import \"src/decidim/comments/comments.component\"\n","/* eslint no-unused-vars: 0 */\n/* eslint id-length: [\"error\", { \"exceptions\": [\"$\"] }] */\n\nimport $ from \"jquery\"\nimport Quill from \"quill\"\nimport Rails from \"@rails/ujs\"\n\nimport \"core-js/stable\";\nimport \"regenerator-runtime/runtime\";\nimport morphdom from \"morphdom\"\n// Export variable to make it available in .js.erb templates\nwindow.morphdom = morphdom\nimport \"src/decidim/vendor/foundation-datepicker\"\nimport \"src/decidim/foundation_datepicker_locales\"\nimport \"src/decidim/vendor/modernizr\"\nimport \"social-share-button\"\n\nimport \"src/decidim/input_tags\"\nimport \"src/decidim/input_hashtags\"\nimport \"src/decidim/input_mentions\"\nimport \"src/decidim/input_multiple_mentions\"\nimport \"src/decidim/input_character_counter\"\nimport \"src/decidim/input_autojump\"\nimport \"src/decidim/index\"\nimport \"src/decidim/history\"\nimport \"src/decidim/callout\"\nimport \"src/decidim/clipboard\"\nimport \"src/decidim/append_elements\"\nimport \"src/decidim/user_registrations\"\nimport \"src/decidim/account_form\"\nimport \"src/decidim/data_picker\"\nimport \"src/decidim/dropdowns_menus\"\nimport \"src/decidim/append_redirect_url_to_modals\"\nimport \"src/decidim/form_validator\"\nimport \"src/decidim/ajax_modals\"\nimport \"src/decidim/conferences\"\nimport \"src/decidim/tooltip_keep_on_hover\"\nimport \"src/decidim/diff_mode_dropdown\"\nimport \"src/decidim/conversations\"\nimport \"src/decidim/delayed\"\nimport \"src/decidim/icon\"\nimport \"src/decidim/vizzs\"\nimport \"src/decidim/responsive_horizontal_tabs\"\nimport \"src/decidim/security/selfxss_warning\"\nimport \"src/decidim/session_timeouter\"\nimport \"src/decidim/configuration\"\nimport \"src/decidim/floating_help\"\nimport \"src/decidim/confirm\"\nimport \"src/decidim/comments/comments\"\nimport \"src/decidim/results_listing\"\nimport \"src/decidim/represent_user_group\"\nimport \"src/decidim/impersonation\"\nimport \"src/decidim/start_conversation_dialog\"\nimport \"src/decidim/notifications\"\nimport \"src/decidim/identity_selector_dialog\"\nimport \"src/decidim/gallery\"\n\n// CSS\nimport \"entrypoints/decidim_core.scss\"\n\n// Import from the Rails instance application\nimport \"src/decidim/decidim_application\"\n\n// Images\nrequire.context(\"../images\", true)\n\n// This needs to be loaded after confirm dialog to bind properly\nRails.start()\n\n","/**\n * Since the delete account has a modal to confirm it we need to copy the content of the\n * reason field to the hidden field in the form inside the modal.\n */\n$(() => {\n const $deleteAccountForm = $(\".delete-account\");\n const $deleteAccountModalForm = $(\".delete-account-modal\");\n\n if ($deleteAccountForm.length > 0) {\n const $openModalButton = $(\".open-modal-button\");\n const $modal = $(\"#deleteConfirm\");\n\n $openModalButton.on(\"click\", (event) => {\n try {\n const reasonValue = $deleteAccountForm.find(\"textarea#delete_account_delete_reason\").val();\n $deleteAccountModalForm.find(\"input#delete_account_delete_reason\").val(reasonValue);\n $modal.foundation(\"open\");\n } catch (error) {\n console.error(error); // eslint-disable-line no-console\n }\n\n event.preventDefault();\n event.stopPropagation();\n return false;\n });\n }\n});\n","import \"@zeitiger/appendaround\"\n\n$(() => {\n let $appendableElements = $(\".js-append\");\n $appendableElements.appendAround();\n})\n","/* eslint-disable multiline-ternary, no-ternary */\n\n/*\n *\n * This is used to make sure users are redirected to\n * the expected URL after sign in.\n *\n * When a button or link trigger a login modal we capture\n * the event and inject the URL where the user should\n * be redirected after sign in (the redirect_url param).\n *\n * The code is injected to any form or link in the modal\n * and when the modal is closed we remove the injected\n * code.\n *\n * In order for this to work the button or link must have\n * a data-open attribute with the ID of the modal to open\n * and a data-redirect-url attribute with the URL to redirect\n * the user. If any of this is missing no code will be\n * injected.\n *\n */\n$(() => {\n const removeUrlParameter = (url, parameter) => {\n const urlParts = url.split(\"?\");\n\n if (urlParts.length >= 2) {\n // Get first part, and remove from array\n const urlBase = urlParts.shift();\n\n // Join it back up\n const queryString = urlParts.join(\"?\");\n\n const prefix = `${encodeURIComponent(parameter)}=`;\n const parts = queryString.split(/[&;]/g);\n\n // Reverse iteration as may be destructive\n for (let index = parts.length - 1; index >= 0; index -= 1) {\n // Idiom for string.startsWith\n if (parts[index].lastIndexOf(prefix, 0) !== -1) {\n parts.splice(index, 1);\n }\n }\n\n if (parts.length === 0) {\n return urlBase;\n }\n\n return `${urlBase}?${parts.join(\"&\")}`;\n }\n\n return url;\n }\n\n $(document).on(\"click.zf.trigger\", (event) => {\n const target = `#${$(event.target).data(\"open\")}`;\n const redirectUrl = $(event.target).data(\"redirectUrl\");\n\n if (target && redirectUrl) {\n $(\"\").\n attr(\"id\", \"redirect_url\").\n attr(\"name\", \"redirect_url\").\n attr(\"value\", redirectUrl).\n appendTo(`${target} form`);\n\n $(`${target} a`).attr(\"href\", (index, href) => {\n const querystring = jQuery.param({\"redirect_url\": redirectUrl});\n return href + (href.match(/\\?/) ? \"&\" : \"?\") + querystring;\n });\n }\n });\n\n $(document).on(\"closed.zf.reveal\", (event) => {\n $(\"#redirect_url\", event.target).remove();\n $(\"a\", event.target).attr(\"href\", (index, href) => {\n if (href && href.indexOf(\"redirect_url\") !== -1) {\n return removeUrlParameter(href, \"redirect_url\");\n }\n\n return href;\n });\n });\n});\n","/**\n * Improves the accessibility of the callout messages for screen readers. Not\n * all screen readers would announce the callout alert contents after the page\n * reload without this.\n */\n\n$(() => {\n const $callout = $('.callout[role=\"alert\"]:first');\n if ($callout.length > 0) {\n setTimeout(() => {\n // The content insertion is to try to hint some of the screen readers\n // that the alert content has changed and needs to be announced.\n $callout.attr(\"tabindex\", \"0\").focus().html(`${$callout.html()} `);\n }, 500);\n }\n});\n","import select from \"select\";\n\n/**\n * This provides functionality to add clipboard copy functionality to buttons\n * on the page. The element to be copied from has to be defined for the button\n * using a `data` attribute and the target element has to be a form input.\n *\n * Usage:\n * 1. Create the button:\n * \n *\n * 2. Make sure the target element exists on the page:\n * \n *\n * Options through data attributes:\n * - `data-clipboard-copy` = The jQuery selector for the target input element\n * where text will be copied from.\n * - `data-clipboard-copy-label` = The label that will be shown in the button\n * after a succesful copy.\n * - `data-clipboard-copy-message` = The text that will be announced to screen\n * readers after a successful copy.\n */\n\n// How long the \"copied\" text is shown in the copy element after successful\n// copy.\nconst CLIPBOARD_COPY_TIMEOUT = 5000;\n\n$(() => {\n $(document).on(\"click\", \"[data-clipboard-copy]\", (ev) => {\n const $el = $(ev.target);\n if (!$el.data(\"clipboard-copy\") || $el.data(\"clipboard-copy\").length < 1) {\n return;\n }\n\n const $input = $($el.data(\"clipboard-copy\"));\n if ($input.length < 1 || !$input.is(\"input, textarea, select\")) {\n return;\n }\n\n // Get the available text to clipboard.\n const selectedText = select($input[0]);\n if (!selectedText || selectedText.length < 1) {\n return;\n }\n\n // Move the selected text to clipboard.\n const $temp = $(``).css({\n width: 1,\n height: 1\n });\n $el.after($temp);\n $temp.select();\n\n const copyDone = () => {\n $temp.remove();\n $el.focus();\n };\n try {\n // document.execCommand is deprecated but the Clipboard API is not\n // supported by IE (which unfortunately is still a thing).\n if (!document.execCommand(\"copy\")) {\n return;\n }\n } catch (err) {\n copyDone();\n return;\n }\n copyDone();\n\n // Change the label to indicate the copying was successful.\n const label = $el.data(\"clipboard-copy-label\");\n if (label) {\n let to = $el.data(\"clipboard-copy-label-timeout\");\n if (to) {\n clearTimeout(to);\n }\n\n if (!$el.data(\"clipboard-copy-label-original\")) {\n $el.data(\"clipboard-copy-label-original\", $el.html());\n }\n\n $el.html(label);\n to = setTimeout(() => {\n $el.html($el.data(\"clipboard-copy-label-original\"));\n $el.removeData(\"clipboard-copy-label-original\");\n $el.removeData(\"clipboard-copy-label-timeout\");\n }, CLIPBOARD_COPY_TIMEOUT);\n $el.data(\"clipboard-copy-label-timeout\", to)\n }\n\n // Alert the screen reader what just happened (the link was copied).\n let message = $el.data(\"clipboard-copy-message\");\n if (message) {\n let $msg = $el.data(\"clipboard-message-element\");\n if ($msg) {\n if ($msg.html() === message) {\n // Try to hint the screen reader to re-read the text in the message\n // element.\n message += \" \";\n }\n } else {\n $msg = $('
    ');\n $el.after($msg);\n $el.data(\"clipboard-message-element\", $msg);\n }\n\n // Add the non breaking space always to content to try to force the\n // screen reader to reannounce the added text.\n $msg.html(message);\n }\n });\n});\n","/* eslint-disable no-invalid-this */\n\nimport Foundation from \"foundation-sites\"\n\n$(() => {\n // True if small devices\n if (!Foundation.MediaQuery.atLeast(\"medium\")) {\n const $speaker = $(\".js-conference\")\n\n $speaker.hover(function () {\n const top = $(window).scrollTop() + ($(window).height() * 0.1)\n $(this).find(\".js-bio\").css(\"top\", top)\n })\n }\n});\n","/**\n * Scroll smoothly to the last message automatically when the page is fully loaded.\n * To apply this to a page, at least one element must have the class \"scroll-to-last-message\".\n * @returns {void}\n */\nconst scrollToLastMessage = function() {\n if ($(\".scroll-to-last-message\").length > 0) {\n window.scrollTo({\n top: $(\".conversation-chat:last-child\").offset().top,\n behavior: \"smooth\"\n });\n }\n}\n\n$(document).ready(() => {\n scrollToLastMessage();\n});\n","$(() => {\n const $allDiffViews = $(\".row.diff_view\");\n\n $(document).on(\"click\", \".diff-view-by a.diff-view-mode\", (event) => {\n event.preventDefault();\n const $target = $(event.target)\n let type = \"escaped\";\n const $selected = $target.parents(\".is-dropdown-submenu-parent\").find(\"#diff-view-selected\");\n if ($selected.text().trim() === $target.text().trim()) {\n return;\n }\n\n $selected.text($target.text());\n\n if ($target.attr(\"id\") === \"diff-view-unified\") {\n if ($(\".row.diff_view_split_escaped\").hasClass(\"hide\")) {\n type = \"unescaped\";\n }\n\n $allDiffViews.addClass(\"hide\");\n $(`.row.diff_view_unified_${type}`).removeClass(\"hide\");\n }\n if ($target.attr(\"id\") === \"diff-view-split\") {\n if ($(\".row.diff_view_unified_escaped\").hasClass(\"hide\")) {\n type = \"unescaped\";\n }\n\n $allDiffViews.addClass(\"hide\");\n $(`.row.diff_view_split_${type}`).removeClass(\"hide\");\n }\n })\n\n $(document).on(\"click\", \".diff-view-by a.diff-view-html\", (event) => {\n event.preventDefault();\n const $target = $(event.target);\n $target.parents(\".is-dropdown-submenu-parent\").find(\"#diff-view-selected\").text($target.text());\n const $visibleDiffViewsId = $allDiffViews.not(\".hide\").first().attr(\"id\").split(\"_\").slice(1, -1).join(\"_\");\n const $visibleDiffViews = $allDiffViews.filter(`[id*=${$visibleDiffViewsId}]`)\n\n if ($target.attr(\"id\") === \"escaped-html\") {\n $visibleDiffViews.filter(\"[id$=_unescaped]\").addClass(\"hide\");\n $visibleDiffViews.filter(\"[id$=_escaped]\").removeClass(\"hide\");\n }\n if ($target.attr(\"id\") === \"unescaped-html\") {\n $visibleDiffViews.filter(\"[id$=_escaped]\").addClass(\"hide\");\n $visibleDiffViews.filter(\"[id$=_unescaped]\").removeClass(\"hide\");\n }\n })\n});\n","/* eslint-disable require-jsdoc */\n\n// This will apply some fixes for the Foundation dropdown menu element\n// according to W3C instructions at:\n// https://www.w3.org/TR/wai-aria-practices/examples/menu-button/menu-button-links.html\n//\n// NOTE:\n// This needs to run AFTER Foundation has been initialized because those\n// initializers will affect the drop down menu elements.\nexport default function fixDropdownMenus() {\n $(\"[data-dropdown-menu]\").each((_i, element) => {\n // This will break navigation on macOS VoiceOver app since it will let the\n // user to focus on the li element instead of the
    element where we\n // actually need the focus to be in.\n $(\"li.is-dropdown-submenu-parent\", element).removeAttr(\"aria-haspopup\").removeAttr(\"aria-label\");\n // Foundation marks the wrong role for the submenu elements\n $(\"ul.is-dropdown-submenu\", element).attr(\"role\", \"menu\");\n })\n}\n\n// Ensure the first element is always focused when a dropdown is opened as\n// this would not always happen when using a screen reader. If this is not\n// done, the screen reader will stay quiet when the menu opens which can lead\n// to the blind user not understanding the menu has opened.\n$(() => {\n $(\"[data-dropdown-menu]\").on(\"show.zf.dropdownMenu\", (_i, element) => {\n $(\"li:first > a\", element).focus();\n });\n})\n","/* eslint-disable require-jsdoc */\n\nexport default function updateExternalDomainLinks($target) {\n const whitelist = window.Decidim.config.get(\"external_domain_whitelist\")\n\n if (window.location.pathname === \"/link\") {\n return;\n }\n\n $(\"a\", $target).filter((_i, link) => {\n const $link = $(link);\n if (!$link[0].hasAttribute(\"href\") || $link.parents(\".ql-editor\").length > 0) {\n return false;\n }\n\n const parts = $link.attr(\"href\").match(/^(([a-z]+):)?\\/\\/([^/:]+)(:[0-9]*)?(\\/.*)?$/) || null;\n if (!parts) {\n return false;\n }\n\n const domain = parts[3].replace(/^www\\./, \"\")\n if (whitelist.includes(domain)) {\n return false;\n }\n\n return true;\n }).each((_n, link) => {\n const $link = $(link);\n const externalHref = `/link?external_url=${encodeURIComponent($link.attr(\"href\"))}`;\n $link.attr(\"href\", externalHref)\n $link.attr(\"data-remote\", true)\n });\n}\n","import icon from \"src/decidim/icon\"\n\nconst EXCLUDE_CLASSES = [\n \"card--list__data__icon\",\n \"footer-social__icon\",\n \"logo-cityhall\"\n];\nconst EXCLUDE_REL = [\"license\", \"decidim\"];\n\nconst DEFAULT_MESSAGES = {\n externalLink: \"External link\"\n};\nlet MESSAGES = DEFAULT_MESSAGES;\n\nexport default class ExternalLink {\n static configureMessages(messages) {\n MESSAGES = $.extend(DEFAULT_MESSAGES, messages);\n }\n\n constructor(link) {\n this.$link = link;\n\n this.setup();\n }\n\n setup() {\n if (EXCLUDE_CLASSES.some((cls) => this.$link.hasClass(cls))) {\n return;\n }\n if (\n EXCLUDE_REL.some((rel) => {\n const linkRels = `${this.$link.attr(\"rel\")}`.split(\" \");\n return linkRels.indexOf(rel) > -1;\n })\n ) {\n return;\n }\n\n this.$link.addClass(\"external-link-container\");\n let spacer = \" \";\n if (this.$link.text().trim().length < 1) {\n // Fixes image links extra space\n spacer = \"\";\n }\n this.$link.append(`${spacer}${this.generateElement()}`);\n }\n\n generateElement() {\n let content = `${this.generateIcon()}${this.generateScreenReaderLabel()}`;\n\n return `${content}`;\n }\n\n generateIcon() {\n return icon(\"external-link\");\n }\n\n generateScreenReaderLabel() {\n return `(${MESSAGES.externalLink})`;\n }\n}\n","$(function() {\n if (!window.localStorage) {\n return;\n }\n\n let getDismissedHelpers = () => {\n let serialized = localStorage.getItem(\"dismissedHelpers\");\n if (!serialized) {\n return [];\n }\n\n return serialized.split(\",\");\n };\n\n let addDismissedHelper = (id) => {\n let dismissedHelpers = getDismissedHelpers();\n\n if (!dismissedHelpers.includes(id)) {\n localStorage.setItem(\n \"dismissedHelpers\",\n [...dismissedHelpers, id].join(\",\")\n );\n }\n };\n\n let dismissedHelpers = getDismissedHelpers();\n\n $(\".floating-helper-container\").each((_index, elem) => {\n let id = $(elem).data(\"help-id\");\n\n $(\n \".floating-helper__trigger, .floating-helper__content-close\",\n elem\n ).on(\"click\", (ev) => {\n ev.preventDefault();\n });\n\n if (!dismissedHelpers.includes(id)) {\n $(\".floating-helper\", elem).foundation(\"toggle\");\n $(\".floating-helper__wrapper\", elem).foundation(\"toggle\");\n\n $(\".floating-helper\", elem).on(\"off.zf.toggler\", () => {\n addDismissedHelper(id);\n });\n }\n });\n});\n","const DEFAULT_MESSAGES = {\n correctErrors: \"There are errors on the form, please correct them.\"\n};\nlet MESSAGES = DEFAULT_MESSAGES;\n\nexport default class FormValidator {\n static configureMessages(messages) {\n MESSAGES = $.extend(DEFAULT_MESSAGES, messages);\n }\n\n constructor(form) {\n this.$form = form;\n\n this.$form.on(\"form-error.decidim\", () => {\n this.handleError();\n });\n }\n\n handleError() {\n this.announceFormError();\n\n $(\".is-invalid-input:first\", this.$form).focus();\n }\n\n /**\n * This announces immediately to the screen reader that there are errors on\n * the form that need to be fixed. Does not work on all screen readers but\n * works e.g. in Windows+Firefox+NVDA and macOS+Safari+VoiceOver\n * combinations.\n *\n * @returns {undefined}\n */\n announceFormError() {\n let $announce = $(\".sr-announce\", this.$form);\n if ($announce.length > 0) {\n $announce.remove();\n }\n $announce = $(\"
    \");\n $announce.attr(\"class\", \"sr-announce show-for-sr\");\n $announce.attr(\"aria-live\", \"assertive\");\n this.$form.prepend($announce);\n\n setTimeout(() => {\n $announce.text(MESSAGES.correctErrors);\n }, 100);\n }\n}\n\n$(() => {\n $(\"form\").each((_i, el) => {\n $(el).data(\"form-validator\", new FormValidator($(el)));\n });\n $(document).on(\"forminvalid.zf.abide\", function(_ev, form) {\n form.trigger(\"form-error.decidim\");\n })\n});\n","const DEFAULT_ATTRIBUTES = {\n role: \"img\",\n \"aria-hidden\": \"true\"\n};\n\n/**\n * Generates a Decidim icon element and returns it as a string.\n * @param {String} iconKey - the key of the icon to be generated\n * @param {Object} attributes - extra attributes to define for the icon SVG\n * @param {int} wait - number of milliseconds to wait before executing the function.\n * @private\n * @returns {Void} - Returns nothing.\n */\nexport default function icon(iconKey, attributes = {}) {\n const iconAttributes = $.extend(DEFAULT_ATTRIBUTES, attributes);\n const title = iconAttributes.title || iconAttributes.ariaLabel;\n Reflect.deleteProperty(iconAttributes, \"title\");\n\n const htmlAttributes = {\n \"class\": `icon icon--${iconKey}`\n };\n Object.keys(iconAttributes).forEach((key) => {\n // Convert the key to dash-format.\n const newKey = key.replace(/([A-Z])/g, (ucw) => `-${ucw[0].toLowerCase()}`);\n if (typeof htmlAttributes[key] === \"undefined\") {\n htmlAttributes[newKey] = iconAttributes[key];\n } else {\n htmlAttributes[newKey] = `${htmlAttributes[newKey]} ${iconAttributes[key]}`;\n }\n });\n\n const iconsPath = window.Decidim.config.get(\"icons_path\");\n const elHtml = ``;\n const $el = $(elHtml);\n if (title) {\n $el.prepend(`${title}`);\n } else {\n // This keeps accessibility audit tools happy\n $el.prepend(`${iconKey}`);\n // Force hidden if title is not defined\n htmlAttributes[\"aria-hidden\"] = \"true\";\n }\n $el.attr(htmlAttributes);\n\n return $(\"
    \").append($el).html();\n}\n","/**\n * Makes the #select-identity-button to open a popup for the user to\n * select with which identity he wants to perform an action.\n *\n */\n$(() => {\n let button = $(\"#select-identity-button\"),\n identitiesUrl = null,\n userIdentitiesDialog = $(\"#user-identities\");\n\n if (userIdentitiesDialog.length) {\n identitiesUrl = userIdentitiesDialog.data(\"reveal-identities-url\");\n\n button.click(function () {\n $.ajax(identitiesUrl).done(function(response) {\n userIdentitiesDialog.html(response).foundation(\"open\");\n button.trigger(\"ajax:success\")\n });\n });\n }\n});\n\n\n/**\n * Manage the identity selector for endorsements.\n *\n */\n$(() => {\n $(\"#select-identity-button\").on(\"ajax:success\", function() {\n // once reveal popup has been rendered register event callbacks\n $(\"#user-identities ul.reveal__list li\").each(function(index, elem) {\n let liTag = $(elem)\n liTag.on(\"click\", function() {\n let method = liTag.data(\"method\"),\n urlDataAttr = null;\n if (method === \"POST\") {\n urlDataAttr = \"create_url\";\n } else {\n urlDataAttr = \"destroy_url\";\n }\n $.ajax({\n url: liTag.data(urlDataAttr),\n method: method,\n dataType: \"script\",\n success: function() {\n if (liTag.hasClass(\"selected\")) {\n liTag.removeClass(\"selected\")\n liTag.find(\".icon--circle-check\").addClass(\"invisible\")\n liTag.data(\"method\", \"POST\")\n } else {\n liTag.addClass(\"selected\")\n liTag.find(\".icon--circle-check\").removeClass(\"invisible\")\n liTag.data(\"method\", \"DELETE\")\n }\n }\n })\n })\n });\n });\n})\n","import moment from \"moment\"\n\n$(() => {\n const $impersonationWarning = $(\".impersonation-warning\");\n if ($impersonationWarning.length) {\n const endsAt = moment($impersonationWarning.data(\"session-ends-at\"));\n const exitInterval = setInterval(() => {\n const diff = (endsAt - moment()) / 60000;\n const diffInMinutes = Math.round(diff);\n $impersonationWarning.find(\".minutes\").html(diffInMinutes);\n\n if (diff <= 0) {\n window.location.reload();\n }\n }, 1000);\n\n // Prevent reload when page is already unloading, otherwise it may cause infinite reloads.\n window.addEventListener(\"beforeunload\", () => {\n clearInterval(exitInterval);\n return;\n });\n }\n});\n","/* eslint-disable no-invalid-this */\n\nimport svg4everybody from \"svg4everybody\"\nimport formDatePicker from \"src/decidim/form_datepicker\"\nimport fixDropdownMenus from \"src/decidim/dropdowns_menus\"\nimport createQuillEditor from \"src/decidim/editor\"\nimport Configuration from \"src/decidim/configuration\"\nimport ExternalLink from \"src/decidim/external_link\"\nimport updateExternalDomainLinks from \"src/decidim/external_domain_warning\"\nimport InputCharacterCounter from \"src/decidim/input_character_counter\"\nimport FormValidator from \"src/decidim/form_validator\"\nimport CommentsComponent from \"src/decidim/comments/comments.component\"\nimport DataPicker from \"src/decidim/data_picker\"\nimport FormFilterComponent from \"src/decidim/form_filter\"\nimport addInputEmoji from \"src/decidim/input_emoji\"\n\nwindow.Decidim = window.Decidim || {};\nwindow.Decidim.config = new Configuration()\nwindow.Decidim.ExternalLink = ExternalLink;\nwindow.Decidim.InputCharacterCounter = InputCharacterCounter;\nwindow.Decidim.FormValidator = FormValidator;\nwindow.Decidim.DataPicker = DataPicker;\nwindow.Decidim.CommentsComponent = CommentsComponent;\nwindow.Decidim.addInputEmoji = addInputEmoji;\n\n$(() => {\n window.theDataPicker = new DataPicker($(\".data-picker\"));\n\n $(document).foundation();\n\n fixDropdownMenus();\n\n svg4everybody();\n\n // Prevent data-open buttons e.g. from submitting the underlying form in\n // authorized action buttons.\n $(\"[data-open]\").on(\"click\", (event) => {\n event.preventDefault();\n });\n\n formDatePicker();\n\n $(\".editor-container\").each((_idx, container) => {\n createQuillEditor(container);\n });\n\n $('a[target=\"_blank\"]').each((_i, elem) => {\n const $link = $(elem);\n $link.data(\"external-link\", new ExternalLink($link));\n });\n\n // Mount comments component\n $(\"[data-decidim-comments]\").each((_i, el) => {\n const $el = $(el);\n const comments = new CommentsComponent($el, $el.data(\"decidim-comments\"));\n comments.mountComponent();\n $(el).data(\"comments\", comments);\n });\n\n $(\"form.new_filter\").each(function () {\n const formFilter = new FormFilterComponent($(this));\n\n formFilter.mountComponent();\n })\n\n updateExternalDomainLinks($(\"body\"))\n\n addInputEmoji()\n});\n","$(() => {\n const $inputs = $(\"input[data-autojump]\");\n const DELETE_KEY_CODE = 8;\n\n // Initialize\n $inputs.on(\"keydown\", (event) => {\n // Don't do anything if there is selected text\n if (event.target.selectionStart !== event.target.selectionEnd) {\n return;\n }\n\n if (event.originalEvent.key.length === 1 && event.target.dataset.jumpNext) {\n if (\n event.target.value.length ===\n parseInt(event.target.dataset.maxLength, 10)\n ) {\n event.preventDefault();\n setTimeout(() => {\n const next = $(event.target.dataset.jumpNext);\n next.val(event.originalEvent.key);\n next.trigger(\"focus\");\n }, 1);\n }\n } else if (\n event.originalEvent.keyCode === DELETE_KEY_CODE &&\n event.target.dataset.jumpPrev\n ) {\n if (event.target.value.length === 0) {\n event.preventDefault();\n setTimeout(() => {\n const prev = $(event.target.dataset.jumpPrev);\n prev.val(prev.val().slice(0, -1));\n prev.trigger(\"focus\");\n }, 1);\n }\n }\n });\n});\n","import { EmojiButton } from \"@joeattardi/emoji-button\";\n\n// eslint-disable-next-line require-jsdoc\nexport default function addInputEmoji() {\n const containers = document.querySelectorAll(\"[data-input-emoji]\");\n\n if (containers.length) {\n containers.forEach((elem) => {\n const picker = new EmojiButton({\n position: \"bottom-end\"\n });\n\n const wrapper = document.createElement(\"div\");\n wrapper.className = \"emoji__container\"\n const btnContainer = document.createElement(\"div\");\n btnContainer.className = \"emoji__trigger\"\n btnContainer.innerHTML = ''\n\n elem.parentNode.insertBefore(wrapper, elem);\n wrapper.appendChild(elem);\n wrapper.appendChild(btnContainer);\n\n btnContainer.addEventListener(\"click\", () => picker.togglePicker(btnContainer))\n\n picker.on(\"emoji\", ({ emoji }) => {\n elem.value += ` ${emoji} `\n\n const event = new Event(\"emoji.added\");\n elem.dispatchEvent(event);\n });\n })\n }\n};\n","/* eslint no-unused-vars: 0 */\nimport Tribute from \"src/decidim/vendor/tribute\"\n\n$(() => {\n const $multipleMentionContainer = $(\".js-multiple-mentions\");\n const $multipleMentionRecipientsContainer = $(\".js-multiple-mentions-recipients\");\n const nodatafound = $multipleMentionContainer.attr(\"data-noresults\");\n const directMessageDisabled = $multipleMentionContainer.attr(\"data-direct-messages-disabled\");\n\n const maxRecipients = 9;\n let mentionsCount = 0;\n\n /* eslint no-unused-vars: 0 */\n let deleteRecipient = function(element) {\n // Remove recipient\n element.remove();\n mentionsCount -= 1;\n // In case mentions container disable, enable again\n if ($multipleMentionContainer.prop(\"disabled\")) {\n $multipleMentionContainer.prop(\"disabled\", false);\n }\n };\n\n let noMatchTemplate = null\n if (nodatafound) {\n noMatchTemplate = () => `
  • ${nodatafound}
  • `;\n }\n\n // Returns a function, that, as long as it continues to be invoked, will not\n // be triggered. The function will be called after it stops being called for\n // N milliseconds\n /* eslint no-invalid-this: 0 */\n /* eslint consistent-this: 0 */\n /* eslint prefer-reflect: 0 */\n const debounce = function(callback, wait) {\n let timeout = null;\n return (...args) => {\n const context = this;\n clearTimeout(timeout);\n timeout = setTimeout(() => callback.apply(context, args), wait);\n };\n }\n\n /* eslint no-use-before-define: [\"error\", { \"variables\": false }]*/\n /* eslint no-unused-expressions: 0 */\n let remoteSearch = function(text, cb) {\n let exclusionIds = [];\n $multipleMentionRecipientsContainer.find(\"input[name^='recipient_id']\").each(function(index) {\n exclusionIds.push($(this).val());\n });\n let query = `{users(filter:{wildcard:\"${text}\",excludeIds:[${exclusionIds}]}){id,nickname,name,avatarUrl,__typename,...on UserGroup{membersCount},...on User{directMessagesEnabled}}}`;\n $.post(\"/api\", {query: query}).\n then((response) => {\n let data = response.data.users || {};\n cb(data)\n }).fail(function() {\n cb([])\n }).always(() => {\n // This function runs Tribute every single time you type something\n // So we must evalute DOM properties after each\n const $parent = $(tribute.current.element).parent();\n $parent.addClass(\"is-active\");\n\n // We need to move the container to the wrapper selected\n const $tribute = $parent.find(\".tribute-container\");\n // Remove the inline styles, relative to absolute positioning\n $tribute.removeAttr(\"style\");\n })\n };\n\n // tribute.js docs - http://github.com/zurb/tribute\n /* global Tribute*/\n /* eslint multiline-ternary: 0 */\n /* eslint no-ternary: 0 */\n let tribute = new Tribute({\n autocompleteMode: true,\n // avoid overloading the API if the user types too fast\n values: debounce(function (text, cb) {\n remoteSearch(text, (users) => cb(users));\n }, 250),\n positionMenu: true,\n menuContainer: null,\n menuItemLimit: 10,\n fillAttr: \"nickname\",\n noMatchTemplate: noMatchTemplate,\n lookup: (item) => item.nickname + item.name,\n selectTemplate: function(item) {\n mentionsCount += 1;\n if (mentionsCount >= maxRecipients) {\n $multipleMentionContainer.prop(\"disabled\", true);\n }\n if (typeof item === \"undefined\") {\n return null;\n }\n // Set recipient profile view\n let recipientLabel = `\n \n `;\n\n // Append new recipient to DOM\n if (item.original.__typename === \"UserGroup\" || item.original.directMessagesEnabled === \"true\") {\n $multipleMentionRecipientsContainer.append($(recipientLabel));\n $multipleMentionContainer.val(\"\");\n }\n\n // In order to add tabindex accessibility control to each recipient in list\n $multipleMentionRecipientsContainer.find(\"label\").each(function(index) {\n $(this).find(\"div\").attr(\"tabIndex\", 0).attr(\"aria-controls\", 0).attr(\"aria-label\", \"Close\").attr(\"role\", \"tab\");\n });\n\n // Clean input\n return \"\";\n },\n menuItemTemplate: function(item) {\n let svg = \"\";\n let enabled = item.original.directMessagesEnabled === \"true\";\n if (window.Decidim && item.original.__typename === \"UserGroup\") {\n enabled = true;\n const iconsPath = window.Decidim.config.get(\"icons_path\");\n svg = `${item.original.membersCount}x `;\n }\n let disabledElementClass = enabled ? \"\" : \"disabled-tribute-element\";\n let disabledElementMessage = enabled ? \"\" : ` ${directMessageDisabled}`;\n return `
    \n \"author-avatar\"\n ${item.original.nickname}\n ${item.original.name}\n ${svg}\n ${disabledElementMessage}\n
    `;\n }\n });\n\n let setupEvents = function($element) {\n // DOM manipulation\n $element.on(\"focusin\", (event) => {\n // Set the parent container relative to the current element\n tribute.menuContainer = event.target.parentNode;\n });\n $element.on(\"focusout\", (event) => {\n let $parent = $(event.target).parent();\n\n if ($parent.hasClass(\"is-active\")) {\n $parent.removeClass(\"is-active\");\n }\n });\n $element.on(\"input\", (event) => {\n let $parent = $(event.target).parent();\n\n if (tribute.isActive) {\n // We need to move the container to the wrapper selected\n let $tribute = $(\".tribute-container\");\n $tribute.appendTo($parent);\n // Remove the inline styles, relative to absolute positioning\n $tribute.removeAttr(\"style\");\n // Parent adaptation\n $parent.addClass(\"is-active\");\n } else {\n $parent.removeClass(\"is-active\");\n }\n });\n };\n\n let setupRecipientEvents = function($element) {\n // Allow delete with click on element in recipients list\n $element.on(\"click\", (event) => {\n let $target = event.target.parentNode;\n if ($target.tagName === \"LABEL\") {\n deleteRecipient($target);\n }\n });\n // Allow delete with keypress on element in recipients list\n $element.on(\"keypress\", (event) => {\n let $target = event.target.parentNode;\n if ($target.tagName === \"LABEL\") {\n deleteRecipient($target);\n }\n });\n };\n\n // Call only if we have containter to bind events to\n if ($multipleMentionContainer.length) {\n setupEvents($multipleMentionContainer);\n tribute.attach($multipleMentionContainer);\n }\n\n // Call only if we have containter to bind events to\n if ($multipleMentionRecipientsContainer.length) {\n setupRecipientEvents($multipleMentionRecipientsContainer);\n }\n});\n","$(() => {\n const $notificationsBellIcon = $(\".title-bar .topbar__notifications\");\n const $wrapper = $(\".wrapper\");\n const $section = $wrapper.find(\"#notifications\");\n const $noNotificationsText = $(\".empty-notifications\");\n const $pagination = $wrapper.find(\"ul.pagination\");\n const FADEOUT_TIME = 500;\n\n const anyNotifications = () => $wrapper.find(\".card--widget\").length > 0;\n const emptyNotifications = () => {\n if (!anyNotifications()) {\n $section.remove();\n $noNotificationsText.removeClass(\"hide\");\n }\n };\n\n $section.on(\"click\", \".mark-as-read-button\", (event) => {\n const $item = $(event.target).parents(\".card--widget\");\n $item.fadeOut(FADEOUT_TIME, () => {\n $item.remove();\n emptyNotifications();\n });\n });\n\n $wrapper.on(\"click\", \".mark-all-as-read-button\", () => {\n $section.fadeOut(FADEOUT_TIME, () => {\n $pagination.remove();\n $notificationsBellIcon.removeClass(\"is-active\");\n $wrapper.find(\".card--widget\").remove();\n emptyNotifications();\n });\n });\n\n emptyNotifications();\n});\n","$(() => {\n const $checkbox = $(\".represent-user-group\").find(\"input#user_group\");\n const $userGroupFields = $(\".user-group-fields\");\n\n $checkbox.click(() => {\n const $select = $userGroupFields.find(\"select\");\n\n if (!$select.val()) {\n $userGroupFields.toggle();\n }\n\n if ($userGroupFields.is(\":visible\")) {\n $checkbox.prop(\"checked\", true);\n } else {\n $checkbox.prop(\"checked\", false);\n }\n });\n});\n","$(() => {\n const $responsiveTabBlock = $(\".responsive-tab-block\");\n\n $responsiveTabBlock.click((event) => {\n if (event.target.closest(\".is-active\") !== null) {\n event.preventDefault();\n if (window.innerWidth <= 639) {\n $responsiveTabBlock.toggleClass(\"expanded\");\n }\n }\n });\n});\n","import { pushState, registerCallback } from \"src/decidim/history\"\n\nconst initializeListingOptionsMenu = (options) => {\n $(document).on(\"click\", `${options.containerSelector} a`, (event) => {\n const $target = $(event.target);\n\n $target.parents(\".menu\").find(\"a:first\").text($target.text());\n\n pushState($target.attr(\"href\"));\n })\n\n registerCallback(options.callbackName, () => {\n const url = window.location.toString();\n const match = url.match(/${options.urlParameter}=([^&]*)/);\n const $targetMenu = $(`${options.containerSelector} .menu`);\n let value = $targetMenu.find(\".menu a:first\").data(options.dataAttribute);\n\n if (match) {\n value = match[1];\n }\n\n const linkText = $targetMenu.find(`.menu a[data-${options.dataAttribute}=\"${value}\"]`).text();\n\n $targetMenu.find(\"a:first\").text(linkText);\n });\n};\n\n$(() => {\n initializeListingOptionsMenu({\n containerSelector: \".order-by\",\n callbackName: \"orders\",\n urlParameter: \"order\",\n dataAttribute: \"order\"\n });\n initializeListingOptionsMenu({\n containerSelector: \".results-per-page\",\n callbackName: \"results_per_page\",\n urlParameter: \"per_page\",\n dataAttribute: \"per-page-option\"\n });\n});\n","/* eslint-disable no-console */\n\n$(() => {\n if (!console) {\n return;\n }\n\n const allMessages = window.Decidim.config.get(\"messages\");\n if (!allMessages) {\n return;\n }\n const messages = allMessages.selfxssWarning;\n\n console.log(`%c${messages.title}`, \"color:#f00;font-weight:bold;font-size:50px;\");\n console.log(`%c${messages.description}`, \"font-size:24px;\");\n});\n","$(() => {\n let addUsersConversationDialog = $(\"#user-conversations-add-modal\"),\n button = $(\"#start-conversation-dialog-button\");\n\n /* eslint no-unused-vars: 0 */\n if (addUsersConversationDialog.length) {\n let refreshUrl = addUsersConversationDialog.data(\"refresh-url\");\n\n button.click(function () {\n addUsersConversationDialog.foundation(\"open\");\n });\n }\n});\n","/* eslint-disable no-invalid-this */\n\n$(() => {\n\n // Foundation requires plugins to be initializated\n setTimeout(function() {\n\n const $tooltips = $(\".tooltip\")\n\n $tooltips.\n on(\"mouseover\", function() {\n $(`[data-keep-on-hover='true'][data-toggle='${this.id}']`).foundation(\"show\");\n }).\n on(\"mouseout\", function() {\n $(`[data-keep-on-hover='true'][data-toggle='${this.id}']`).foundation(\"hide\");\n })\n }, 0);\n});\n","$(() => {\n const $userRegistrationForm = $(\"#register-form\");\n const $userGroupFields = $userRegistrationForm.find(\".user-group-fields\");\n const inputSelector = 'input[name=\"user[sign_up_as]\"]';\n const newsletterSelector = 'input[type=\"checkbox\"][name=\"user[newsletter]\"]';\n const $newsletterModal = $(\"#sign-up-newsletter-modal\");\n\n\n const setGroupFieldsVisibility = (value) => {\n if (value === \"user\") {\n $userGroupFields.hide();\n } else {\n $userGroupFields.show();\n }\n }\n\n const checkNewsletter = (check) => {\n $userRegistrationForm.find(newsletterSelector).prop(\"checked\", check);\n $newsletterModal.data(\"continue\", true);\n $newsletterModal.foundation(\"close\");\n $userRegistrationForm.submit();\n }\n\n setGroupFieldsVisibility($userRegistrationForm.find(`${inputSelector}:checked`).val());\n\n $userRegistrationForm.on(\"change\", inputSelector, (event) => {\n const value = event.target.value;\n\n setGroupFieldsVisibility(value);\n });\n\n $userRegistrationForm.on(\"submit\", (event) => {\n const newsletterChecked = $userRegistrationForm.find(newsletterSelector);\n if (!$newsletterModal.data(\"continue\")) {\n if (!newsletterChecked.prop(\"checked\")) {\n event.preventDefault();\n $newsletterModal.foundation(\"open\");\n }\n }\n });\n\n $newsletterModal.find(\".check-newsletter\").on(\"click\", (event) => {\n checkNewsletter($(event.target).data(\"check\"));\n });\n});\n","/* eslint-disable */\n\n/*! modernizr 3.3.1 (Custom Build) | MIT *\n * https://modernizr.com/download/?-setclasses !*/\n!function(n,e,s){function o(n,e){return typeof n===e}function a(){var n,e,s,a,i,l,r;for(var c in f)if(f.hasOwnProperty(c)){if(n=[],e=f[c],e.name&&(n.push(e.name.toLowerCase()),e.options&&e.options.aliases&&e.options.aliases.length))for(s=0;s 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar chunkIds = deferred[i][0];\n\t\tvar fn = deferred[i][1];\n\t\tvar priority = deferred[i][2];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every(function(key) { return __webpack_require__.O[key](chunkIds[j]); })) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = function(module) {\n\tvar getter = module && module.__esModule ?\n\t\tfunction() { return module['default']; } :\n\t\tfunction() { return module; };\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// define __esModule on exports\n__webpack_require__.r = function(exports) {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.nmd = function(module) {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","__webpack_require__.p = \"/decidim-packs/\";","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t\"decidim_core\": 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = function(chunkId) { return installedChunks[chunkId] === 0; };\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = function(parentChunkLoadingFunction, data) {\n\tvar chunkIds = data[0];\n\tvar moreModules = data[1];\n\tvar runtime = data[2];\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some(function(id) { return installedChunks[id] !== 0; })) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunkapp\"] = self[\"webpackChunkapp\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [\"vendors-node_modules_jquery_dist_jquery-exposed_js\",\"vendors-node_modules_bootstrap-tagsinput_dist_bootstrap-tagsinput_js-node_modules_rails_ujs_l-ee688c\",\"vendors-node_modules_d3_index_js\",\"vendors-node_modules_foundation-datepicker_js_locales_foundation-datepicker_ar_js-node_module-679306\",\"vendors-node_modules_joeattardi_emoji-button_dist_index_js-node_modules_zeitiger_appendaround-3ddad2\",\"_rbenv_versions_2_7_3_lib_ruby_gems_2_7_0_bundler_gems_decidim-04ca5ebdba87_decidim-core_app_-378ce2\",\"_rbenv_versions_2_7_3_lib_ruby_gems_2_7_0_bundler_gems_decidim-04ca5ebdba87_decidim-core_app_-63837c\",\"_rbenv_versions_2_7_3_lib_ruby_gems_2_7_0_bundler_gems_decidim-04ca5ebdba87_decidim-core_app_-5fdcc0\",\"_rbenv_versions_2_7_3_lib_ruby_gems_2_7_0_bundler_gems_decidim-04ca5ebdba87_decidim-core_app_-c47082\"], function() { return __webpack_require__(\"../../../../.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/bundler/gems/decidim-04ca5ebdba87/decidim-core/app/packs/entrypoints/decidim_core.js\"); })\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n",""],"names":[],"sourceRoot":""} \ No newline at end of file diff --git a/spec/factories.rb b/spec/factories.rb index 16fc8f0..0e6d87b 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -1,2 +1,3 @@ # frozen_string_literal: true + require "decidim/core/test/factories" diff --git a/spec/features/feder_footer_spec.rb b/spec/features/feder_footer_spec.rb index 297a654..a56e3c5 100644 --- a/spec/features/feder_footer_spec.rb +++ b/spec/features/feder_footer_spec.rb @@ -2,7 +2,8 @@ require "rails_helper" -feature "new registration" do +# rubocop:disable RSpec/DescribeClass +describe "new registration" do let(:organization) { create :organization } before do @@ -10,13 +11,14 @@ Capybara.app_host = app_host end - scenario "display feder logo on footer on homepage" do - visit '/' + it "display feder logo on footer on homepage" do + visit "/" expect(page).to have_content "Fons Europeu de Desenvolupament Regional" end - scenario "display feder logo on footer on user registration page" do - visit '/users/sign_up' + it "display feder logo on footer on user registration page" do + visit "/users/sign_up" expect(page).to have_content "Fons Europeu de Desenvolupament Regional" end -end \ No newline at end of file +end +# rubocop:enable RSpec/DescribeClass diff --git a/spec/lib/overrides_spec.rb b/spec/lib/overrides_spec.rb index 65a9e0c..bfa9706 100644 --- a/spec/lib/overrides_spec.rb +++ b/spec/lib/overrides_spec.rb @@ -22,7 +22,7 @@ describe "Overriden files", type: :view do checksums.each do |item| - spec = ::Gem::Specification.find_by_name(item[:package]) + spec = ::Gem::Specification.find_by(name: item[:package]) item[:files].each do |file, signature| it "#{spec.gem_dir}#{file} matches checksum" do diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 4bb5fad..4002461 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -1,12 +1,14 @@ +# frozen_string_literal: true + # This file is copied to spec/ when you run 'rails generate rspec:install' -require 'spec_helper' -ENV['RAILS_ENV'] ||= 'test' -require File.expand_path('../config/environment', __dir__) +require "spec_helper" +ENV["RAILS_ENV"] ||= "test" +require File.expand_path("../config/environment", __dir__) # Prevent database truncation if the environment is production abort("The Rails environment is running in production mode!") if Rails.env.production? -require 'rspec/rails' +require "rspec/rails" -require 'decidim/dev' +require "decidim/dev" Decidim::Dev.dummy_app_path = File.expand_path(File.join(__dir__, "..")) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6236795..49d5f28 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This file was generated by the `rails generate rspec:install` command. Conventionally, all # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. # The generated `.rspec` file contains `--require spec_helper` which will cause @@ -44,42 +46,42 @@ # triggering implicit auto-inclusion in groups with matching metadata. config.shared_context_metadata_behavior = :apply_to_host_groups -# # The settings below are suggested to provide a good initial experience -# # with RSpec, but feel free to customize to your heart's content. + # # The settings below are suggested to provide a good initial experience + # # with RSpec, but feel free to customize to your heart's content. -# # This allows you to limit a spec run to individual examples or groups -# # you care about by tagging them with `:focus` metadata. When nothing -# # is tagged with `:focus`, all examples get run. RSpec also provides -# # aliases for `it`, `describe`, and `context` that include `:focus` -# # metadata: `fit`, `fdescribe` and `fcontext`, respectively. -# config.filter_run_when_matching :focus + # # This allows you to limit a spec run to individual examples or groups + # # you care about by tagging them with `:focus` metadata. When nothing + # # is tagged with `:focus`, all examples get run. RSpec also provides + # # aliases for `it`, `describe`, and `context` that include `:focus` + # # metadata: `fit`, `fdescribe` and `fcontext`, respectively. + # config.filter_run_when_matching :focus -# # Allows RSpec to persist some state between runs in order to support -# # the `--only-failures` and `--next-failure` CLI options. We recommend -# # you configure your source control system to ignore this file. -# config.example_status_persistence_file_path = "spec/examples.txt" + # # Allows RSpec to persist some state between runs in order to support + # # the `--only-failures` and `--next-failure` CLI options. We recommend + # # you configure your source control system to ignore this file. + # config.example_status_persistence_file_path = "spec/examples.txt" -# # Limits the available syntax to the non-monkey patched syntax that is -# # recommended. For more details, see: -# # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ -# # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ -# # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode -# config.disable_monkey_patching! + # # Limits the available syntax to the non-monkey patched syntax that is + # # recommended. For more details, see: + # # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ + # # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ + # # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode + # config.disable_monkey_patching! -# # Many RSpec users commonly either run the entire suite or an individual -# # file, and it's useful to allow more verbose output when running an -# # individual spec file. -# if config.files_to_run.one? -# # Use the documentation formatter for detailed output, -# # unless a formatter has already been configured -# # (e.g. via a command-line flag). -# config.default_formatter = "doc" -# end + # # Many RSpec users commonly either run the entire suite or an individual + # # file, and it's useful to allow more verbose output when running an + # # individual spec file. + # if config.files_to_run.one? + # # Use the documentation formatter for detailed output, + # # unless a formatter has already been configured + # # (e.g. via a command-line flag). + # config.default_formatter = "doc" + # end -# # Print the 10 slowest examples and example groups at the -# # end of the spec run, to help surface which specs are running -# # particularly slow. -# config.profile_examples = 10 + # # Print the 10 slowest examples and example groups at the + # # end of the spec run, to help surface which specs are running + # # particularly slow. + # config.profile_examples = 10 # Run specs in random order to surface order dependencies. If you find an # order dependency and want to debug it, you can fix the order by providing